blob: f6225ed698804b57f3924c97f8a2d05e72b345b5 [file] [log] [blame]
Shih-wei Liao2d831012011-09-28 22:06:53 -07001/*
Elliott Hughes0f3c5532012-03-30 14:51:51 -07002 * Copyright (C) 2012 The Android Open Source Project
Shih-wei Liao2d831012011-09-28 22:06:53 -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
17#include "runtime_support.h"
18
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080019#include "class_linker-inl.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070020#include "dex_file-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080021#include "gc/card_table-inl.h"
22#include "mirror/abstract_method-inl.h"
23#include "mirror/class-inl.h"
24#include "mirror/field-inl.h"
25#include "mirror/object-inl.h"
26#include "mirror/object_array-inl.h"
27#include "mirror/proxy.h"
Ian Rogersaf6e67a2013-01-16 08:38:37 -080028#include "reflection.h"
29#include "scoped_thread_state_change.h"
TDYa1275bb86012012-04-11 05:57:28 -070030#include "ScopedLocalRef.h"
Elliott Hugheseac76672012-05-24 21:56:51 -070031#include "well_known_classes.h"
TDYa1275bb86012012-04-11 05:57:28 -070032
jeffhao41005dd2012-05-09 17:58:52 -070033double art_l2d(int64_t l) {
Elliott Hughes74847412012-06-20 18:10:21 -070034 return static_cast<double>(l);
jeffhao41005dd2012-05-09 17:58:52 -070035}
36
37float art_l2f(int64_t l) {
Elliott Hughes74847412012-06-20 18:10:21 -070038 return static_cast<float>(l);
jeffhao41005dd2012-05-09 17:58:52 -070039}
Shih-wei Liao2d831012011-09-28 22:06:53 -070040
Ian Rogers776ac1f2012-04-13 23:36:36 -070041/*
42 * Float/double conversion requires clamping to min and max of integer form. If
43 * target doesn't support this normally, use these.
44 */
jeffhao41005dd2012-05-09 17:58:52 -070045int64_t art_d2l(double d) {
Elliott Hughes74847412012-06-20 18:10:21 -070046 static const double kMaxLong = static_cast<double>(static_cast<int64_t>(0x7fffffffffffffffULL));
47 static const double kMinLong = static_cast<double>(static_cast<int64_t>(0x8000000000000000ULL));
Ian Rogers776ac1f2012-04-13 23:36:36 -070048 if (d >= kMaxLong) {
Logan Chien008fa512012-06-22 08:09:57 -070049 return static_cast<int64_t>(0x7fffffffffffffffULL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070050 } else if (d <= kMinLong) {
Logan Chien008fa512012-06-22 08:09:57 -070051 return static_cast<int64_t>(0x8000000000000000ULL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070052 } else if (d != d) { // NaN case
53 return 0;
54 } else {
Elliott Hughes74847412012-06-20 18:10:21 -070055 return static_cast<int64_t>(d);
Ian Rogers776ac1f2012-04-13 23:36:36 -070056 }
57}
58
jeffhao41005dd2012-05-09 17:58:52 -070059int64_t art_f2l(float f) {
Elliott Hughes74847412012-06-20 18:10:21 -070060 static const float kMaxLong = static_cast<float>(static_cast<int64_t>(0x7fffffffffffffffULL));
61 static const float kMinLong = static_cast<float>(static_cast<int64_t>(0x8000000000000000ULL));
Ian Rogers776ac1f2012-04-13 23:36:36 -070062 if (f >= kMaxLong) {
Logan Chien008fa512012-06-22 08:09:57 -070063 return static_cast<int64_t>(0x7fffffffffffffffULL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070064 } else if (f <= kMinLong) {
Logan Chien008fa512012-06-22 08:09:57 -070065 return static_cast<int64_t>(0x8000000000000000ULL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070066 } else if (f != f) { // NaN case
67 return 0;
68 } else {
Elliott Hughes74847412012-06-20 18:10:21 -070069 return static_cast<int64_t>(f);
Ian Rogers776ac1f2012-04-13 23:36:36 -070070 }
71}
72
jeffhao41005dd2012-05-09 17:58:52 -070073int32_t art_d2i(double d) {
Logan Chien008fa512012-06-22 08:09:57 -070074 static const double kMaxInt = static_cast<double>(static_cast<int32_t>(0x7fffffffUL));
75 static const double kMinInt = static_cast<double>(static_cast<int32_t>(0x80000000UL));
Ian Rogers776ac1f2012-04-13 23:36:36 -070076 if (d >= kMaxInt) {
Logan Chien008fa512012-06-22 08:09:57 -070077 return static_cast<int32_t>(0x7fffffffUL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070078 } else if (d <= kMinInt) {
Logan Chien008fa512012-06-22 08:09:57 -070079 return static_cast<int32_t>(0x80000000UL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070080 } else if (d != d) { // NaN case
81 return 0;
82 } else {
Elliott Hughes74847412012-06-20 18:10:21 -070083 return static_cast<int32_t>(d);
Ian Rogers776ac1f2012-04-13 23:36:36 -070084 }
85}
86
jeffhao41005dd2012-05-09 17:58:52 -070087int32_t art_f2i(float f) {
Logan Chien008fa512012-06-22 08:09:57 -070088 static const float kMaxInt = static_cast<float>(static_cast<int32_t>(0x7fffffffUL));
89 static const float kMinInt = static_cast<float>(static_cast<int32_t>(0x80000000UL));
Ian Rogers776ac1f2012-04-13 23:36:36 -070090 if (f >= kMaxInt) {
Logan Chien008fa512012-06-22 08:09:57 -070091 return static_cast<int32_t>(0x7fffffffUL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070092 } else if (f <= kMinInt) {
Logan Chien008fa512012-06-22 08:09:57 -070093 return static_cast<int32_t>(0x80000000UL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070094 } else if (f != f) { // NaN case
95 return 0;
96 } else {
Elliott Hughes74847412012-06-20 18:10:21 -070097 return static_cast<int32_t>(f);
Ian Rogers776ac1f2012-04-13 23:36:36 -070098 }
99}
100
jeffhao41005dd2012-05-09 17:58:52 -0700101namespace art {
102
Ian Rogers57b86d42012-03-27 16:05:41 -0700103// Helper function to allocate array for FILLED_NEW_ARRAY.
Ian Rogers62d6c772013-02-27 08:32:07 -0800104mirror::Array* CheckAndAllocArrayFromCode(uint32_t type_idx, mirror::AbstractMethod* referrer,
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800105 int32_t component_count, Thread* self,
106 bool access_check) {
Ian Rogers57b86d42012-03-27 16:05:41 -0700107 if (UNLIKELY(component_count < 0)) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800108 ThrowNegativeArraySizeException(component_count);
Ian Rogers57b86d42012-03-27 16:05:41 -0700109 return NULL; // Failure
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700110 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800111 mirror::Class* klass = referrer->GetDexCacheResolvedTypes()->Get(type_idx);
Ian Rogers57b86d42012-03-27 16:05:41 -0700112 if (UNLIKELY(klass == NULL)) { // Not in dex cache so try to resolve
Ian Rogers62d6c772013-02-27 08:32:07 -0800113 klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, referrer);
Ian Rogers57b86d42012-03-27 16:05:41 -0700114 if (klass == NULL) { // Error
Ian Rogers50b35e22012-10-04 10:09:15 -0700115 DCHECK(self->IsExceptionPending());
Ian Rogers57b86d42012-03-27 16:05:41 -0700116 return NULL; // Failure
Ian Rogers19846512012-02-24 11:42:47 -0800117 }
Ian Rogersea2a11d2011-10-11 16:48:51 -0700118 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700119 if (UNLIKELY(klass->IsPrimitive() && !klass->IsPrimitiveInt())) {
120 if (klass->IsPrimitiveLong() || klass->IsPrimitiveDouble()) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800121 ThrowRuntimeException("Bad filled array request for type %s",
122 PrettyDescriptor(klass).c_str());
Ian Rogers573db4a2011-12-13 15:30:50 -0800123 } else {
Ian Rogers62d6c772013-02-27 08:32:07 -0800124 ThrowLocation throw_location = self->GetCurrentLocationForThrow();
125 DCHECK(throw_location.GetMethod() == referrer);
126 self->ThrowNewExceptionF(throw_location, "Ljava/lang/InternalError;",
Ian Rogers50b35e22012-10-04 10:09:15 -0700127 "Found type %s; filled-new-array not implemented for anything but \'int\'",
128 PrettyDescriptor(klass).c_str());
Ian Rogers573db4a2011-12-13 15:30:50 -0800129 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700130 return NULL; // Failure
Ian Rogersad25ac52011-10-04 19:13:33 -0700131 } else {
Ian Rogers57b86d42012-03-27 16:05:41 -0700132 if (access_check) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800133 mirror::Class* referrer_klass = referrer->GetDeclaringClass();
134 if (UNLIKELY(!referrer_klass->CanAccess(klass))) {
135 ThrowIllegalAccessErrorClass(referrer_klass, klass);
Ian Rogers57b86d42012-03-27 16:05:41 -0700136 return NULL; // Failure
137 }
Ian Rogers60db5ab2012-02-20 17:02:00 -0800138 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700139 DCHECK(klass->IsArrayClass()) << PrettyClass(klass);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800140 return mirror::Array::Alloc(self, klass, component_count);
Ian Rogers57b86d42012-03-27 16:05:41 -0700141 }
142}
143
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800144mirror::Field* FindFieldFromCode(uint32_t field_idx, const mirror::AbstractMethod* referrer,
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200145 Thread* self, FindFieldType type, size_t expected_size,
146 bool access_check) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700147 bool is_primitive;
148 bool is_set;
149 bool is_static;
150 switch (type) {
151 case InstanceObjectRead: is_primitive = false; is_set = false; is_static = false; break;
152 case InstanceObjectWrite: is_primitive = false; is_set = true; is_static = false; break;
153 case InstancePrimitiveRead: is_primitive = true; is_set = false; is_static = false; break;
154 case InstancePrimitiveWrite: is_primitive = true; is_set = true; is_static = false; break;
155 case StaticObjectRead: is_primitive = false; is_set = false; is_static = true; break;
156 case StaticObjectWrite: is_primitive = false; is_set = true; is_static = true; break;
157 case StaticPrimitiveRead: is_primitive = true; is_set = false; is_static = true; break;
158 case StaticPrimitiveWrite: // Keep GCC happy by having a default handler, fall-through.
159 default: is_primitive = true; is_set = true; is_static = true; break;
160 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700161 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800162 mirror::Field* resolved_field = class_linker->ResolveField(field_idx, referrer, is_static);
Ian Rogers57b86d42012-03-27 16:05:41 -0700163 if (UNLIKELY(resolved_field == NULL)) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700164 DCHECK(self->IsExceptionPending()); // Throw exception and unwind.
165 return NULL; // Failure.
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200166 }
167 mirror::Class* fields_class = resolved_field->GetDeclaringClass();
168 if (access_check) {
Sebastien Hertz807a2562013-04-15 09:33:39 +0200169 if (UNLIKELY(resolved_field->IsStatic() != is_static)) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700170 ThrowIncompatibleClassChangeErrorField(resolved_field, is_static, referrer);
Ian Rogers08f753d2012-08-24 14:35:25 -0700171 return NULL;
172 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800173 mirror::Class* referring_class = referrer->GetDeclaringClass();
Ian Rogerse2645d32012-04-11 14:42:42 -0700174 if (UNLIKELY(!referring_class->CanAccess(fields_class) ||
175 !referring_class->CanAccessMember(fields_class,
176 resolved_field->GetAccessFlags()))) {
177 // The referring class can't access the resolved field, this may occur as a result of a
178 // protected field being made public by a sub-class. Resort to the dex file to determine
179 // the correct class for the access check.
Ian Rogers4445a7e2012-10-05 17:19:13 -0700180 const DexFile& dex_file = *referring_class->GetDexCache()->GetDexFile();
Ian Rogerse2645d32012-04-11 14:42:42 -0700181 fields_class = class_linker->ResolveType(dex_file,
182 dex_file.GetFieldId(field_idx).class_idx_,
183 referring_class);
184 if (UNLIKELY(!referring_class->CanAccess(fields_class))) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700185 ThrowIllegalAccessErrorClass(referring_class, fields_class);
Ian Rogerse2645d32012-04-11 14:42:42 -0700186 return NULL; // failure
187 } else if (UNLIKELY(!referring_class->CanAccessMember(fields_class,
188 resolved_field->GetAccessFlags()))) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700189 ThrowIllegalAccessErrorField(referring_class, resolved_field);
Ian Rogerse2645d32012-04-11 14:42:42 -0700190 return NULL; // failure
191 }
192 }
193 if (UNLIKELY(is_set && resolved_field->IsFinal() && (fields_class != referring_class))) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700194 ThrowIllegalAccessErrorFinalField(referrer, resolved_field);
Ian Rogers57b86d42012-03-27 16:05:41 -0700195 return NULL; // failure
196 } else {
197 FieldHelper fh(resolved_field);
198 if (UNLIKELY(fh.IsPrimitiveType() != is_primitive ||
199 fh.FieldSize() != expected_size)) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800200 ThrowLocation throw_location = self->GetCurrentLocationForThrow();
201 DCHECK(throw_location.GetMethod() == referrer);
202 self->ThrowNewExceptionF(throw_location, "Ljava/lang/NoSuchFieldError;",
Ian Rogers57b86d42012-03-27 16:05:41 -0700203 "Attempted read of %zd-bit %s on field '%s'",
204 expected_size * (32 / sizeof(int32_t)),
205 is_primitive ? "primitive" : "non-primitive",
206 PrettyField(resolved_field, true).c_str());
207 return NULL; // failure
Ian Rogers60db5ab2012-02-20 17:02:00 -0800208 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700209 }
210 }
Sebastien Hertz233ea8e2013-06-06 11:57:09 +0200211 if (!is_static) {
212 // instance fields must be being accessed on an initialized class
213 return resolved_field;
214 } else {
215 // If the class is initialized we're done.
216 if (fields_class->IsInitialized()) {
217 return resolved_field;
218 } else if (Runtime::Current()->GetClassLinker()->EnsureInitialized(fields_class, true, true)) {
219 // Otherwise let's ensure the class is initialized before resolving the field.
220 return resolved_field;
221 } else {
222 DCHECK(self->IsExceptionPending()); // Throw exception and unwind
223 return NULL; // failure
224 }
225 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700226}
227
228// Slow path method resolution
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800229mirror::AbstractMethod* FindMethodFromCode(uint32_t method_idx, mirror::Object* this_object,
230 mirror::AbstractMethod* referrer,
231 Thread* self, bool access_check, InvokeType type) {
Ian Rogers57b86d42012-03-27 16:05:41 -0700232 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
233 bool is_direct = type == kStatic || type == kDirect;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800234 mirror::AbstractMethod* resolved_method = class_linker->ResolveMethod(method_idx, referrer, type);
Ian Rogers57b86d42012-03-27 16:05:41 -0700235 if (UNLIKELY(resolved_method == NULL)) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700236 DCHECK(self->IsExceptionPending()); // Throw exception and unwind.
237 return NULL; // Failure.
jeffhao262e2512012-12-11 09:46:43 -0800238 } else if (UNLIKELY(this_object == NULL && type != kStatic)) {
239 // Maintain interpreter-like semantics where NullPointerException is thrown
240 // after potential NoSuchMethodError from class linker.
Ian Rogers62d6c772013-02-27 08:32:07 -0800241 ThrowLocation throw_location = self->GetCurrentLocationForThrow();
242 DCHECK(referrer == throw_location.GetMethod());
243 ThrowNullPointerExceptionForMethodAccess(throw_location, method_idx, type);
jeffhao262e2512012-12-11 09:46:43 -0800244 return NULL; // Failure.
Ian Rogers57b86d42012-03-27 16:05:41 -0700245 } else {
246 if (!access_check) {
247 if (is_direct) {
248 return resolved_method;
249 } else if (type == kInterface) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800250 mirror::AbstractMethod* interface_method =
Ian Rogers57b86d42012-03-27 16:05:41 -0700251 this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
252 if (UNLIKELY(interface_method == NULL)) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700253 ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(resolved_method, this_object,
254 referrer);
Ian Rogers08f753d2012-08-24 14:35:25 -0700255 return NULL; // Failure.
Ian Rogers57b86d42012-03-27 16:05:41 -0700256 } else {
257 return interface_method;
258 }
Ian Rogers60db5ab2012-02-20 17:02:00 -0800259 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800260 mirror::ObjectArray<mirror::AbstractMethod>* vtable;
Ian Rogers57b86d42012-03-27 16:05:41 -0700261 uint16_t vtable_index = resolved_method->GetMethodIndex();
262 if (type == kSuper) {
263 vtable = referrer->GetDeclaringClass()->GetSuperClass()->GetVTable();
264 } else {
265 vtable = this_object->GetClass()->GetVTable();
266 }
267 // TODO: eliminate bounds check?
268 return vtable->Get(vtable_index);
269 }
270 } else {
Ian Rogers08f753d2012-08-24 14:35:25 -0700271 // Incompatible class change should have been handled in resolve method.
272 if (UNLIKELY(resolved_method->CheckIncompatibleClassChange(type))) {
Ian Rogers2fc14272012-08-30 10:56:57 -0700273 ThrowIncompatibleClassChangeError(type, resolved_method->GetInvokeType(), resolved_method,
274 referrer);
Ian Rogers08f753d2012-08-24 14:35:25 -0700275 return NULL; // Failure.
276 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800277 mirror::Class* methods_class = resolved_method->GetDeclaringClass();
278 mirror::Class* referring_class = referrer->GetDeclaringClass();
Ian Rogers57b86d42012-03-27 16:05:41 -0700279 if (UNLIKELY(!referring_class->CanAccess(methods_class) ||
280 !referring_class->CanAccessMember(methods_class,
281 resolved_method->GetAccessFlags()))) {
282 // The referring class can't access the resolved method, this may occur as a result of a
283 // protected method being made public by implementing an interface that re-declares the
284 // method public. Resort to the dex file to determine the correct class for the access check
Ian Rogers4445a7e2012-10-05 17:19:13 -0700285 const DexFile& dex_file = *referring_class->GetDexCache()->GetDexFile();
Ian Rogers57b86d42012-03-27 16:05:41 -0700286 methods_class = class_linker->ResolveType(dex_file,
287 dex_file.GetMethodId(method_idx).class_idx_,
288 referring_class);
289 if (UNLIKELY(!referring_class->CanAccess(methods_class))) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700290 ThrowIllegalAccessErrorClassForMethodDispatch(referring_class, methods_class,
291 referrer, resolved_method, type);
Ian Rogers08f753d2012-08-24 14:35:25 -0700292 return NULL; // Failure.
Ian Rogers57b86d42012-03-27 16:05:41 -0700293 } else if (UNLIKELY(!referring_class->CanAccessMember(methods_class,
294 resolved_method->GetAccessFlags()))) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700295 ThrowIllegalAccessErrorMethod(referring_class, resolved_method);
Ian Rogers08f753d2012-08-24 14:35:25 -0700296 return NULL; // Failure.
Ian Rogers57b86d42012-03-27 16:05:41 -0700297 }
298 }
299 if (is_direct) {
300 return resolved_method;
301 } else if (type == kInterface) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800302 mirror::AbstractMethod* interface_method =
Ian Rogers57b86d42012-03-27 16:05:41 -0700303 this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
304 if (UNLIKELY(interface_method == NULL)) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700305 ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(resolved_method, this_object,
306 referrer);
Ian Rogers08f753d2012-08-24 14:35:25 -0700307 return NULL; // Failure.
Ian Rogers57b86d42012-03-27 16:05:41 -0700308 } else {
309 return interface_method;
310 }
311 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800312 mirror::ObjectArray<mirror::AbstractMethod>* vtable;
Ian Rogers57b86d42012-03-27 16:05:41 -0700313 uint16_t vtable_index = resolved_method->GetMethodIndex();
314 if (type == kSuper) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800315 mirror::Class* super_class = referring_class->GetSuperClass();
Ian Rogers57b86d42012-03-27 16:05:41 -0700316 if (LIKELY(super_class != NULL)) {
317 vtable = referring_class->GetSuperClass()->GetVTable();
318 } else {
319 vtable = NULL;
320 }
321 } else {
322 vtable = this_object->GetClass()->GetVTable();
323 }
324 if (LIKELY(vtable != NULL &&
325 vtable_index < static_cast<uint32_t>(vtable->GetLength()))) {
326 return vtable->GetWithoutChecks(vtable_index);
327 } else {
Ian Rogers08f753d2012-08-24 14:35:25 -0700328 // Behavior to agree with that of the verifier.
329 MethodHelper mh(resolved_method);
330 ThrowNoSuchMethodError(type, resolved_method->GetDeclaringClass(), mh.GetName(),
Ian Rogers62d6c772013-02-27 08:32:07 -0800331 mh.GetSignature());
Ian Rogers08f753d2012-08-24 14:35:25 -0700332 return NULL; // Failure.
Ian Rogers57b86d42012-03-27 16:05:41 -0700333 }
Ian Rogers60db5ab2012-02-20 17:02:00 -0800334 }
335 }
336 }
Ian Rogers60db5ab2012-02-20 17:02:00 -0800337}
338
jeffhaod7521322012-11-21 15:38:24 -0800339void ThrowStackOverflowError(Thread* self) {
340 CHECK(!self->IsHandlingStackOverflow()) << "Recursive stack overflow.";
Ian Rogers62d6c772013-02-27 08:32:07 -0800341
342 if (Runtime::Current()->GetInstrumentation()->AreExitStubsInstalled()) {
343 // Remove extra entry pushed onto second stack during method tracing.
344 Runtime::Current()->GetInstrumentation()->PopMethodForUnwind(self, false);
jeffhaod7521322012-11-21 15:38:24 -0800345 }
Ian Rogers62d6c772013-02-27 08:32:07 -0800346
jeffhaod7521322012-11-21 15:38:24 -0800347 self->SetStackEndForStackOverflow(); // Allow space on the stack for constructor to execute.
348 JNIEnvExt* env = self->GetJniEnv();
349 std::string msg("stack size ");
350 msg += PrettySize(self->GetStackSize());
351 // Use low-level JNI routine and pre-baked error class to avoid class linking operations that
352 // would consume more stack.
353 int rc = ::art::ThrowNewException(env, WellKnownClasses::java_lang_StackOverflowError,
354 msg.c_str(), NULL);
355 if (rc != JNI_OK) {
356 // TODO: ThrowNewException failed presumably because of an OOME, we continue to throw the OOME
357 // or die in the CHECK below. We may want to throw a pre-baked StackOverflowError
358 // instead.
359 LOG(ERROR) << "Couldn't throw new StackOverflowError because JNI ThrowNew failed.";
360 CHECK(self->IsExceptionPending());
361 }
362 self->ResetDefaultStackEnd(); // Return to default stack size.
363}
364
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800365JValue InvokeProxyInvocationHandler(ScopedObjectAccessUnchecked& soa, const char* shorty,
366 jobject rcvr_jobj, jobject interface_method_jobj,
367 std::vector<jvalue>& args) {
368 DCHECK(soa.Env()->IsInstanceOf(rcvr_jobj, WellKnownClasses::java_lang_reflect_Proxy));
369
370 // Build argument array possibly triggering GC.
371 soa.Self()->AssertThreadSuspensionIsAllowable();
372 jobjectArray args_jobj = NULL;
373 const JValue zero;
374 if (args.size() > 0) {
375 args_jobj = soa.Env()->NewObjectArray(args.size(), WellKnownClasses::java_lang_Object, NULL);
376 if (args_jobj == NULL) {
377 CHECK(soa.Self()->IsExceptionPending());
378 return zero;
379 }
380 for (size_t i = 0; i < args.size(); ++i) {
381 if (shorty[i + 1] == 'L') {
382 jobject val = args.at(i).l;
383 soa.Env()->SetObjectArrayElement(args_jobj, i, val);
384 } else {
385 JValue jv;
386 jv.SetJ(args.at(i).j);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800387 mirror::Object* val = BoxPrimitive(Primitive::GetType(shorty[i + 1]), jv);
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800388 if (val == NULL) {
389 CHECK(soa.Self()->IsExceptionPending());
390 return zero;
391 }
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800392 soa.Decode<mirror::ObjectArray<mirror::Object>* >(args_jobj)->Set(i, val);
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800393 }
394 }
395 }
396
397 // Call InvocationHandler.invoke(Object proxy, Method method, Object[] args).
398 jobject inv_hand = soa.Env()->GetObjectField(rcvr_jobj,
399 WellKnownClasses::java_lang_reflect_Proxy_h);
400 jvalue invocation_args[3];
401 invocation_args[0].l = rcvr_jobj;
402 invocation_args[1].l = interface_method_jobj;
403 invocation_args[2].l = args_jobj;
404 jobject result =
405 soa.Env()->CallObjectMethodA(inv_hand,
406 WellKnownClasses::java_lang_reflect_InvocationHandler_invoke,
407 invocation_args);
408
409 // Unbox result and handle error conditions.
Ian Rogers62d6c772013-02-27 08:32:07 -0800410 if (LIKELY(!soa.Self()->IsExceptionPending())) {
411 if (shorty[0] == 'V' || (shorty[0] == 'L' && result == NULL)) {
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800412 // Do nothing.
413 return zero;
414 } else {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800415 mirror::Object* result_ref = soa.Decode<mirror::Object*>(result);
Ian Rogers62d6c772013-02-27 08:32:07 -0800416 mirror::Object* rcvr = soa.Decode<mirror::Object*>(rcvr_jobj);
417 mirror::AbstractMethod* interface_method =
418 soa.Decode<mirror::AbstractMethod*>(interface_method_jobj);
419 mirror::Class* result_type = MethodHelper(interface_method).GetReturnType();
420 mirror::AbstractMethod* proxy_method;
421 if (interface_method->GetDeclaringClass()->IsInterface()) {
422 proxy_method = rcvr->GetClass()->FindVirtualMethodForInterface(interface_method);
423 } else {
424 // Proxy dispatch to a method defined in Object.
425 DCHECK(interface_method->GetDeclaringClass()->IsObjectClass());
426 proxy_method = interface_method;
427 }
428 ThrowLocation throw_location(rcvr, proxy_method, -1);
429 JValue result_unboxed;
430 if (!UnboxPrimitiveForResult(throw_location, result_ref, result_type, result_unboxed)) {
Ian Rogers530f71c2013-02-22 23:29:00 -0800431 DCHECK(soa.Self()->IsExceptionPending());
Ian Rogers62d6c772013-02-27 08:32:07 -0800432 return zero;
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800433 }
434 return result_unboxed;
435 }
436 } else {
437 // In the case of checked exceptions that aren't declared, the exception must be wrapped by
438 // a UndeclaredThrowableException.
Ian Rogers62d6c772013-02-27 08:32:07 -0800439 mirror::Throwable* exception = soa.Self()->GetException(NULL);
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800440 if (exception->IsCheckedException()) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800441 mirror::Object* rcvr = soa.Decode<mirror::Object*>(rcvr_jobj);
442 mirror::SynthesizedProxyClass* proxy_class =
443 down_cast<mirror::SynthesizedProxyClass*>(rcvr->GetClass());
444 mirror::AbstractMethod* interface_method =
445 soa.Decode<mirror::AbstractMethod*>(interface_method_jobj);
446 mirror::AbstractMethod* proxy_method =
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800447 rcvr->GetClass()->FindVirtualMethodForInterface(interface_method);
448 int throws_index = -1;
449 size_t num_virt_methods = proxy_class->NumVirtualMethods();
450 for (size_t i = 0; i < num_virt_methods; i++) {
451 if (proxy_class->GetVirtualMethod(i) == proxy_method) {
452 throws_index = i;
453 break;
454 }
455 }
456 CHECK_NE(throws_index, -1);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800457 mirror::ObjectArray<mirror::Class>* declared_exceptions = proxy_class->GetThrows()->Get(throws_index);
458 mirror::Class* exception_class = exception->GetClass();
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800459 bool declares_exception = false;
460 for (int i = 0; i < declared_exceptions->GetLength() && !declares_exception; i++) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800461 mirror::Class* declared_exception = declared_exceptions->Get(i);
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800462 declares_exception = declared_exception->IsAssignableFrom(exception_class);
463 }
464 if (!declares_exception) {
Ian Rogers62d6c772013-02-27 08:32:07 -0800465 ThrowLocation throw_location(rcvr, proxy_method, -1);
466 soa.Self()->ThrowNewWrappedException(throw_location,
467 "Ljava/lang/reflect/UndeclaredThrowableException;",
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800468 NULL);
469 }
470 }
471 return zero;
472 }
473}
474
Shih-wei Liao2d831012011-09-28 22:06:53 -0700475} // namespace art