blob: b276917be9f20762db40b52261648bc0b64f0030 [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 Rogersaf6e67a2013-01-16 08:38:37 -080019#include "reflection.h"
20#include "scoped_thread_state_change.h"
TDYa1275bb86012012-04-11 05:57:28 -070021#include "ScopedLocalRef.h"
Elliott Hugheseac76672012-05-24 21:56:51 -070022#include "well_known_classes.h"
TDYa1275bb86012012-04-11 05:57:28 -070023
jeffhao41005dd2012-05-09 17:58:52 -070024double art_l2d(int64_t l) {
Elliott Hughes74847412012-06-20 18:10:21 -070025 return static_cast<double>(l);
jeffhao41005dd2012-05-09 17:58:52 -070026}
27
28float art_l2f(int64_t l) {
Elliott Hughes74847412012-06-20 18:10:21 -070029 return static_cast<float>(l);
jeffhao41005dd2012-05-09 17:58:52 -070030}
Shih-wei Liao2d831012011-09-28 22:06:53 -070031
Ian Rogers776ac1f2012-04-13 23:36:36 -070032/*
33 * Float/double conversion requires clamping to min and max of integer form. If
34 * target doesn't support this normally, use these.
35 */
jeffhao41005dd2012-05-09 17:58:52 -070036int64_t art_d2l(double d) {
Elliott Hughes74847412012-06-20 18:10:21 -070037 static const double kMaxLong = static_cast<double>(static_cast<int64_t>(0x7fffffffffffffffULL));
38 static const double kMinLong = static_cast<double>(static_cast<int64_t>(0x8000000000000000ULL));
Ian Rogers776ac1f2012-04-13 23:36:36 -070039 if (d >= kMaxLong) {
Logan Chien008fa512012-06-22 08:09:57 -070040 return static_cast<int64_t>(0x7fffffffffffffffULL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070041 } else if (d <= kMinLong) {
Logan Chien008fa512012-06-22 08:09:57 -070042 return static_cast<int64_t>(0x8000000000000000ULL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070043 } else if (d != d) { // NaN case
44 return 0;
45 } else {
Elliott Hughes74847412012-06-20 18:10:21 -070046 return static_cast<int64_t>(d);
Ian Rogers776ac1f2012-04-13 23:36:36 -070047 }
48}
49
jeffhao41005dd2012-05-09 17:58:52 -070050int64_t art_f2l(float f) {
Elliott Hughes74847412012-06-20 18:10:21 -070051 static const float kMaxLong = static_cast<float>(static_cast<int64_t>(0x7fffffffffffffffULL));
52 static const float kMinLong = static_cast<float>(static_cast<int64_t>(0x8000000000000000ULL));
Ian Rogers776ac1f2012-04-13 23:36:36 -070053 if (f >= kMaxLong) {
Logan Chien008fa512012-06-22 08:09:57 -070054 return static_cast<int64_t>(0x7fffffffffffffffULL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070055 } else if (f <= kMinLong) {
Logan Chien008fa512012-06-22 08:09:57 -070056 return static_cast<int64_t>(0x8000000000000000ULL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070057 } else if (f != f) { // NaN case
58 return 0;
59 } else {
Elliott Hughes74847412012-06-20 18:10:21 -070060 return static_cast<int64_t>(f);
Ian Rogers776ac1f2012-04-13 23:36:36 -070061 }
62}
63
jeffhao41005dd2012-05-09 17:58:52 -070064int32_t art_d2i(double d) {
Logan Chien008fa512012-06-22 08:09:57 -070065 static const double kMaxInt = static_cast<double>(static_cast<int32_t>(0x7fffffffUL));
66 static const double kMinInt = static_cast<double>(static_cast<int32_t>(0x80000000UL));
Ian Rogers776ac1f2012-04-13 23:36:36 -070067 if (d >= kMaxInt) {
Logan Chien008fa512012-06-22 08:09:57 -070068 return static_cast<int32_t>(0x7fffffffUL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070069 } else if (d <= kMinInt) {
Logan Chien008fa512012-06-22 08:09:57 -070070 return static_cast<int32_t>(0x80000000UL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070071 } else if (d != d) { // NaN case
72 return 0;
73 } else {
Elliott Hughes74847412012-06-20 18:10:21 -070074 return static_cast<int32_t>(d);
Ian Rogers776ac1f2012-04-13 23:36:36 -070075 }
76}
77
jeffhao41005dd2012-05-09 17:58:52 -070078int32_t art_f2i(float f) {
Logan Chien008fa512012-06-22 08:09:57 -070079 static const float kMaxInt = static_cast<float>(static_cast<int32_t>(0x7fffffffUL));
80 static const float kMinInt = static_cast<float>(static_cast<int32_t>(0x80000000UL));
Ian Rogers776ac1f2012-04-13 23:36:36 -070081 if (f >= kMaxInt) {
Logan Chien008fa512012-06-22 08:09:57 -070082 return static_cast<int32_t>(0x7fffffffUL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070083 } else if (f <= kMinInt) {
Logan Chien008fa512012-06-22 08:09:57 -070084 return static_cast<int32_t>(0x80000000UL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070085 } else if (f != f) { // NaN case
86 return 0;
87 } else {
Elliott Hughes74847412012-06-20 18:10:21 -070088 return static_cast<int32_t>(f);
Ian Rogers776ac1f2012-04-13 23:36:36 -070089 }
90}
91
jeffhao41005dd2012-05-09 17:58:52 -070092namespace art {
93
Ian Rogers57b86d42012-03-27 16:05:41 -070094// Helper function to allocate array for FILLED_NEW_ARRAY.
Mathieu Chartier66f19252012-09-18 08:57:04 -070095Array* CheckAndAllocArrayFromCode(uint32_t type_idx, AbstractMethod* method, int32_t component_count,
Ian Rogers57b86d42012-03-27 16:05:41 -070096 Thread* self, bool access_check) {
97 if (UNLIKELY(component_count < 0)) {
98 self->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", component_count);
99 return NULL; // Failure
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700100 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700101 Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
102 if (UNLIKELY(klass == NULL)) { // Not in dex cache so try to resolve
103 klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
104 if (klass == NULL) { // Error
Ian Rogers50b35e22012-10-04 10:09:15 -0700105 DCHECK(self->IsExceptionPending());
Ian Rogers57b86d42012-03-27 16:05:41 -0700106 return NULL; // Failure
Ian Rogers19846512012-02-24 11:42:47 -0800107 }
Ian Rogersea2a11d2011-10-11 16:48:51 -0700108 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700109 if (UNLIKELY(klass->IsPrimitive() && !klass->IsPrimitiveInt())) {
110 if (klass->IsPrimitiveLong() || klass->IsPrimitiveDouble()) {
Ian Rogers50b35e22012-10-04 10:09:15 -0700111 self->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
112 "Bad filled array request for type %s",
113 PrettyDescriptor(klass).c_str());
Ian Rogers573db4a2011-12-13 15:30:50 -0800114 } else {
Ian Rogers50b35e22012-10-04 10:09:15 -0700115 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
116 "Found type %s; filled-new-array not implemented for anything but \'int\'",
117 PrettyDescriptor(klass).c_str());
Ian Rogers573db4a2011-12-13 15:30:50 -0800118 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700119 return NULL; // Failure
Ian Rogersad25ac52011-10-04 19:13:33 -0700120 } else {
Ian Rogers57b86d42012-03-27 16:05:41 -0700121 if (access_check) {
122 Class* referrer = method->GetDeclaringClass();
123 if (UNLIKELY(!referrer->CanAccess(klass))) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700124 ThrowIllegalAccessErrorClass(referrer, klass);
Ian Rogers57b86d42012-03-27 16:05:41 -0700125 return NULL; // Failure
126 }
Ian Rogers60db5ab2012-02-20 17:02:00 -0800127 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700128 DCHECK(klass->IsArrayClass()) << PrettyClass(klass);
Ian Rogers50b35e22012-10-04 10:09:15 -0700129 return Array::Alloc(self, klass, component_count);
Ian Rogers57b86d42012-03-27 16:05:41 -0700130 }
131}
132
Mathieu Chartier66f19252012-09-18 08:57:04 -0700133Field* FindFieldFromCode(uint32_t field_idx, const AbstractMethod* referrer, Thread* self,
Ian Rogers08f753d2012-08-24 14:35:25 -0700134 FindFieldType type, size_t expected_size) {
135 bool is_primitive;
136 bool is_set;
137 bool is_static;
138 switch (type) {
139 case InstanceObjectRead: is_primitive = false; is_set = false; is_static = false; break;
140 case InstanceObjectWrite: is_primitive = false; is_set = true; is_static = false; break;
141 case InstancePrimitiveRead: is_primitive = true; is_set = false; is_static = false; break;
142 case InstancePrimitiveWrite: is_primitive = true; is_set = true; is_static = false; break;
143 case StaticObjectRead: is_primitive = false; is_set = false; is_static = true; break;
144 case StaticObjectWrite: is_primitive = false; is_set = true; is_static = true; break;
145 case StaticPrimitiveRead: is_primitive = true; is_set = false; is_static = true; break;
146 case StaticPrimitiveWrite: // Keep GCC happy by having a default handler, fall-through.
147 default: is_primitive = true; is_set = true; is_static = true; break;
148 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700149 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
150 Field* resolved_field = class_linker->ResolveField(field_idx, referrer, is_static);
151 if (UNLIKELY(resolved_field == NULL)) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700152 DCHECK(self->IsExceptionPending()); // Throw exception and unwind.
153 return NULL; // Failure.
Ian Rogers57b86d42012-03-27 16:05:41 -0700154 } else {
Ian Rogers08f753d2012-08-24 14:35:25 -0700155 if (resolved_field->IsStatic() != is_static) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700156 ThrowIncompatibleClassChangeErrorField(resolved_field, is_static, referrer);
Ian Rogers08f753d2012-08-24 14:35:25 -0700157 return NULL;
158 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700159 Class* fields_class = resolved_field->GetDeclaringClass();
160 Class* referring_class = referrer->GetDeclaringClass();
Ian Rogerse2645d32012-04-11 14:42:42 -0700161 if (UNLIKELY(!referring_class->CanAccess(fields_class) ||
162 !referring_class->CanAccessMember(fields_class,
163 resolved_field->GetAccessFlags()))) {
164 // The referring class can't access the resolved field, this may occur as a result of a
165 // protected field being made public by a sub-class. Resort to the dex file to determine
166 // the correct class for the access check.
Ian Rogers4445a7e2012-10-05 17:19:13 -0700167 const DexFile& dex_file = *referring_class->GetDexCache()->GetDexFile();
Ian Rogerse2645d32012-04-11 14:42:42 -0700168 fields_class = class_linker->ResolveType(dex_file,
169 dex_file.GetFieldId(field_idx).class_idx_,
170 referring_class);
171 if (UNLIKELY(!referring_class->CanAccess(fields_class))) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700172 ThrowIllegalAccessErrorClass(referring_class, fields_class);
Ian Rogerse2645d32012-04-11 14:42:42 -0700173 return NULL; // failure
174 } else if (UNLIKELY(!referring_class->CanAccessMember(fields_class,
175 resolved_field->GetAccessFlags()))) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700176 ThrowIllegalAccessErrorField(referring_class, resolved_field);
Ian Rogerse2645d32012-04-11 14:42:42 -0700177 return NULL; // failure
178 }
179 }
180 if (UNLIKELY(is_set && resolved_field->IsFinal() && (fields_class != referring_class))) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700181 ThrowIllegalAccessErrorFinalField(referrer, resolved_field);
Ian Rogers57b86d42012-03-27 16:05:41 -0700182 return NULL; // failure
183 } else {
184 FieldHelper fh(resolved_field);
185 if (UNLIKELY(fh.IsPrimitiveType() != is_primitive ||
186 fh.FieldSize() != expected_size)) {
187 self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
188 "Attempted read of %zd-bit %s on field '%s'",
189 expected_size * (32 / sizeof(int32_t)),
190 is_primitive ? "primitive" : "non-primitive",
191 PrettyField(resolved_field, true).c_str());
192 return NULL; // failure
193 } else if (!is_static) {
194 // instance fields must be being accessed on an initialized class
195 return resolved_field;
Ian Rogers60db5ab2012-02-20 17:02:00 -0800196 } else {
Ian Rogers57b86d42012-03-27 16:05:41 -0700197 // If the class is already initializing, we must be inside <clinit>, or
198 // we'd still be waiting for the lock.
199 if (fields_class->IsInitializing()) {
200 return resolved_field;
Ian Rogers0045a292012-03-31 21:08:41 -0700201 } else if (Runtime::Current()->GetClassLinker()->EnsureInitialized(fields_class, true, true)) {
Ian Rogers57b86d42012-03-27 16:05:41 -0700202 return resolved_field;
Ian Rogers60db5ab2012-02-20 17:02:00 -0800203 } else {
Ian Rogers57b86d42012-03-27 16:05:41 -0700204 DCHECK(self->IsExceptionPending()); // Throw exception and unwind
205 return NULL; // failure
Ian Rogers60db5ab2012-02-20 17:02:00 -0800206 }
207 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700208 }
209 }
210}
211
212// Slow path method resolution
jeffhao262e2512012-12-11 09:46:43 -0800213AbstractMethod* FindMethodFromCode(uint32_t method_idx, Object* this_object, AbstractMethod* referrer,
Ian Rogers57b86d42012-03-27 16:05:41 -0700214 Thread* self, bool access_check, InvokeType type) {
215 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
216 bool is_direct = type == kStatic || type == kDirect;
Mathieu Chartier66f19252012-09-18 08:57:04 -0700217 AbstractMethod* resolved_method = class_linker->ResolveMethod(method_idx, referrer, type);
Ian Rogers57b86d42012-03-27 16:05:41 -0700218 if (UNLIKELY(resolved_method == NULL)) {
Ian Rogers08f753d2012-08-24 14:35:25 -0700219 DCHECK(self->IsExceptionPending()); // Throw exception and unwind.
220 return NULL; // Failure.
jeffhao262e2512012-12-11 09:46:43 -0800221 } else if (UNLIKELY(this_object == NULL && type != kStatic)) {
222 // Maintain interpreter-like semantics where NullPointerException is thrown
223 // after potential NoSuchMethodError from class linker.
224 ThrowNullPointerExceptionForMethodAccess(referrer, method_idx, type);
225 return NULL; // Failure.
Ian Rogers57b86d42012-03-27 16:05:41 -0700226 } else {
227 if (!access_check) {
228 if (is_direct) {
229 return resolved_method;
230 } else if (type == kInterface) {
Mathieu Chartier66f19252012-09-18 08:57:04 -0700231 AbstractMethod* interface_method =
Ian Rogers57b86d42012-03-27 16:05:41 -0700232 this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
233 if (UNLIKELY(interface_method == NULL)) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700234 ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(resolved_method, this_object,
235 referrer);
Ian Rogers08f753d2012-08-24 14:35:25 -0700236 return NULL; // Failure.
Ian Rogers57b86d42012-03-27 16:05:41 -0700237 } else {
238 return interface_method;
239 }
Ian Rogers60db5ab2012-02-20 17:02:00 -0800240 } else {
Mathieu Chartier66f19252012-09-18 08:57:04 -0700241 ObjectArray<AbstractMethod>* vtable;
Ian Rogers57b86d42012-03-27 16:05:41 -0700242 uint16_t vtable_index = resolved_method->GetMethodIndex();
243 if (type == kSuper) {
244 vtable = referrer->GetDeclaringClass()->GetSuperClass()->GetVTable();
245 } else {
246 vtable = this_object->GetClass()->GetVTable();
247 }
248 // TODO: eliminate bounds check?
249 return vtable->Get(vtable_index);
250 }
251 } else {
Ian Rogers08f753d2012-08-24 14:35:25 -0700252 // Incompatible class change should have been handled in resolve method.
253 if (UNLIKELY(resolved_method->CheckIncompatibleClassChange(type))) {
Ian Rogers2fc14272012-08-30 10:56:57 -0700254 ThrowIncompatibleClassChangeError(type, resolved_method->GetInvokeType(), resolved_method,
255 referrer);
Ian Rogers08f753d2012-08-24 14:35:25 -0700256 return NULL; // Failure.
257 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700258 Class* methods_class = resolved_method->GetDeclaringClass();
259 Class* referring_class = referrer->GetDeclaringClass();
260 if (UNLIKELY(!referring_class->CanAccess(methods_class) ||
261 !referring_class->CanAccessMember(methods_class,
262 resolved_method->GetAccessFlags()))) {
263 // The referring class can't access the resolved method, this may occur as a result of a
264 // protected method being made public by implementing an interface that re-declares the
265 // method public. Resort to the dex file to determine the correct class for the access check
Ian Rogers4445a7e2012-10-05 17:19:13 -0700266 const DexFile& dex_file = *referring_class->GetDexCache()->GetDexFile();
Ian Rogers57b86d42012-03-27 16:05:41 -0700267 methods_class = class_linker->ResolveType(dex_file,
268 dex_file.GetMethodId(method_idx).class_idx_,
269 referring_class);
270 if (UNLIKELY(!referring_class->CanAccess(methods_class))) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700271 ThrowIllegalAccessErrorClassForMethodDispatch(referring_class, methods_class,
272 referrer, resolved_method, type);
Ian Rogers08f753d2012-08-24 14:35:25 -0700273 return NULL; // Failure.
Ian Rogers57b86d42012-03-27 16:05:41 -0700274 } else if (UNLIKELY(!referring_class->CanAccessMember(methods_class,
275 resolved_method->GetAccessFlags()))) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700276 ThrowIllegalAccessErrorMethod(referring_class, resolved_method);
Ian Rogers08f753d2012-08-24 14:35:25 -0700277 return NULL; // Failure.
Ian Rogers57b86d42012-03-27 16:05:41 -0700278 }
279 }
280 if (is_direct) {
281 return resolved_method;
282 } else if (type == kInterface) {
Mathieu Chartier66f19252012-09-18 08:57:04 -0700283 AbstractMethod* interface_method =
Ian Rogers57b86d42012-03-27 16:05:41 -0700284 this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
285 if (UNLIKELY(interface_method == NULL)) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700286 ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(resolved_method, this_object,
287 referrer);
Ian Rogers08f753d2012-08-24 14:35:25 -0700288 return NULL; // Failure.
Ian Rogers57b86d42012-03-27 16:05:41 -0700289 } else {
290 return interface_method;
291 }
292 } else {
Mathieu Chartier66f19252012-09-18 08:57:04 -0700293 ObjectArray<AbstractMethod>* vtable;
Ian Rogers57b86d42012-03-27 16:05:41 -0700294 uint16_t vtable_index = resolved_method->GetMethodIndex();
295 if (type == kSuper) {
296 Class* super_class = referring_class->GetSuperClass();
297 if (LIKELY(super_class != NULL)) {
298 vtable = referring_class->GetSuperClass()->GetVTable();
299 } else {
300 vtable = NULL;
301 }
302 } else {
303 vtable = this_object->GetClass()->GetVTable();
304 }
305 if (LIKELY(vtable != NULL &&
306 vtable_index < static_cast<uint32_t>(vtable->GetLength()))) {
307 return vtable->GetWithoutChecks(vtable_index);
308 } else {
Ian Rogers08f753d2012-08-24 14:35:25 -0700309 // Behavior to agree with that of the verifier.
310 MethodHelper mh(resolved_method);
311 ThrowNoSuchMethodError(type, resolved_method->GetDeclaringClass(), mh.GetName(),
Ian Rogers2fc14272012-08-30 10:56:57 -0700312 mh.GetSignature(), referrer);
Ian Rogers08f753d2012-08-24 14:35:25 -0700313 return NULL; // Failure.
Ian Rogers57b86d42012-03-27 16:05:41 -0700314 }
Ian Rogers60db5ab2012-02-20 17:02:00 -0800315 }
316 }
317 }
Ian Rogers60db5ab2012-02-20 17:02:00 -0800318}
319
Mathieu Chartier66f19252012-09-18 08:57:04 -0700320Class* ResolveVerifyAndClinit(uint32_t type_idx, const AbstractMethod* referrer, Thread* self,
Ian Rogers57b86d42012-03-27 16:05:41 -0700321 bool can_run_clinit, bool verify_access) {
322 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
323 Class* klass = class_linker->ResolveType(type_idx, referrer);
324 if (UNLIKELY(klass == NULL)) {
jeffhao441d9122012-03-21 17:29:10 -0700325 CHECK(self->IsExceptionPending());
Ian Rogers57b86d42012-03-27 16:05:41 -0700326 return NULL; // Failure - Indicate to caller to deliver exception
jeffhao441d9122012-03-21 17:29:10 -0700327 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700328 // Perform access check if necessary.
329 Class* referring_class = referrer->GetDeclaringClass();
330 if (verify_access && UNLIKELY(!referring_class->CanAccess(klass))) {
Ian Rogers87e552d2012-08-31 15:54:48 -0700331 ThrowIllegalAccessErrorClass(referring_class, klass);
Ian Rogers57b86d42012-03-27 16:05:41 -0700332 return NULL; // Failure - Indicate to caller to deliver exception
Ian Rogers14b1b242011-10-11 18:54:34 -0700333 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700334 // If we're just implementing const-class, we shouldn't call <clinit>.
335 if (!can_run_clinit) {
336 return klass;
Ian Rogersdfcdf1a2011-10-10 17:50:35 -0700337 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700338 // If we are the <clinit> of this class, just return our storage.
339 //
340 // Do not set the DexCache InitializedStaticStorage, since that implies <clinit> has finished
341 // running.
342 if (klass == referring_class && MethodHelper(referrer).IsClassInitializer()) {
343 return klass;
Ian Rogersdfcdf1a2011-10-10 17:50:35 -0700344 }
Ian Rogers0045a292012-03-31 21:08:41 -0700345 if (!class_linker->EnsureInitialized(klass, true, true)) {
Ian Rogers57b86d42012-03-27 16:05:41 -0700346 CHECK(self->IsExceptionPending());
347 return NULL; // Failure - Indicate to caller to deliver exception
Ian Rogersdfcdf1a2011-10-10 17:50:35 -0700348 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700349 referrer->GetDexCacheInitializedStaticStorage()->Set(type_idx, klass);
350 return klass;
Shih-wei Liao2d831012011-09-28 22:06:53 -0700351}
352
jeffhaod7521322012-11-21 15:38:24 -0800353void ThrowStackOverflowError(Thread* self) {
354 CHECK(!self->IsHandlingStackOverflow()) << "Recursive stack overflow.";
355 // Remove extra entry pushed onto second stack during method tracing.
356 if (Runtime::Current()->IsMethodTracingActive()) {
357 InstrumentationMethodUnwindFromCode(self);
358 }
359 self->SetStackEndForStackOverflow(); // Allow space on the stack for constructor to execute.
360 JNIEnvExt* env = self->GetJniEnv();
361 std::string msg("stack size ");
362 msg += PrettySize(self->GetStackSize());
363 // Use low-level JNI routine and pre-baked error class to avoid class linking operations that
364 // would consume more stack.
365 int rc = ::art::ThrowNewException(env, WellKnownClasses::java_lang_StackOverflowError,
366 msg.c_str(), NULL);
367 if (rc != JNI_OK) {
368 // TODO: ThrowNewException failed presumably because of an OOME, we continue to throw the OOME
369 // or die in the CHECK below. We may want to throw a pre-baked StackOverflowError
370 // instead.
371 LOG(ERROR) << "Couldn't throw new StackOverflowError because JNI ThrowNew failed.";
372 CHECK(self->IsExceptionPending());
373 }
374 self->ResetDefaultStackEnd(); // Return to default stack size.
375}
376
Ian Rogersaf6e67a2013-01-16 08:38:37 -0800377JValue InvokeProxyInvocationHandler(ScopedObjectAccessUnchecked& soa, const char* shorty,
378 jobject rcvr_jobj, jobject interface_method_jobj,
379 std::vector<jvalue>& args) {
380 DCHECK(soa.Env()->IsInstanceOf(rcvr_jobj, WellKnownClasses::java_lang_reflect_Proxy));
381
382 // Build argument array possibly triggering GC.
383 soa.Self()->AssertThreadSuspensionIsAllowable();
384 jobjectArray args_jobj = NULL;
385 const JValue zero;
386 if (args.size() > 0) {
387 args_jobj = soa.Env()->NewObjectArray(args.size(), WellKnownClasses::java_lang_Object, NULL);
388 if (args_jobj == NULL) {
389 CHECK(soa.Self()->IsExceptionPending());
390 return zero;
391 }
392 for (size_t i = 0; i < args.size(); ++i) {
393 if (shorty[i + 1] == 'L') {
394 jobject val = args.at(i).l;
395 soa.Env()->SetObjectArrayElement(args_jobj, i, val);
396 } else {
397 JValue jv;
398 jv.SetJ(args.at(i).j);
399 Object* val = BoxPrimitive(Primitive::GetType(shorty[i + 1]), jv);
400 if (val == NULL) {
401 CHECK(soa.Self()->IsExceptionPending());
402 return zero;
403 }
404 soa.Decode<ObjectArray<Object>* >(args_jobj)->Set(i, val);
405 }
406 }
407 }
408
409 // Call InvocationHandler.invoke(Object proxy, Method method, Object[] args).
410 jobject inv_hand = soa.Env()->GetObjectField(rcvr_jobj,
411 WellKnownClasses::java_lang_reflect_Proxy_h);
412 jvalue invocation_args[3];
413 invocation_args[0].l = rcvr_jobj;
414 invocation_args[1].l = interface_method_jobj;
415 invocation_args[2].l = args_jobj;
416 jobject result =
417 soa.Env()->CallObjectMethodA(inv_hand,
418 WellKnownClasses::java_lang_reflect_InvocationHandler_invoke,
419 invocation_args);
420
421 // Unbox result and handle error conditions.
422 if (!soa.Self()->IsExceptionPending()) {
423 if (shorty[0] == 'V' || result == NULL) {
424 // Do nothing.
425 return zero;
426 } else {
427 JValue result_unboxed;
428 MethodHelper mh(soa.Decode<AbstractMethod*>(interface_method_jobj));
429 Class* result_type = mh.GetReturnType();
430 Object* result_ref = soa.Decode<Object*>(result);
431 bool unboxed_okay = UnboxPrimitiveForResult(result_ref, result_type, result_unboxed);
432 if (!unboxed_okay) {
433 soa.Self()->ThrowNewWrappedException("Ljava/lang/ClassCastException;",
434 StringPrintf("Couldn't convert result of type %s to %s",
435 PrettyTypeOf(result_ref).c_str(),
436 PrettyDescriptor(result_type).c_str()
437 ).c_str());
438 }
439 return result_unboxed;
440 }
441 } else {
442 // In the case of checked exceptions that aren't declared, the exception must be wrapped by
443 // a UndeclaredThrowableException.
444 Throwable* exception = soa.Self()->GetException();
445 if (exception->IsCheckedException()) {
446 Object* rcvr = soa.Decode<Object*>(rcvr_jobj);
447 SynthesizedProxyClass* proxy_class = down_cast<SynthesizedProxyClass*>(rcvr->GetClass());
448 AbstractMethod* interface_method = soa.Decode<AbstractMethod*>(interface_method_jobj);
449 AbstractMethod* proxy_method =
450 rcvr->GetClass()->FindVirtualMethodForInterface(interface_method);
451 int throws_index = -1;
452 size_t num_virt_methods = proxy_class->NumVirtualMethods();
453 for (size_t i = 0; i < num_virt_methods; i++) {
454 if (proxy_class->GetVirtualMethod(i) == proxy_method) {
455 throws_index = i;
456 break;
457 }
458 }
459 CHECK_NE(throws_index, -1);
460 ObjectArray<Class>* declared_exceptions = proxy_class->GetThrows()->Get(throws_index);
461 Class* exception_class = exception->GetClass();
462 bool declares_exception = false;
463 for (int i = 0; i < declared_exceptions->GetLength() && !declares_exception; i++) {
464 Class* declared_exception = declared_exceptions->Get(i);
465 declares_exception = declared_exception->IsAssignableFrom(exception_class);
466 }
467 if (!declares_exception) {
468 soa.Self()->ThrowNewWrappedException("Ljava/lang/reflect/UndeclaredThrowableException;",
469 NULL);
470 }
471 }
472 return zero;
473 }
474}
475
Shih-wei Liao2d831012011-09-28 22:06:53 -0700476} // namespace art