blob: 50f0130b4c950e809e90517ca19e5f83f92f30df [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
TDYa1275bb86012012-04-11 05:57:28 -070019#include "ScopedLocalRef.h"
20
Shih-wei Liao2d831012011-09-28 22:06:53 -070021namespace art {
22
Ian Rogers776ac1f2012-04-13 23:36:36 -070023/*
24 * Float/double conversion requires clamping to min and max of integer form. If
25 * target doesn't support this normally, use these.
26 */
27int64_t D2L(double d) {
28 static const double kMaxLong = (double) (int64_t) 0x7fffffffffffffffULL;
29 static const double kMinLong = (double) (int64_t) 0x8000000000000000ULL;
30 if (d >= kMaxLong) {
31 return (int64_t) 0x7fffffffffffffffULL;
32 } else if (d <= kMinLong) {
33 return (int64_t) 0x8000000000000000ULL;
34 } else if (d != d) { // NaN case
35 return 0;
36 } else {
37 return (int64_t) d;
38 }
39}
40
41int64_t F2L(float f) {
42 static const float kMaxLong = (float) (int64_t) 0x7fffffffffffffffULL;
43 static const float kMinLong = (float) (int64_t) 0x8000000000000000ULL;
44 if (f >= kMaxLong) {
45 return (int64_t) 0x7fffffffffffffffULL;
46 } else if (f <= kMinLong) {
47 return (int64_t) 0x8000000000000000ULL;
48 } else if (f != f) { // NaN case
49 return 0;
50 } else {
51 return (int64_t) f;
52 }
53}
54
55int32_t D2I(double d) {
56 static const double kMaxInt = (double) (int32_t) 0x7fffffffUL;
57 static const double kMinInt = (double) (int32_t) 0x80000000UL;
58 if (d >= kMaxInt) {
59 return (int32_t) 0x7fffffffUL;
60 } else if (d <= kMinInt) {
61 return (int32_t) 0x80000000UL;
62 } else if (d != d) { // NaN case
63 return 0;
64 } else {
65 return (int32_t) d;
66 }
67}
68
69int32_t F2I(float f) {
70 static const float kMaxInt = (float) (int32_t) 0x7fffffffUL;
71 static const float kMinInt = (float) (int32_t) 0x80000000UL;
72 if (f >= kMaxInt) {
73 return (int32_t) 0x7fffffffUL;
74 } else if (f <= kMinInt) {
75 return (int32_t) 0x80000000UL;
76 } else if (f != f) { // NaN case
77 return 0;
78 } else {
79 return (int32_t) f;
80 }
81}
82
Ian Rogers57b86d42012-03-27 16:05:41 -070083void ThrowNewIllegalAccessErrorClass(Thread* self,
84 Class* referrer,
85 Class* accessed) {
86 self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
87 "illegal class access: '%s' -> '%s'",
88 PrettyDescriptor(referrer).c_str(),
89 PrettyDescriptor(accessed).c_str());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -080090}
91
Ian Rogers57b86d42012-03-27 16:05:41 -070092void ThrowNewIllegalAccessErrorClassForMethodDispatch(Thread* self,
93 Class* referrer,
94 Class* accessed,
95 const Method* caller,
96 const Method* called,
97 InvokeType type) {
98 std::ostringstream type_stream;
99 type_stream << type;
100 self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
101 "illegal class access ('%s' -> '%s')"
102 "in attempt to invoke %s method '%s' from '%s'",
103 PrettyDescriptor(referrer).c_str(),
104 PrettyDescriptor(accessed).c_str(),
105 type_stream.str().c_str(),
106 PrettyMethod(called).c_str(),
107 PrettyMethod(caller).c_str());
buzbee44b412b2012-02-04 08:50:53 -0800108}
109
Ian Rogers57b86d42012-03-27 16:05:41 -0700110void ThrowNewIncompatibleClassChangeErrorClassForInterfaceDispatch(Thread* self,
111 const Method* referrer,
112 const Method* interface_method,
113 Object* this_object) {
114 self->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
115 "class '%s' does not implement interface '%s' in call to '%s' from '%s'",
116 PrettyDescriptor(this_object->GetClass()).c_str(),
117 PrettyDescriptor(interface_method->GetDeclaringClass()).c_str(),
118 PrettyMethod(interface_method).c_str(), PrettyMethod(referrer).c_str());
Shih-wei Liao2d831012011-09-28 22:06:53 -0700119}
120
Ian Rogers57b86d42012-03-27 16:05:41 -0700121void ThrowNewIllegalAccessErrorField(Thread* self,
122 Class* referrer,
123 Field* accessed) {
124 self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
125 "Field '%s' is inaccessible to class '%s'",
126 PrettyField(accessed, false).c_str(),
127 PrettyDescriptor(referrer).c_str());
Shih-wei Liao2d831012011-09-28 22:06:53 -0700128}
129
Ian Rogers57b86d42012-03-27 16:05:41 -0700130void ThrowNewIllegalAccessErrorFinalField(Thread* self,
131 const Method* referrer,
132 Field* accessed) {
133 self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
134 "Final field '%s' cannot be written to by method '%s'",
135 PrettyField(accessed, false).c_str(),
136 PrettyMethod(referrer).c_str());
Shih-wei Liao2d831012011-09-28 22:06:53 -0700137}
138
Ian Rogers57b86d42012-03-27 16:05:41 -0700139void ThrowNewIllegalAccessErrorMethod(Thread* self,
140 Class* referrer,
141 Method* accessed) {
142 self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
143 "Method '%s' is inaccessible to class '%s'",
144 PrettyMethod(accessed).c_str(),
145 PrettyDescriptor(referrer).c_str());
Shih-wei Liao2d831012011-09-28 22:06:53 -0700146}
147
Ian Rogers57b86d42012-03-27 16:05:41 -0700148void ThrowNullPointerExceptionForFieldAccess(Thread* self,
149 Field* field,
150 bool is_read) {
151 self->ThrowNewExceptionF("Ljava/lang/NullPointerException;",
152 "Attempt to %s field '%s' on a null object reference",
153 is_read ? "read from" : "write to",
154 PrettyField(field, true).c_str());
Shih-wei Liao2d831012011-09-28 22:06:53 -0700155}
156
Ian Rogers57b86d42012-03-27 16:05:41 -0700157void ThrowNullPointerExceptionForMethodAccess(Thread* self,
158 Method* caller,
159 uint32_t method_idx,
160 InvokeType type) {
161 const DexFile& dex_file =
162 Runtime::Current()->GetClassLinker()->FindDexFile(caller->GetDeclaringClass()->GetDexCache());
163 std::ostringstream type_stream;
164 type_stream << type;
165 self->ThrowNewExceptionF("Ljava/lang/NullPointerException;",
166 "Attempt to invoke %s method '%s' on a null object reference",
167 type_stream.str().c_str(),
168 PrettyMethod(method_idx, dex_file, true).c_str());
Shih-wei Liao2d831012011-09-28 22:06:53 -0700169}
170
TDYa1273f9137d2012-04-08 15:59:19 -0700171void ThrowNullPointerExceptionFromDexPC(Thread* self, Method* throw_method, uint32_t dex_pc) {
172 const DexFile::CodeItem* code = MethodHelper(throw_method).GetCodeItem();
173 CHECK_LT(dex_pc, code->insns_size_in_code_units_);
174 const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
175 DecodedInstruction dec_insn(instr);
176 switch (instr->Opcode()) {
177 case Instruction::INVOKE_DIRECT:
178 case Instruction::INVOKE_DIRECT_RANGE:
179 ThrowNullPointerExceptionForMethodAccess(self, throw_method, dec_insn.vB, kDirect);
180 break;
181 case Instruction::INVOKE_VIRTUAL:
182 case Instruction::INVOKE_VIRTUAL_RANGE:
183 ThrowNullPointerExceptionForMethodAccess(self, throw_method, dec_insn.vB, kVirtual);
184 break;
185 case Instruction::IGET:
186 case Instruction::IGET_WIDE:
187 case Instruction::IGET_OBJECT:
188 case Instruction::IGET_BOOLEAN:
189 case Instruction::IGET_BYTE:
190 case Instruction::IGET_CHAR:
191 case Instruction::IGET_SHORT: {
192 Field* field =
193 Runtime::Current()->GetClassLinker()->ResolveField(dec_insn.vC, throw_method, false);
194 ThrowNullPointerExceptionForFieldAccess(self, field, true /* read */);
195 break;
196 }
197 case Instruction::IPUT:
198 case Instruction::IPUT_WIDE:
199 case Instruction::IPUT_OBJECT:
200 case Instruction::IPUT_BOOLEAN:
201 case Instruction::IPUT_BYTE:
202 case Instruction::IPUT_CHAR:
203 case Instruction::IPUT_SHORT: {
204 Field* field =
205 Runtime::Current()->GetClassLinker()->ResolveField(dec_insn.vC, throw_method, false);
206 ThrowNullPointerExceptionForFieldAccess(self, field, false /* write */);
207 break;
208 }
209 case Instruction::AGET:
210 case Instruction::AGET_WIDE:
211 case Instruction::AGET_OBJECT:
212 case Instruction::AGET_BOOLEAN:
213 case Instruction::AGET_BYTE:
214 case Instruction::AGET_CHAR:
215 case Instruction::AGET_SHORT:
216 self->ThrowNewException("Ljava/lang/NullPointerException;",
217 "Attempt to read from null array");
218 break;
219 case Instruction::APUT:
220 case Instruction::APUT_WIDE:
221 case Instruction::APUT_OBJECT:
222 case Instruction::APUT_BOOLEAN:
223 case Instruction::APUT_BYTE:
224 case Instruction::APUT_CHAR:
225 case Instruction::APUT_SHORT:
226 self->ThrowNewException("Ljava/lang/NullPointerException;",
227 "Attempt to write to null array");
228 break;
229 default: {
230 const DexFile& dex_file = Runtime::Current()->GetClassLinker()
231 ->FindDexFile(throw_method->GetDeclaringClass()->GetDexCache());
232 std::string message("Null pointer exception during instruction '");
233 message += instr->DumpString(&dex_file);
234 message += "'";
235 self->ThrowNewException("Ljava/lang/NullPointerException;", message.c_str());
236 break;
237 }
238 }
239}
240
Ian Rogers57b86d42012-03-27 16:05:41 -0700241std::string FieldNameFromIndex(const Method* method, uint32_t ref,
242 verifier::VerifyErrorRefType ref_type, bool access) {
Ian Rogersd81871c2011-10-03 13:57:23 -0700243 CHECK_EQ(static_cast<int>(ref_type), static_cast<int>(verifier::VERIFY_ERROR_REF_FIELD));
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700244
245 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
246 const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache());
247
248 const DexFile::FieldId& id = dex_file.GetFieldId(ref);
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700249 std::string class_name(PrettyDescriptor(dex_file.GetFieldDeclaringClassDescriptor(id)));
Ian Rogers0571d352011-11-03 19:51:38 -0700250 const char* field_name = dex_file.StringDataByIdx(id.name_idx_);
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700251 if (!access) {
252 return class_name + "." + field_name;
253 }
254
255 std::string result;
256 result += "tried to access field ";
257 result += class_name + "." + field_name;
258 result += " from class ";
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800259 result += PrettyDescriptor(method->GetDeclaringClass());
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700260 return result;
261}
262
Ian Rogers57b86d42012-03-27 16:05:41 -0700263std::string MethodNameFromIndex(const Method* method, uint32_t ref,
264 verifier::VerifyErrorRefType ref_type, bool access) {
Ian Rogersd81871c2011-10-03 13:57:23 -0700265 CHECK_EQ(static_cast<int>(ref_type), static_cast<int>(verifier::VERIFY_ERROR_REF_METHOD));
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700266
267 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
268 const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache());
269
270 const DexFile::MethodId& id = dex_file.GetMethodId(ref);
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700271 std::string class_name(PrettyDescriptor(dex_file.GetMethodDeclaringClassDescriptor(id)));
Ian Rogers0571d352011-11-03 19:51:38 -0700272 const char* method_name = dex_file.StringDataByIdx(id.name_idx_);
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700273 if (!access) {
274 return class_name + "." + method_name;
275 }
276
277 std::string result;
278 result += "tried to access method ";
Ian Rogers4f0d07c2011-10-06 23:38:47 -0700279 result += class_name + "." + method_name + ":" +
Ian Rogers0571d352011-11-03 19:51:38 -0700280 dex_file.CreateMethodSignature(id.proto_idx_, NULL);
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700281 result += " from class ";
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800282 result += PrettyDescriptor(method->GetDeclaringClass());
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700283 return result;
284}
285
TDYa127b92bcab2012-04-08 00:09:51 -0700286static std::string ClassNameFromIndex(const Method* method, uint32_t ref,
287 verifier::VerifyErrorRefType ref_type, bool access) {
Logan Chien9e5f5c12012-04-10 13:51:45 +0800288 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
289 const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache());
290
291 uint16_t type_idx = 0;
292 if (ref_type == verifier::VERIFY_ERROR_REF_FIELD) {
293 const DexFile::FieldId& id = dex_file.GetFieldId(ref);
294 type_idx = id.class_idx_;
295 } else if (ref_type == verifier::VERIFY_ERROR_REF_METHOD) {
296 const DexFile::MethodId& id = dex_file.GetMethodId(ref);
297 type_idx = id.class_idx_;
298 } else if (ref_type == verifier::VERIFY_ERROR_REF_CLASS) {
299 type_idx = ref;
300 } else {
301 CHECK(false) << static_cast<int>(ref_type);
302 }
303
304 std::string class_name(PrettyDescriptor(dex_file.StringByTypeIdx(type_idx)));
305 if (!access) {
306 return class_name;
307 }
308
309 std::string result;
310 result += "tried to access class ";
311 result += class_name;
312 result += " from class ";
313 result += PrettyDescriptor(method->GetDeclaringClass());
314 return result;
315}
316
317void ThrowVerificationError(Thread* self, const Method* method,
318 int32_t kind, int32_t ref) {
319 verifier::VerifyErrorRefType ref_type =
320 static_cast<verifier::VerifyErrorRefType>(kind >> verifier::kVerifyErrorRefTypeShift);
321
322 const char* exception_class = "Ljava/lang/VerifyError;";
323 std::string msg;
324
325 switch (static_cast<verifier::VerifyError>(kind & ~(0xff << verifier::kVerifyErrorRefTypeShift))) {
326 case verifier::VERIFY_ERROR_NO_CLASS:
327 exception_class = "Ljava/lang/NoClassDefFoundError;";
328 msg = ClassNameFromIndex(method, ref, ref_type, false);
329 break;
330 case verifier::VERIFY_ERROR_NO_FIELD:
331 exception_class = "Ljava/lang/NoSuchFieldError;";
332 msg = FieldNameFromIndex(method, ref, ref_type, false);
333 break;
334 case verifier::VERIFY_ERROR_NO_METHOD:
335 exception_class = "Ljava/lang/NoSuchMethodError;";
336 msg = MethodNameFromIndex(method, ref, ref_type, false);
337 break;
338 case verifier::VERIFY_ERROR_ACCESS_CLASS:
339 exception_class = "Ljava/lang/IllegalAccessError;";
340 msg = ClassNameFromIndex(method, ref, ref_type, true);
341 break;
342 case verifier::VERIFY_ERROR_ACCESS_FIELD:
343 exception_class = "Ljava/lang/IllegalAccessError;";
344 msg = FieldNameFromIndex(method, ref, ref_type, true);
345 break;
346 case verifier::VERIFY_ERROR_ACCESS_METHOD:
347 exception_class = "Ljava/lang/IllegalAccessError;";
348 msg = MethodNameFromIndex(method, ref, ref_type, true);
349 break;
350 case verifier::VERIFY_ERROR_CLASS_CHANGE:
351 exception_class = "Ljava/lang/IncompatibleClassChangeError;";
352 msg = ClassNameFromIndex(method, ref, ref_type, false);
353 break;
354 case verifier::VERIFY_ERROR_INSTANTIATION:
355 exception_class = "Ljava/lang/InstantiationError;";
356 msg = ClassNameFromIndex(method, ref, ref_type, false);
357 break;
358 case verifier::VERIFY_ERROR_BAD_CLASS_SOFT:
359 case verifier::VERIFY_ERROR_BAD_CLASS_HARD:
360 // Generic VerifyError; use default exception, no message.
361 break;
362 case verifier::VERIFY_ERROR_NONE:
363 CHECK(false);
364 break;
365 }
366
367 self->ThrowNewException(exception_class, msg.c_str());
368}
369
Ian Rogers57b86d42012-03-27 16:05:41 -0700370// Helper function to allocate array for FILLED_NEW_ARRAY.
371Array* CheckAndAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count,
372 Thread* self, bool access_check) {
373 if (UNLIKELY(component_count < 0)) {
374 self->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", component_count);
375 return NULL; // Failure
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700376 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700377 Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
378 if (UNLIKELY(klass == NULL)) { // Not in dex cache so try to resolve
379 klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
380 if (klass == NULL) { // Error
381 DCHECK(Thread::Current()->IsExceptionPending());
382 return NULL; // Failure
Ian Rogers19846512012-02-24 11:42:47 -0800383 }
Ian Rogersea2a11d2011-10-11 16:48:51 -0700384 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700385 if (UNLIKELY(klass->IsPrimitive() && !klass->IsPrimitiveInt())) {
386 if (klass->IsPrimitiveLong() || klass->IsPrimitiveDouble()) {
387 Thread::Current()->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
388 "Bad filled array request for type %s",
389 PrettyDescriptor(klass).c_str());
Ian Rogers573db4a2011-12-13 15:30:50 -0800390 } else {
Ian Rogers57b86d42012-03-27 16:05:41 -0700391 Thread::Current()->ThrowNewExceptionF("Ljava/lang/InternalError;",
392 "Found type %s; filled-new-array not implemented for anything but \'int\'",
393 PrettyDescriptor(klass).c_str());
Ian Rogers573db4a2011-12-13 15:30:50 -0800394 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700395 return NULL; // Failure
Ian Rogersad25ac52011-10-04 19:13:33 -0700396 } else {
Ian Rogers57b86d42012-03-27 16:05:41 -0700397 if (access_check) {
398 Class* referrer = method->GetDeclaringClass();
399 if (UNLIKELY(!referrer->CanAccess(klass))) {
400 ThrowNewIllegalAccessErrorClass(self, referrer, klass);
401 return NULL; // Failure
402 }
Ian Rogers60db5ab2012-02-20 17:02:00 -0800403 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700404 DCHECK(klass->IsArrayClass()) << PrettyClass(klass);
405 return Array::Alloc(klass, component_count);
406 }
407}
408
409// Slow path field resolution and declaring class initialization
410Field* FindFieldFromCode(uint32_t field_idx, const Method* referrer, Thread* self,
411 bool is_static, bool is_primitive, bool is_set, size_t expected_size) {
412 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
413 Field* resolved_field = class_linker->ResolveField(field_idx, referrer, is_static);
414 if (UNLIKELY(resolved_field == NULL)) {
415 DCHECK(self->IsExceptionPending()); // Throw exception and unwind
416 return NULL; // failure
417 } else {
418 Class* fields_class = resolved_field->GetDeclaringClass();
419 Class* referring_class = referrer->GetDeclaringClass();
Ian Rogerse2645d32012-04-11 14:42:42 -0700420 if (UNLIKELY(!referring_class->CanAccess(fields_class) ||
421 !referring_class->CanAccessMember(fields_class,
422 resolved_field->GetAccessFlags()))) {
423 // The referring class can't access the resolved field, this may occur as a result of a
424 // protected field being made public by a sub-class. Resort to the dex file to determine
425 // the correct class for the access check.
426 const DexFile& dex_file = class_linker->FindDexFile(referring_class->GetDexCache());
427 fields_class = class_linker->ResolveType(dex_file,
428 dex_file.GetFieldId(field_idx).class_idx_,
429 referring_class);
430 if (UNLIKELY(!referring_class->CanAccess(fields_class))) {
431 ThrowNewIllegalAccessErrorClass(self, referring_class, fields_class);
432 return NULL; // failure
433 } else if (UNLIKELY(!referring_class->CanAccessMember(fields_class,
434 resolved_field->GetAccessFlags()))) {
435 ThrowNewIllegalAccessErrorField(self, referring_class, resolved_field);
436 return NULL; // failure
437 }
438 }
439 if (UNLIKELY(is_set && resolved_field->IsFinal() && (fields_class != referring_class))) {
Ian Rogers57b86d42012-03-27 16:05:41 -0700440 ThrowNewIllegalAccessErrorFinalField(self, referrer, resolved_field);
441 return NULL; // failure
442 } else {
443 FieldHelper fh(resolved_field);
444 if (UNLIKELY(fh.IsPrimitiveType() != is_primitive ||
445 fh.FieldSize() != expected_size)) {
446 self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
447 "Attempted read of %zd-bit %s on field '%s'",
448 expected_size * (32 / sizeof(int32_t)),
449 is_primitive ? "primitive" : "non-primitive",
450 PrettyField(resolved_field, true).c_str());
451 return NULL; // failure
452 } else if (!is_static) {
453 // instance fields must be being accessed on an initialized class
454 return resolved_field;
Ian Rogers60db5ab2012-02-20 17:02:00 -0800455 } else {
Ian Rogers57b86d42012-03-27 16:05:41 -0700456 // If the class is already initializing, we must be inside <clinit>, or
457 // we'd still be waiting for the lock.
458 if (fields_class->IsInitializing()) {
459 return resolved_field;
Ian Rogers0045a292012-03-31 21:08:41 -0700460 } else if (Runtime::Current()->GetClassLinker()->EnsureInitialized(fields_class, true, true)) {
Ian Rogers57b86d42012-03-27 16:05:41 -0700461 return resolved_field;
Ian Rogers60db5ab2012-02-20 17:02:00 -0800462 } else {
Ian Rogers57b86d42012-03-27 16:05:41 -0700463 DCHECK(self->IsExceptionPending()); // Throw exception and unwind
464 return NULL; // failure
Ian Rogers60db5ab2012-02-20 17:02:00 -0800465 }
466 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700467 }
468 }
469}
470
471// Slow path method resolution
472Method* FindMethodFromCode(uint32_t method_idx, Object* this_object, const Method* referrer,
473 Thread* self, bool access_check, InvokeType type) {
474 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
475 bool is_direct = type == kStatic || type == kDirect;
476 Method* resolved_method = class_linker->ResolveMethod(method_idx, referrer, is_direct);
477 if (UNLIKELY(resolved_method == NULL)) {
478 DCHECK(self->IsExceptionPending()); // Throw exception and unwind
479 return NULL; // failure
480 } else {
481 if (!access_check) {
482 if (is_direct) {
483 return resolved_method;
484 } else if (type == kInterface) {
485 Method* interface_method =
486 this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
487 if (UNLIKELY(interface_method == NULL)) {
488 ThrowNewIncompatibleClassChangeErrorClassForInterfaceDispatch(self, referrer,
489 resolved_method,
490 this_object);
491 return NULL; // failure
492 } else {
493 return interface_method;
494 }
Ian Rogers60db5ab2012-02-20 17:02:00 -0800495 } else {
Ian Rogers57b86d42012-03-27 16:05:41 -0700496 ObjectArray<Method>* vtable;
497 uint16_t vtable_index = resolved_method->GetMethodIndex();
498 if (type == kSuper) {
499 vtable = referrer->GetDeclaringClass()->GetSuperClass()->GetVTable();
500 } else {
501 vtable = this_object->GetClass()->GetVTable();
502 }
503 // TODO: eliminate bounds check?
504 return vtable->Get(vtable_index);
505 }
506 } else {
507 Class* methods_class = resolved_method->GetDeclaringClass();
508 Class* referring_class = referrer->GetDeclaringClass();
509 if (UNLIKELY(!referring_class->CanAccess(methods_class) ||
510 !referring_class->CanAccessMember(methods_class,
511 resolved_method->GetAccessFlags()))) {
512 // The referring class can't access the resolved method, this may occur as a result of a
513 // protected method being made public by implementing an interface that re-declares the
514 // method public. Resort to the dex file to determine the correct class for the access check
515 const DexFile& dex_file = class_linker->FindDexFile(referring_class->GetDexCache());
516 methods_class = class_linker->ResolveType(dex_file,
517 dex_file.GetMethodId(method_idx).class_idx_,
518 referring_class);
519 if (UNLIKELY(!referring_class->CanAccess(methods_class))) {
520 ThrowNewIllegalAccessErrorClassForMethodDispatch(self, referring_class, methods_class,
521 referrer, resolved_method, type);
522 return NULL; // failure
523 } else if (UNLIKELY(!referring_class->CanAccessMember(methods_class,
524 resolved_method->GetAccessFlags()))) {
525 ThrowNewIllegalAccessErrorMethod(self, referring_class, resolved_method);
526 return NULL; // failure
527 }
528 }
529 if (is_direct) {
530 return resolved_method;
531 } else if (type == kInterface) {
532 Method* interface_method =
533 this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
534 if (UNLIKELY(interface_method == NULL)) {
535 ThrowNewIncompatibleClassChangeErrorClassForInterfaceDispatch(self, referrer,
536 resolved_method,
537 this_object);
538 return NULL; // failure
539 } else {
540 return interface_method;
541 }
542 } else {
543 ObjectArray<Method>* vtable;
544 uint16_t vtable_index = resolved_method->GetMethodIndex();
545 if (type == kSuper) {
546 Class* super_class = referring_class->GetSuperClass();
547 if (LIKELY(super_class != NULL)) {
548 vtable = referring_class->GetSuperClass()->GetVTable();
549 } else {
550 vtable = NULL;
551 }
552 } else {
553 vtable = this_object->GetClass()->GetVTable();
554 }
555 if (LIKELY(vtable != NULL &&
556 vtable_index < static_cast<uint32_t>(vtable->GetLength()))) {
557 return vtable->GetWithoutChecks(vtable_index);
558 } else {
559 // Behavior to agree with that of the verifier
560 self->ThrowNewExceptionF("Ljava/lang/NoSuchMethodError;",
561 "attempt to invoke %s method '%s' from '%s'"
562 " using incorrect form of method dispatch",
563 (type == kSuper ? "super class" : "virtual"),
564 PrettyMethod(resolved_method).c_str(),
565 PrettyMethod(referrer).c_str());
566 return NULL; // failure
567 }
Ian Rogers60db5ab2012-02-20 17:02:00 -0800568 }
569 }
570 }
Ian Rogers60db5ab2012-02-20 17:02:00 -0800571}
572
Ian Rogers57b86d42012-03-27 16:05:41 -0700573Class* ResolveVerifyAndClinit(uint32_t type_idx, const Method* referrer, Thread* self,
574 bool can_run_clinit, bool verify_access) {
575 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
576 Class* klass = class_linker->ResolveType(type_idx, referrer);
577 if (UNLIKELY(klass == NULL)) {
jeffhao441d9122012-03-21 17:29:10 -0700578 CHECK(self->IsExceptionPending());
Ian Rogers57b86d42012-03-27 16:05:41 -0700579 return NULL; // Failure - Indicate to caller to deliver exception
jeffhao441d9122012-03-21 17:29:10 -0700580 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700581 // Perform access check if necessary.
582 Class* referring_class = referrer->GetDeclaringClass();
583 if (verify_access && UNLIKELY(!referring_class->CanAccess(klass))) {
584 ThrowNewIllegalAccessErrorClass(self, referring_class, klass);
585 return NULL; // Failure - Indicate to caller to deliver exception
Ian Rogers14b1b242011-10-11 18:54:34 -0700586 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700587 // If we're just implementing const-class, we shouldn't call <clinit>.
588 if (!can_run_clinit) {
589 return klass;
Ian Rogersdfcdf1a2011-10-10 17:50:35 -0700590 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700591 // If we are the <clinit> of this class, just return our storage.
592 //
593 // Do not set the DexCache InitializedStaticStorage, since that implies <clinit> has finished
594 // running.
595 if (klass == referring_class && MethodHelper(referrer).IsClassInitializer()) {
596 return klass;
Ian Rogersdfcdf1a2011-10-10 17:50:35 -0700597 }
Ian Rogers0045a292012-03-31 21:08:41 -0700598 if (!class_linker->EnsureInitialized(klass, true, true)) {
Ian Rogers57b86d42012-03-27 16:05:41 -0700599 CHECK(self->IsExceptionPending());
600 return NULL; // Failure - Indicate to caller to deliver exception
Ian Rogersdfcdf1a2011-10-10 17:50:35 -0700601 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700602 referrer->GetDexCacheInitializedStaticStorage()->Set(type_idx, klass);
603 return klass;
Shih-wei Liao2d831012011-09-28 22:06:53 -0700604}
605
TDYa1275bb86012012-04-11 05:57:28 -0700606void ThrowNewUndeclaredThrowableException(Thread* self, JNIEnv* env, Throwable* exception) {
607 ScopedLocalRef<jclass> jlr_UTE_class(env,
608 env->FindClass("java/lang/reflect/UndeclaredThrowableException"));
609 if (jlr_UTE_class.get() == NULL) {
610 LOG(ERROR) << "Couldn't throw new \"java/lang/reflect/UndeclaredThrowableException\"";
611 } else {
612 jmethodID jlre_UTE_constructor = env->GetMethodID(jlr_UTE_class.get(), "<init>",
613 "(Ljava/lang/Throwable;)V");
614 jthrowable jexception = AddLocalReference<jthrowable>(env, exception);
615 ScopedLocalRef<jthrowable> jlr_UTE(env,
616 reinterpret_cast<jthrowable>(env->NewObject(jlr_UTE_class.get(), jlre_UTE_constructor,
617 jexception)));
618 int rc = env->Throw(jlr_UTE.get());
619 if (rc != JNI_OK) {
620 LOG(ERROR) << "Couldn't throw new \"java/lang/reflect/UndeclaredThrowableException\"";
621 }
622 }
623 CHECK(self->IsExceptionPending());
624}
625
Shih-wei Liao2d831012011-09-28 22:06:53 -0700626} // namespace art