blob: f8b40a258a072bee1067740c395ea2e4214c819d [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
jeffhao41005dd2012-05-09 17:58:52 -070021double art_l2d(int64_t l) {
22 return (double) l;
23}
24
25float art_l2f(int64_t l) {
26 return (float) l;
27}
Shih-wei Liao2d831012011-09-28 22:06:53 -070028
Ian Rogers776ac1f2012-04-13 23:36:36 -070029/*
30 * Float/double conversion requires clamping to min and max of integer form. If
31 * target doesn't support this normally, use these.
32 */
jeffhao41005dd2012-05-09 17:58:52 -070033int64_t art_d2l(double d) {
Ian Rogers776ac1f2012-04-13 23:36:36 -070034 static const double kMaxLong = (double) (int64_t) 0x7fffffffffffffffULL;
35 static const double kMinLong = (double) (int64_t) 0x8000000000000000ULL;
36 if (d >= kMaxLong) {
37 return (int64_t) 0x7fffffffffffffffULL;
38 } else if (d <= kMinLong) {
39 return (int64_t) 0x8000000000000000ULL;
40 } else if (d != d) { // NaN case
41 return 0;
42 } else {
43 return (int64_t) d;
44 }
45}
46
jeffhao41005dd2012-05-09 17:58:52 -070047int64_t art_f2l(float f) {
Ian Rogers776ac1f2012-04-13 23:36:36 -070048 static const float kMaxLong = (float) (int64_t) 0x7fffffffffffffffULL;
49 static const float kMinLong = (float) (int64_t) 0x8000000000000000ULL;
50 if (f >= kMaxLong) {
51 return (int64_t) 0x7fffffffffffffffULL;
52 } else if (f <= kMinLong) {
53 return (int64_t) 0x8000000000000000ULL;
54 } else if (f != f) { // NaN case
55 return 0;
56 } else {
57 return (int64_t) f;
58 }
59}
60
jeffhao41005dd2012-05-09 17:58:52 -070061int32_t art_d2i(double d) {
Ian Rogers776ac1f2012-04-13 23:36:36 -070062 static const double kMaxInt = (double) (int32_t) 0x7fffffffUL;
63 static const double kMinInt = (double) (int32_t) 0x80000000UL;
64 if (d >= kMaxInt) {
65 return (int32_t) 0x7fffffffUL;
66 } else if (d <= kMinInt) {
67 return (int32_t) 0x80000000UL;
68 } else if (d != d) { // NaN case
69 return 0;
70 } else {
71 return (int32_t) d;
72 }
73}
74
jeffhao41005dd2012-05-09 17:58:52 -070075int32_t art_f2i(float f) {
Ian Rogers776ac1f2012-04-13 23:36:36 -070076 static const float kMaxInt = (float) (int32_t) 0x7fffffffUL;
77 static const float kMinInt = (float) (int32_t) 0x80000000UL;
78 if (f >= kMaxInt) {
79 return (int32_t) 0x7fffffffUL;
80 } else if (f <= kMinInt) {
81 return (int32_t) 0x80000000UL;
82 } else if (f != f) { // NaN case
83 return 0;
84 } else {
85 return (int32_t) f;
86 }
87}
88
jeffhao41005dd2012-05-09 17:58:52 -070089namespace art {
90
Ian Rogers57b86d42012-03-27 16:05:41 -070091void ThrowNewIllegalAccessErrorClass(Thread* self,
92 Class* referrer,
93 Class* accessed) {
94 self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
95 "illegal class access: '%s' -> '%s'",
96 PrettyDescriptor(referrer).c_str(),
97 PrettyDescriptor(accessed).c_str());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -080098}
99
Ian Rogers57b86d42012-03-27 16:05:41 -0700100void ThrowNewIllegalAccessErrorClassForMethodDispatch(Thread* self,
101 Class* referrer,
102 Class* accessed,
103 const Method* caller,
104 const Method* called,
105 InvokeType type) {
106 std::ostringstream type_stream;
107 type_stream << type;
108 self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
109 "illegal class access ('%s' -> '%s')"
110 "in attempt to invoke %s method '%s' from '%s'",
111 PrettyDescriptor(referrer).c_str(),
112 PrettyDescriptor(accessed).c_str(),
113 type_stream.str().c_str(),
114 PrettyMethod(called).c_str(),
115 PrettyMethod(caller).c_str());
buzbee44b412b2012-02-04 08:50:53 -0800116}
117
Ian Rogers57b86d42012-03-27 16:05:41 -0700118void ThrowNewIncompatibleClassChangeErrorClassForInterfaceDispatch(Thread* self,
119 const Method* referrer,
120 const Method* interface_method,
121 Object* this_object) {
122 self->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
123 "class '%s' does not implement interface '%s' in call to '%s' from '%s'",
124 PrettyDescriptor(this_object->GetClass()).c_str(),
125 PrettyDescriptor(interface_method->GetDeclaringClass()).c_str(),
126 PrettyMethod(interface_method).c_str(), PrettyMethod(referrer).c_str());
Shih-wei Liao2d831012011-09-28 22:06:53 -0700127}
128
Ian Rogers57b86d42012-03-27 16:05:41 -0700129void ThrowNewIllegalAccessErrorField(Thread* self,
130 Class* referrer,
131 Field* accessed) {
132 self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
133 "Field '%s' is inaccessible to class '%s'",
134 PrettyField(accessed, false).c_str(),
135 PrettyDescriptor(referrer).c_str());
Shih-wei Liao2d831012011-09-28 22:06:53 -0700136}
137
Ian Rogers57b86d42012-03-27 16:05:41 -0700138void ThrowNewIllegalAccessErrorFinalField(Thread* self,
139 const Method* referrer,
140 Field* accessed) {
141 self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
142 "Final field '%s' cannot be written to by method '%s'",
143 PrettyField(accessed, false).c_str(),
144 PrettyMethod(referrer).c_str());
Shih-wei Liao2d831012011-09-28 22:06:53 -0700145}
146
Ian Rogers57b86d42012-03-27 16:05:41 -0700147void ThrowNewIllegalAccessErrorMethod(Thread* self,
148 Class* referrer,
149 Method* accessed) {
150 self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
151 "Method '%s' is inaccessible to class '%s'",
152 PrettyMethod(accessed).c_str(),
153 PrettyDescriptor(referrer).c_str());
Shih-wei Liao2d831012011-09-28 22:06:53 -0700154}
155
Ian Rogers57b86d42012-03-27 16:05:41 -0700156void ThrowNullPointerExceptionForFieldAccess(Thread* self,
157 Field* field,
158 bool is_read) {
159 self->ThrowNewExceptionF("Ljava/lang/NullPointerException;",
160 "Attempt to %s field '%s' on a null object reference",
161 is_read ? "read from" : "write to",
162 PrettyField(field, true).c_str());
Shih-wei Liao2d831012011-09-28 22:06:53 -0700163}
164
Ian Rogers57b86d42012-03-27 16:05:41 -0700165void ThrowNullPointerExceptionForMethodAccess(Thread* self,
166 Method* caller,
167 uint32_t method_idx,
168 InvokeType type) {
169 const DexFile& dex_file =
170 Runtime::Current()->GetClassLinker()->FindDexFile(caller->GetDeclaringClass()->GetDexCache());
171 std::ostringstream type_stream;
172 type_stream << type;
173 self->ThrowNewExceptionF("Ljava/lang/NullPointerException;",
174 "Attempt to invoke %s method '%s' on a null object reference",
175 type_stream.str().c_str(),
176 PrettyMethod(method_idx, dex_file, true).c_str());
Shih-wei Liao2d831012011-09-28 22:06:53 -0700177}
178
TDYa1273f9137d2012-04-08 15:59:19 -0700179void ThrowNullPointerExceptionFromDexPC(Thread* self, Method* throw_method, uint32_t dex_pc) {
180 const DexFile::CodeItem* code = MethodHelper(throw_method).GetCodeItem();
181 CHECK_LT(dex_pc, code->insns_size_in_code_units_);
182 const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
183 DecodedInstruction dec_insn(instr);
184 switch (instr->Opcode()) {
185 case Instruction::INVOKE_DIRECT:
186 case Instruction::INVOKE_DIRECT_RANGE:
187 ThrowNullPointerExceptionForMethodAccess(self, throw_method, dec_insn.vB, kDirect);
188 break;
189 case Instruction::INVOKE_VIRTUAL:
190 case Instruction::INVOKE_VIRTUAL_RANGE:
191 ThrowNullPointerExceptionForMethodAccess(self, throw_method, dec_insn.vB, kVirtual);
192 break;
193 case Instruction::IGET:
194 case Instruction::IGET_WIDE:
195 case Instruction::IGET_OBJECT:
196 case Instruction::IGET_BOOLEAN:
197 case Instruction::IGET_BYTE:
198 case Instruction::IGET_CHAR:
199 case Instruction::IGET_SHORT: {
200 Field* field =
201 Runtime::Current()->GetClassLinker()->ResolveField(dec_insn.vC, throw_method, false);
202 ThrowNullPointerExceptionForFieldAccess(self, field, true /* read */);
203 break;
204 }
205 case Instruction::IPUT:
206 case Instruction::IPUT_WIDE:
207 case Instruction::IPUT_OBJECT:
208 case Instruction::IPUT_BOOLEAN:
209 case Instruction::IPUT_BYTE:
210 case Instruction::IPUT_CHAR:
211 case Instruction::IPUT_SHORT: {
212 Field* field =
213 Runtime::Current()->GetClassLinker()->ResolveField(dec_insn.vC, throw_method, false);
214 ThrowNullPointerExceptionForFieldAccess(self, field, false /* write */);
215 break;
216 }
217 case Instruction::AGET:
218 case Instruction::AGET_WIDE:
219 case Instruction::AGET_OBJECT:
220 case Instruction::AGET_BOOLEAN:
221 case Instruction::AGET_BYTE:
222 case Instruction::AGET_CHAR:
223 case Instruction::AGET_SHORT:
224 self->ThrowNewException("Ljava/lang/NullPointerException;",
225 "Attempt to read from null array");
226 break;
227 case Instruction::APUT:
228 case Instruction::APUT_WIDE:
229 case Instruction::APUT_OBJECT:
230 case Instruction::APUT_BOOLEAN:
231 case Instruction::APUT_BYTE:
232 case Instruction::APUT_CHAR:
233 case Instruction::APUT_SHORT:
234 self->ThrowNewException("Ljava/lang/NullPointerException;",
235 "Attempt to write to null array");
236 break;
237 default: {
238 const DexFile& dex_file = Runtime::Current()->GetClassLinker()
239 ->FindDexFile(throw_method->GetDeclaringClass()->GetDexCache());
240 std::string message("Null pointer exception during instruction '");
241 message += instr->DumpString(&dex_file);
242 message += "'";
243 self->ThrowNewException("Ljava/lang/NullPointerException;", message.c_str());
244 break;
245 }
246 }
247}
248
Ian Rogers57b86d42012-03-27 16:05:41 -0700249std::string FieldNameFromIndex(const Method* method, uint32_t ref,
250 verifier::VerifyErrorRefType ref_type, bool access) {
Ian Rogersd81871c2011-10-03 13:57:23 -0700251 CHECK_EQ(static_cast<int>(ref_type), static_cast<int>(verifier::VERIFY_ERROR_REF_FIELD));
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700252
253 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
254 const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache());
255
256 const DexFile::FieldId& id = dex_file.GetFieldId(ref);
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700257 std::string class_name(PrettyDescriptor(dex_file.GetFieldDeclaringClassDescriptor(id)));
Ian Rogers0571d352011-11-03 19:51:38 -0700258 const char* field_name = dex_file.StringDataByIdx(id.name_idx_);
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700259 if (!access) {
260 return class_name + "." + field_name;
261 }
262
263 std::string result;
264 result += "tried to access field ";
265 result += class_name + "." + field_name;
266 result += " from class ";
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800267 result += PrettyDescriptor(method->GetDeclaringClass());
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700268 return result;
269}
270
Ian Rogers57b86d42012-03-27 16:05:41 -0700271std::string MethodNameFromIndex(const Method* method, uint32_t ref,
272 verifier::VerifyErrorRefType ref_type, bool access) {
Ian Rogersd81871c2011-10-03 13:57:23 -0700273 CHECK_EQ(static_cast<int>(ref_type), static_cast<int>(verifier::VERIFY_ERROR_REF_METHOD));
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700274
275 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
276 const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache());
277
278 const DexFile::MethodId& id = dex_file.GetMethodId(ref);
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700279 std::string class_name(PrettyDescriptor(dex_file.GetMethodDeclaringClassDescriptor(id)));
Ian Rogers0571d352011-11-03 19:51:38 -0700280 const char* method_name = dex_file.StringDataByIdx(id.name_idx_);
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700281 if (!access) {
282 return class_name + "." + method_name;
283 }
284
285 std::string result;
286 result += "tried to access method ";
Ian Rogers4f0d07c2011-10-06 23:38:47 -0700287 result += class_name + "." + method_name + ":" +
Ian Rogers0571d352011-11-03 19:51:38 -0700288 dex_file.CreateMethodSignature(id.proto_idx_, NULL);
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700289 result += " from class ";
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800290 result += PrettyDescriptor(method->GetDeclaringClass());
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700291 return result;
292}
293
TDYa127b92bcab2012-04-08 00:09:51 -0700294static std::string ClassNameFromIndex(const Method* method, uint32_t ref,
295 verifier::VerifyErrorRefType ref_type, bool access) {
Logan Chien9e5f5c12012-04-10 13:51:45 +0800296 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
297 const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache());
298
299 uint16_t type_idx = 0;
300 if (ref_type == verifier::VERIFY_ERROR_REF_FIELD) {
301 const DexFile::FieldId& id = dex_file.GetFieldId(ref);
302 type_idx = id.class_idx_;
303 } else if (ref_type == verifier::VERIFY_ERROR_REF_METHOD) {
304 const DexFile::MethodId& id = dex_file.GetMethodId(ref);
305 type_idx = id.class_idx_;
306 } else if (ref_type == verifier::VERIFY_ERROR_REF_CLASS) {
307 type_idx = ref;
308 } else {
309 CHECK(false) << static_cast<int>(ref_type);
310 }
311
312 std::string class_name(PrettyDescriptor(dex_file.StringByTypeIdx(type_idx)));
313 if (!access) {
314 return class_name;
315 }
316
317 std::string result;
318 result += "tried to access class ";
319 result += class_name;
320 result += " from class ";
321 result += PrettyDescriptor(method->GetDeclaringClass());
322 return result;
323}
324
325void ThrowVerificationError(Thread* self, const Method* method,
326 int32_t kind, int32_t ref) {
327 verifier::VerifyErrorRefType ref_type =
328 static_cast<verifier::VerifyErrorRefType>(kind >> verifier::kVerifyErrorRefTypeShift);
329
330 const char* exception_class = "Ljava/lang/VerifyError;";
331 std::string msg;
332
333 switch (static_cast<verifier::VerifyError>(kind & ~(0xff << verifier::kVerifyErrorRefTypeShift))) {
334 case verifier::VERIFY_ERROR_NO_CLASS:
335 exception_class = "Ljava/lang/NoClassDefFoundError;";
336 msg = ClassNameFromIndex(method, ref, ref_type, false);
337 break;
338 case verifier::VERIFY_ERROR_NO_FIELD:
339 exception_class = "Ljava/lang/NoSuchFieldError;";
340 msg = FieldNameFromIndex(method, ref, ref_type, false);
341 break;
342 case verifier::VERIFY_ERROR_NO_METHOD:
343 exception_class = "Ljava/lang/NoSuchMethodError;";
344 msg = MethodNameFromIndex(method, ref, ref_type, false);
345 break;
346 case verifier::VERIFY_ERROR_ACCESS_CLASS:
347 exception_class = "Ljava/lang/IllegalAccessError;";
348 msg = ClassNameFromIndex(method, ref, ref_type, true);
349 break;
350 case verifier::VERIFY_ERROR_ACCESS_FIELD:
351 exception_class = "Ljava/lang/IllegalAccessError;";
352 msg = FieldNameFromIndex(method, ref, ref_type, true);
353 break;
354 case verifier::VERIFY_ERROR_ACCESS_METHOD:
355 exception_class = "Ljava/lang/IllegalAccessError;";
356 msg = MethodNameFromIndex(method, ref, ref_type, true);
357 break;
358 case verifier::VERIFY_ERROR_CLASS_CHANGE:
359 exception_class = "Ljava/lang/IncompatibleClassChangeError;";
360 msg = ClassNameFromIndex(method, ref, ref_type, false);
361 break;
362 case verifier::VERIFY_ERROR_INSTANTIATION:
363 exception_class = "Ljava/lang/InstantiationError;";
364 msg = ClassNameFromIndex(method, ref, ref_type, false);
365 break;
366 case verifier::VERIFY_ERROR_BAD_CLASS_SOFT:
367 case verifier::VERIFY_ERROR_BAD_CLASS_HARD:
368 // Generic VerifyError; use default exception, no message.
369 break;
Logan Chien9e5f5c12012-04-10 13:51:45 +0800370 }
371
372 self->ThrowNewException(exception_class, msg.c_str());
373}
374
Ian Rogers57b86d42012-03-27 16:05:41 -0700375// Helper function to allocate array for FILLED_NEW_ARRAY.
376Array* CheckAndAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count,
377 Thread* self, bool access_check) {
378 if (UNLIKELY(component_count < 0)) {
379 self->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", component_count);
380 return NULL; // Failure
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700381 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700382 Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
383 if (UNLIKELY(klass == NULL)) { // Not in dex cache so try to resolve
384 klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
385 if (klass == NULL) { // Error
386 DCHECK(Thread::Current()->IsExceptionPending());
387 return NULL; // Failure
Ian Rogers19846512012-02-24 11:42:47 -0800388 }
Ian Rogersea2a11d2011-10-11 16:48:51 -0700389 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700390 if (UNLIKELY(klass->IsPrimitive() && !klass->IsPrimitiveInt())) {
391 if (klass->IsPrimitiveLong() || klass->IsPrimitiveDouble()) {
392 Thread::Current()->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
393 "Bad filled array request for type %s",
394 PrettyDescriptor(klass).c_str());
Ian Rogers573db4a2011-12-13 15:30:50 -0800395 } else {
Ian Rogers57b86d42012-03-27 16:05:41 -0700396 Thread::Current()->ThrowNewExceptionF("Ljava/lang/InternalError;",
397 "Found type %s; filled-new-array not implemented for anything but \'int\'",
398 PrettyDescriptor(klass).c_str());
Ian Rogers573db4a2011-12-13 15:30:50 -0800399 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700400 return NULL; // Failure
Ian Rogersad25ac52011-10-04 19:13:33 -0700401 } else {
Ian Rogers57b86d42012-03-27 16:05:41 -0700402 if (access_check) {
403 Class* referrer = method->GetDeclaringClass();
404 if (UNLIKELY(!referrer->CanAccess(klass))) {
405 ThrowNewIllegalAccessErrorClass(self, referrer, klass);
406 return NULL; // Failure
407 }
Ian Rogers60db5ab2012-02-20 17:02:00 -0800408 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700409 DCHECK(klass->IsArrayClass()) << PrettyClass(klass);
410 return Array::Alloc(klass, component_count);
411 }
412}
413
414// Slow path field resolution and declaring class initialization
415Field* FindFieldFromCode(uint32_t field_idx, const Method* referrer, Thread* self,
416 bool is_static, bool is_primitive, bool is_set, size_t expected_size) {
417 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
418 Field* resolved_field = class_linker->ResolveField(field_idx, referrer, is_static);
419 if (UNLIKELY(resolved_field == NULL)) {
420 DCHECK(self->IsExceptionPending()); // Throw exception and unwind
421 return NULL; // failure
422 } else {
423 Class* fields_class = resolved_field->GetDeclaringClass();
424 Class* referring_class = referrer->GetDeclaringClass();
Ian Rogerse2645d32012-04-11 14:42:42 -0700425 if (UNLIKELY(!referring_class->CanAccess(fields_class) ||
426 !referring_class->CanAccessMember(fields_class,
427 resolved_field->GetAccessFlags()))) {
428 // The referring class can't access the resolved field, this may occur as a result of a
429 // protected field being made public by a sub-class. Resort to the dex file to determine
430 // the correct class for the access check.
431 const DexFile& dex_file = class_linker->FindDexFile(referring_class->GetDexCache());
432 fields_class = class_linker->ResolveType(dex_file,
433 dex_file.GetFieldId(field_idx).class_idx_,
434 referring_class);
435 if (UNLIKELY(!referring_class->CanAccess(fields_class))) {
436 ThrowNewIllegalAccessErrorClass(self, referring_class, fields_class);
437 return NULL; // failure
438 } else if (UNLIKELY(!referring_class->CanAccessMember(fields_class,
439 resolved_field->GetAccessFlags()))) {
440 ThrowNewIllegalAccessErrorField(self, referring_class, resolved_field);
441 return NULL; // failure
442 }
443 }
444 if (UNLIKELY(is_set && resolved_field->IsFinal() && (fields_class != referring_class))) {
Ian Rogers57b86d42012-03-27 16:05:41 -0700445 ThrowNewIllegalAccessErrorFinalField(self, referrer, resolved_field);
446 return NULL; // failure
447 } else {
448 FieldHelper fh(resolved_field);
449 if (UNLIKELY(fh.IsPrimitiveType() != is_primitive ||
450 fh.FieldSize() != expected_size)) {
451 self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
452 "Attempted read of %zd-bit %s on field '%s'",
453 expected_size * (32 / sizeof(int32_t)),
454 is_primitive ? "primitive" : "non-primitive",
455 PrettyField(resolved_field, true).c_str());
456 return NULL; // failure
457 } else if (!is_static) {
458 // instance fields must be being accessed on an initialized class
459 return resolved_field;
Ian Rogers60db5ab2012-02-20 17:02:00 -0800460 } else {
Ian Rogers57b86d42012-03-27 16:05:41 -0700461 // If the class is already initializing, we must be inside <clinit>, or
462 // we'd still be waiting for the lock.
463 if (fields_class->IsInitializing()) {
464 return resolved_field;
Ian Rogers0045a292012-03-31 21:08:41 -0700465 } else if (Runtime::Current()->GetClassLinker()->EnsureInitialized(fields_class, true, true)) {
Ian Rogers57b86d42012-03-27 16:05:41 -0700466 return resolved_field;
Ian Rogers60db5ab2012-02-20 17:02:00 -0800467 } else {
Ian Rogers57b86d42012-03-27 16:05:41 -0700468 DCHECK(self->IsExceptionPending()); // Throw exception and unwind
469 return NULL; // failure
Ian Rogers60db5ab2012-02-20 17:02:00 -0800470 }
471 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700472 }
473 }
474}
475
476// Slow path method resolution
477Method* FindMethodFromCode(uint32_t method_idx, Object* this_object, const Method* referrer,
478 Thread* self, bool access_check, InvokeType type) {
479 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
480 bool is_direct = type == kStatic || type == kDirect;
481 Method* resolved_method = class_linker->ResolveMethod(method_idx, referrer, is_direct);
482 if (UNLIKELY(resolved_method == NULL)) {
483 DCHECK(self->IsExceptionPending()); // Throw exception and unwind
484 return NULL; // failure
485 } else {
486 if (!access_check) {
487 if (is_direct) {
488 return resolved_method;
489 } else if (type == kInterface) {
490 Method* interface_method =
491 this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
492 if (UNLIKELY(interface_method == NULL)) {
493 ThrowNewIncompatibleClassChangeErrorClassForInterfaceDispatch(self, referrer,
494 resolved_method,
495 this_object);
496 return NULL; // failure
497 } else {
498 return interface_method;
499 }
Ian Rogers60db5ab2012-02-20 17:02:00 -0800500 } else {
Ian Rogers57b86d42012-03-27 16:05:41 -0700501 ObjectArray<Method>* vtable;
502 uint16_t vtable_index = resolved_method->GetMethodIndex();
503 if (type == kSuper) {
504 vtable = referrer->GetDeclaringClass()->GetSuperClass()->GetVTable();
505 } else {
506 vtable = this_object->GetClass()->GetVTable();
507 }
508 // TODO: eliminate bounds check?
509 return vtable->Get(vtable_index);
510 }
511 } else {
512 Class* methods_class = resolved_method->GetDeclaringClass();
513 Class* referring_class = referrer->GetDeclaringClass();
514 if (UNLIKELY(!referring_class->CanAccess(methods_class) ||
515 !referring_class->CanAccessMember(methods_class,
516 resolved_method->GetAccessFlags()))) {
517 // The referring class can't access the resolved method, this may occur as a result of a
518 // protected method being made public by implementing an interface that re-declares the
519 // method public. Resort to the dex file to determine the correct class for the access check
520 const DexFile& dex_file = class_linker->FindDexFile(referring_class->GetDexCache());
521 methods_class = class_linker->ResolveType(dex_file,
522 dex_file.GetMethodId(method_idx).class_idx_,
523 referring_class);
524 if (UNLIKELY(!referring_class->CanAccess(methods_class))) {
525 ThrowNewIllegalAccessErrorClassForMethodDispatch(self, referring_class, methods_class,
526 referrer, resolved_method, type);
527 return NULL; // failure
528 } else if (UNLIKELY(!referring_class->CanAccessMember(methods_class,
529 resolved_method->GetAccessFlags()))) {
530 ThrowNewIllegalAccessErrorMethod(self, referring_class, resolved_method);
531 return NULL; // failure
532 }
533 }
534 if (is_direct) {
535 return resolved_method;
536 } else if (type == kInterface) {
537 Method* interface_method =
538 this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
539 if (UNLIKELY(interface_method == NULL)) {
540 ThrowNewIncompatibleClassChangeErrorClassForInterfaceDispatch(self, referrer,
541 resolved_method,
542 this_object);
543 return NULL; // failure
544 } else {
545 return interface_method;
546 }
547 } else {
548 ObjectArray<Method>* vtable;
549 uint16_t vtable_index = resolved_method->GetMethodIndex();
550 if (type == kSuper) {
551 Class* super_class = referring_class->GetSuperClass();
552 if (LIKELY(super_class != NULL)) {
553 vtable = referring_class->GetSuperClass()->GetVTable();
554 } else {
555 vtable = NULL;
556 }
557 } else {
558 vtable = this_object->GetClass()->GetVTable();
559 }
560 if (LIKELY(vtable != NULL &&
561 vtable_index < static_cast<uint32_t>(vtable->GetLength()))) {
562 return vtable->GetWithoutChecks(vtable_index);
563 } else {
564 // Behavior to agree with that of the verifier
565 self->ThrowNewExceptionF("Ljava/lang/NoSuchMethodError;",
566 "attempt to invoke %s method '%s' from '%s'"
567 " using incorrect form of method dispatch",
568 (type == kSuper ? "super class" : "virtual"),
569 PrettyMethod(resolved_method).c_str(),
570 PrettyMethod(referrer).c_str());
571 return NULL; // failure
572 }
Ian Rogers60db5ab2012-02-20 17:02:00 -0800573 }
574 }
575 }
Ian Rogers60db5ab2012-02-20 17:02:00 -0800576}
577
Ian Rogers57b86d42012-03-27 16:05:41 -0700578Class* ResolveVerifyAndClinit(uint32_t type_idx, const Method* referrer, Thread* self,
579 bool can_run_clinit, bool verify_access) {
580 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
581 Class* klass = class_linker->ResolveType(type_idx, referrer);
582 if (UNLIKELY(klass == NULL)) {
jeffhao441d9122012-03-21 17:29:10 -0700583 CHECK(self->IsExceptionPending());
Ian Rogers57b86d42012-03-27 16:05:41 -0700584 return NULL; // Failure - Indicate to caller to deliver exception
jeffhao441d9122012-03-21 17:29:10 -0700585 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700586 // Perform access check if necessary.
587 Class* referring_class = referrer->GetDeclaringClass();
588 if (verify_access && UNLIKELY(!referring_class->CanAccess(klass))) {
589 ThrowNewIllegalAccessErrorClass(self, referring_class, klass);
590 return NULL; // Failure - Indicate to caller to deliver exception
Ian Rogers14b1b242011-10-11 18:54:34 -0700591 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700592 // If we're just implementing const-class, we shouldn't call <clinit>.
593 if (!can_run_clinit) {
594 return klass;
Ian Rogersdfcdf1a2011-10-10 17:50:35 -0700595 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700596 // If we are the <clinit> of this class, just return our storage.
597 //
598 // Do not set the DexCache InitializedStaticStorage, since that implies <clinit> has finished
599 // running.
600 if (klass == referring_class && MethodHelper(referrer).IsClassInitializer()) {
601 return klass;
Ian Rogersdfcdf1a2011-10-10 17:50:35 -0700602 }
Ian Rogers0045a292012-03-31 21:08:41 -0700603 if (!class_linker->EnsureInitialized(klass, true, true)) {
Ian Rogers57b86d42012-03-27 16:05:41 -0700604 CHECK(self->IsExceptionPending());
605 return NULL; // Failure - Indicate to caller to deliver exception
Ian Rogersdfcdf1a2011-10-10 17:50:35 -0700606 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700607 referrer->GetDexCacheInitializedStaticStorage()->Set(type_idx, klass);
608 return klass;
Shih-wei Liao2d831012011-09-28 22:06:53 -0700609}
610
TDYa1275bb86012012-04-11 05:57:28 -0700611void ThrowNewUndeclaredThrowableException(Thread* self, JNIEnv* env, Throwable* exception) {
612 ScopedLocalRef<jclass> jlr_UTE_class(env,
613 env->FindClass("java/lang/reflect/UndeclaredThrowableException"));
614 if (jlr_UTE_class.get() == NULL) {
615 LOG(ERROR) << "Couldn't throw new \"java/lang/reflect/UndeclaredThrowableException\"";
616 } else {
617 jmethodID jlre_UTE_constructor = env->GetMethodID(jlr_UTE_class.get(), "<init>",
618 "(Ljava/lang/Throwable;)V");
619 jthrowable jexception = AddLocalReference<jthrowable>(env, exception);
620 ScopedLocalRef<jthrowable> jlr_UTE(env,
621 reinterpret_cast<jthrowable>(env->NewObject(jlr_UTE_class.get(), jlre_UTE_constructor,
622 jexception)));
623 int rc = env->Throw(jlr_UTE.get());
624 if (rc != JNI_OK) {
625 LOG(ERROR) << "Couldn't throw new \"java/lang/reflect/UndeclaredThrowableException\"";
626 }
627 }
628 CHECK(self->IsExceptionPending());
629}
630
Shih-wei Liao2d831012011-09-28 22:06:53 -0700631} // namespace art