blob: 202b031bca62ba2c1ba9549a9744222dd5dcdab4 [file] [log] [blame]
Ian Rogers57b86d42012-03-27 16:05:41 -07001/*
Elliott Hughes0f3c5532012-03-30 14:51:51 -07002 * Copyright (C) 2012 The Android Open Source Project
Ian Rogers57b86d42012-03-27 16:05:41 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
David Sehr0225f8e2018-01-31 08:52:24 +000017#include "art_method-inl.h"
Ian Rogers57b86d42012-03-27 16:05:41 -070018#include "callee_save_frame.h"
Vladimir Marko175e7862018-03-27 09:03:13 +000019#include "dex/code_item_accessors-inl.h"
20#include "dex/dex_instruction-inl.h"
Ian Rogersa9a82542013-10-04 11:17:26 -070021#include "common_throws.h"
Ian Rogersa9a82542013-10-04 11:17:26 -070022#include "mirror/object-inl.h"
Vladimir Marko175e7862018-03-27 09:03:13 +000023#include "nth_caller_visitor.h"
Ian Rogers57b86d42012-03-27 16:05:41 -070024#include "thread.h"
Ian Rogers120f1c72012-09-28 17:17:10 -070025#include "well_known_classes.h"
Ian Rogers57b86d42012-03-27 16:05:41 -070026
27namespace art {
28
29// Deliver an exception that's pending on thread helping set up a callee save frame on the way.
Andreas Gampe65b798e2015-04-06 09:35:22 -070030extern "C" NO_RETURN void artDeliverPendingExceptionFromCode(Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070031 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers1d8cdbc2014-09-22 22:51:09 -070032 ScopedQuickEntrypointChecks sqec(self);
33 self->QuickDeliverException();
Ian Rogers57b86d42012-03-27 16:05:41 -070034}
35
Alex Lightdb01a092017-04-03 15:39:55 -070036extern "C" NO_RETURN uint64_t artInvokeObsoleteMethod(ArtMethod* method, Thread* self)
37 REQUIRES_SHARED(Locks::mutator_lock_) {
38 DCHECK(method->IsObsolete());
39 ScopedQuickEntrypointChecks sqec(self);
40 ThrowInternalError("Attempting to invoke obsolete version of '%s'.",
41 method->PrettyMethod().c_str());
42 self->QuickDeliverException();
43}
44
Vladimir Marko87f3fcb2016-04-28 15:52:11 +010045// Called by generated code to throw an exception.
Andreas Gampe65b798e2015-04-06 09:35:22 -070046extern "C" NO_RETURN void artDeliverExceptionFromCode(mirror::Throwable* exception, Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070047 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers57b86d42012-03-27 16:05:41 -070048 /*
Mathieu Chartier2cebb242015-04-21 16:50:40 -070049 * exception may be null, in which case this routine should
Ian Rogers57b86d42012-03-27 16:05:41 -070050 * throw NPE. NOTE: this is a convenience for generated code,
51 * which previously did the null check inline and constructed
Mathieu Chartier2cebb242015-04-21 16:50:40 -070052 * and threw a NPE if null. This routine responsible for setting
Ian Rogers57b86d42012-03-27 16:05:41 -070053 * exception_ in thread and delivering the exception.
54 */
Ian Rogers1d8cdbc2014-09-22 22:51:09 -070055 ScopedQuickEntrypointChecks sqec(self);
Ian Rogers1d8cdbc2014-09-22 22:51:09 -070056 if (exception == nullptr) {
Nicolas Geoffray635967b2019-08-07 10:15:39 +010057 self->ThrowNewException("Ljava/lang/NullPointerException;", nullptr);
Ian Rogers62d6c772013-02-27 08:32:07 -080058 } else {
Nicolas Geoffray14691c52015-03-05 10:40:17 +000059 self->SetException(exception);
Ian Rogers62d6c772013-02-27 08:32:07 -080060 }
61 self->QuickDeliverException();
Ian Rogers57b86d42012-03-27 16:05:41 -070062}
63
Vladimir Marko87f3fcb2016-04-28 15:52:11 +010064// Called by generated code to throw a NPE exception.
Andreas Gampe65b798e2015-04-06 09:35:22 -070065extern "C" NO_RETURN void artThrowNullPointerExceptionFromCode(Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070066 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers1d8cdbc2014-09-22 22:51:09 -070067 ScopedQuickEntrypointChecks sqec(self);
Nicolas Geoffraye8e11272016-06-28 18:08:46 +010068 // We come from an explicit check in the generated code. This path is triggered
69 // only if the object is indeed null.
Andreas Gampe98ea9d92018-10-19 14:06:15 -070070 ThrowNullPointerExceptionFromDexPC(/* check_address= */ false, 0U);
Nicolas Geoffraye8e11272016-06-28 18:08:46 +010071 self->QuickDeliverException();
72}
73
74// Installed by a signal handler to throw a NPE exception.
75extern "C" NO_RETURN void artThrowNullPointerExceptionFromSignal(uintptr_t addr, Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070076 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffraye8e11272016-06-28 18:08:46 +010077 ScopedQuickEntrypointChecks sqec(self);
Andreas Gampe98ea9d92018-10-19 14:06:15 -070078 ThrowNullPointerExceptionFromDexPC(/* check_address= */ true, addr);
jeffhao94d6df42012-11-26 16:02:12 -080079 self->QuickDeliverException();
Ian Rogers57b86d42012-03-27 16:05:41 -070080}
81
Vladimir Marko87f3fcb2016-04-28 15:52:11 +010082// Called by generated code to throw an arithmetic divide by zero exception.
Andreas Gampe65b798e2015-04-06 09:35:22 -070083extern "C" NO_RETURN void artThrowDivZeroFromCode(Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070084 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers1d8cdbc2014-09-22 22:51:09 -070085 ScopedQuickEntrypointChecks sqec(self);
Sebastien Hertz0a3b8632013-06-26 11:16:01 +020086 ThrowArithmeticExceptionDivideByZero();
Ian Rogers62d6c772013-02-27 08:32:07 -080087 self->QuickDeliverException();
Ian Rogers57b86d42012-03-27 16:05:41 -070088}
89
Vladimir Marko87f3fcb2016-04-28 15:52:11 +010090// Called by generated code to throw an array index out of bounds exception.
Andreas Gampe65b798e2015-04-06 09:35:22 -070091extern "C" NO_RETURN void artThrowArrayBoundsFromCode(int index, int length, Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070092 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers1d8cdbc2014-09-22 22:51:09 -070093 ScopedQuickEntrypointChecks sqec(self);
Ian Rogers62d6c772013-02-27 08:32:07 -080094 ThrowArrayIndexOutOfBoundsException(index, length);
95 self->QuickDeliverException();
Ian Rogers57b86d42012-03-27 16:05:41 -070096}
97
Vladimir Marko87f3fcb2016-04-28 15:52:11 +010098// Called by generated code to throw a string index out of bounds exception.
99extern "C" NO_RETURN void artThrowStringBoundsFromCode(int index, int length, Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700100 REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Marko87f3fcb2016-04-28 15:52:11 +0100101 ScopedQuickEntrypointChecks sqec(self);
102 ThrowStringIndexOutOfBoundsException(index, length);
103 self->QuickDeliverException();
104}
105
Andreas Gampe65b798e2015-04-06 09:35:22 -0700106extern "C" NO_RETURN void artThrowStackOverflowFromCode(Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700107 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers1d8cdbc2014-09-22 22:51:09 -0700108 ScopedQuickEntrypointChecks sqec(self);
jeffhaod7521322012-11-21 15:38:24 -0800109 ThrowStackOverflowError(self);
jeffhao94d6df42012-11-26 16:02:12 -0800110 self->QuickDeliverException();
Ian Rogers57b86d42012-03-27 16:05:41 -0700111}
112
Andreas Gampe65b798e2015-04-06 09:35:22 -0700113extern "C" NO_RETURN void artThrowClassCastException(mirror::Class* dest_type,
114 mirror::Class* src_type,
115 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700116 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers1d8cdbc2014-09-22 22:51:09 -0700117 ScopedQuickEntrypointChecks sqec(self);
Vladimir Marko175e7862018-03-27 09:03:13 +0000118 if (dest_type == nullptr) {
119 // Find the target class for check cast using the bitstring check (dest_type == null).
120 NthCallerVisitor visitor(self, 0u);
121 visitor.WalkStack();
122 DCHECK(visitor.caller != nullptr);
123 uint32_t dex_pc = visitor.GetDexPc();
124 CodeItemDataAccessor accessor(*visitor.caller->GetDexFile(), visitor.caller->GetCodeItem());
125 const Instruction& check_cast = accessor.InstructionAt(dex_pc);
126 DCHECK_EQ(check_cast.Opcode(), Instruction::CHECK_CAST);
127 dex::TypeIndex type_index(check_cast.VRegB_21c());
128 ClassLinker* linker = Runtime::Current()->GetClassLinker();
129 dest_type = linker->LookupResolvedType(type_index, visitor.caller).Ptr();
130 CHECK(dest_type != nullptr) << "Target class should have been previously resolved: "
131 << visitor.caller->GetDexFile()->PrettyType(type_index);
132 CHECK(!dest_type->IsAssignableFrom(src_type))
133 << " " << std::hex << dest_type->PrettyDescriptor() << ";" << dest_type->Depth()
134 << "/" << dest_type->GetField32(mirror::Class::StatusOffset())
135 << " <: " << src_type->PrettyDescriptor() << ";" << src_type->Depth()
136 << "/" << src_type->GetField32(mirror::Class::StatusOffset());
137 }
Ian Rogers1d8cdbc2014-09-22 22:51:09 -0700138 DCHECK(!dest_type->IsAssignableFrom(src_type));
Ian Rogersa9a82542013-10-04 11:17:26 -0700139 ThrowClassCastException(dest_type, src_type);
140 self->QuickDeliverException();
141}
142
Mathieu Chartierb99f4d62016-11-07 16:17:26 -0800143extern "C" NO_RETURN void artThrowClassCastExceptionForObject(mirror::Object* obj,
144 mirror::Class* dest_type,
145 Thread* self)
146 REQUIRES_SHARED(Locks::mutator_lock_) {
147 DCHECK(obj != nullptr);
148 artThrowClassCastException(dest_type, obj->GetClass(), self);
149}
150
Andreas Gampe65b798e2015-04-06 09:35:22 -0700151extern "C" NO_RETURN void artThrowArrayStoreException(mirror::Object* array, mirror::Object* value,
152 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700153 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers1d8cdbc2014-09-22 22:51:09 -0700154 ScopedQuickEntrypointChecks sqec(self);
Ian Rogersa9a82542013-10-04 11:17:26 -0700155 ThrowArrayStoreException(value->GetClass(), array->GetClass());
156 self->QuickDeliverException();
157}
158
Ian Rogers57b86d42012-03-27 16:05:41 -0700159} // namespace art