blob: 0caccf66238b20306539ba84c6e6f9a1ec758fb6 [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"
Elliott Hugheseac76672012-05-24 21:56:51 -070020#include "well_known_classes.h"
TDYa1275bb86012012-04-11 05:57:28 -070021
jeffhao41005dd2012-05-09 17:58:52 -070022double art_l2d(int64_t l) {
Elliott Hughes74847412012-06-20 18:10:21 -070023 return static_cast<double>(l);
jeffhao41005dd2012-05-09 17:58:52 -070024}
25
26float art_l2f(int64_t l) {
Elliott Hughes74847412012-06-20 18:10:21 -070027 return static_cast<float>(l);
jeffhao41005dd2012-05-09 17:58:52 -070028}
Shih-wei Liao2d831012011-09-28 22:06:53 -070029
Ian Rogers776ac1f2012-04-13 23:36:36 -070030/*
31 * Float/double conversion requires clamping to min and max of integer form. If
32 * target doesn't support this normally, use these.
33 */
jeffhao41005dd2012-05-09 17:58:52 -070034int64_t art_d2l(double d) {
Elliott Hughes74847412012-06-20 18:10:21 -070035 static const double kMaxLong = static_cast<double>(static_cast<int64_t>(0x7fffffffffffffffULL));
36 static const double kMinLong = static_cast<double>(static_cast<int64_t>(0x8000000000000000ULL));
Ian Rogers776ac1f2012-04-13 23:36:36 -070037 if (d >= kMaxLong) {
Logan Chien008fa512012-06-22 08:09:57 -070038 return static_cast<int64_t>(0x7fffffffffffffffULL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070039 } else if (d <= kMinLong) {
Logan Chien008fa512012-06-22 08:09:57 -070040 return static_cast<int64_t>(0x8000000000000000ULL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070041 } else if (d != d) { // NaN case
42 return 0;
43 } else {
Elliott Hughes74847412012-06-20 18:10:21 -070044 return static_cast<int64_t>(d);
Ian Rogers776ac1f2012-04-13 23:36:36 -070045 }
46}
47
jeffhao41005dd2012-05-09 17:58:52 -070048int64_t art_f2l(float f) {
Elliott Hughes74847412012-06-20 18:10:21 -070049 static const float kMaxLong = static_cast<float>(static_cast<int64_t>(0x7fffffffffffffffULL));
50 static const float kMinLong = static_cast<float>(static_cast<int64_t>(0x8000000000000000ULL));
Ian Rogers776ac1f2012-04-13 23:36:36 -070051 if (f >= kMaxLong) {
Logan Chien008fa512012-06-22 08:09:57 -070052 return static_cast<int64_t>(0x7fffffffffffffffULL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070053 } else if (f <= kMinLong) {
Logan Chien008fa512012-06-22 08:09:57 -070054 return static_cast<int64_t>(0x8000000000000000ULL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070055 } else if (f != f) { // NaN case
56 return 0;
57 } else {
Elliott Hughes74847412012-06-20 18:10:21 -070058 return static_cast<int64_t>(f);
Ian Rogers776ac1f2012-04-13 23:36:36 -070059 }
60}
61
jeffhao41005dd2012-05-09 17:58:52 -070062int32_t art_d2i(double d) {
Logan Chien008fa512012-06-22 08:09:57 -070063 static const double kMaxInt = static_cast<double>(static_cast<int32_t>(0x7fffffffUL));
64 static const double kMinInt = static_cast<double>(static_cast<int32_t>(0x80000000UL));
Ian Rogers776ac1f2012-04-13 23:36:36 -070065 if (d >= kMaxInt) {
Logan Chien008fa512012-06-22 08:09:57 -070066 return static_cast<int32_t>(0x7fffffffUL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070067 } else if (d <= kMinInt) {
Logan Chien008fa512012-06-22 08:09:57 -070068 return static_cast<int32_t>(0x80000000UL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070069 } else if (d != d) { // NaN case
70 return 0;
71 } else {
Elliott Hughes74847412012-06-20 18:10:21 -070072 return static_cast<int32_t>(d);
Ian Rogers776ac1f2012-04-13 23:36:36 -070073 }
74}
75
jeffhao41005dd2012-05-09 17:58:52 -070076int32_t art_f2i(float f) {
Logan Chien008fa512012-06-22 08:09:57 -070077 static const float kMaxInt = static_cast<float>(static_cast<int32_t>(0x7fffffffUL));
78 static const float kMinInt = static_cast<float>(static_cast<int32_t>(0x80000000UL));
Ian Rogers776ac1f2012-04-13 23:36:36 -070079 if (f >= kMaxInt) {
Logan Chien008fa512012-06-22 08:09:57 -070080 return static_cast<int32_t>(0x7fffffffUL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070081 } else if (f <= kMinInt) {
Logan Chien008fa512012-06-22 08:09:57 -070082 return static_cast<int32_t>(0x80000000UL);
Ian Rogers776ac1f2012-04-13 23:36:36 -070083 } else if (f != f) { // NaN case
84 return 0;
85 } else {
Elliott Hughes74847412012-06-20 18:10:21 -070086 return static_cast<int32_t>(f);
Ian Rogers776ac1f2012-04-13 23:36:36 -070087 }
88}
89
jeffhao41005dd2012-05-09 17:58:52 -070090namespace art {
91
Ian Rogers57b86d42012-03-27 16:05:41 -070092void ThrowNewIllegalAccessErrorClass(Thread* self,
93 Class* referrer,
94 Class* accessed) {
95 self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
96 "illegal class access: '%s' -> '%s'",
97 PrettyDescriptor(referrer).c_str(),
98 PrettyDescriptor(accessed).c_str());
Shih-wei Liaoddbd01a2012-03-09 14:42:12 -080099}
100
Ian Rogers57b86d42012-03-27 16:05:41 -0700101void ThrowNewIllegalAccessErrorClassForMethodDispatch(Thread* self,
102 Class* referrer,
103 Class* accessed,
104 const Method* caller,
105 const Method* called,
106 InvokeType type) {
Ian Rogers57b86d42012-03-27 16:05:41 -0700107 self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
108 "illegal class access ('%s' -> '%s')"
109 "in attempt to invoke %s method '%s' from '%s'",
110 PrettyDescriptor(referrer).c_str(),
111 PrettyDescriptor(accessed).c_str(),
Elliott Hughes6fcce302012-06-19 16:54:19 -0700112 ToStr<InvokeType>(type).c_str(),
Ian Rogers57b86d42012-03-27 16:05:41 -0700113 PrettyMethod(called).c_str(),
114 PrettyMethod(caller).c_str());
buzbee44b412b2012-02-04 08:50:53 -0800115}
116
Ian Rogers57b86d42012-03-27 16:05:41 -0700117void ThrowNewIncompatibleClassChangeErrorClassForInterfaceDispatch(Thread* self,
118 const Method* referrer,
119 const Method* interface_method,
120 Object* this_object) {
121 self->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
122 "class '%s' does not implement interface '%s' in call to '%s' from '%s'",
123 PrettyDescriptor(this_object->GetClass()).c_str(),
124 PrettyDescriptor(interface_method->GetDeclaringClass()).c_str(),
125 PrettyMethod(interface_method).c_str(), PrettyMethod(referrer).c_str());
Shih-wei Liao2d831012011-09-28 22:06:53 -0700126}
127
Ian Rogers57b86d42012-03-27 16:05:41 -0700128void ThrowNewIllegalAccessErrorField(Thread* self,
129 Class* referrer,
130 Field* accessed) {
131 self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
132 "Field '%s' is inaccessible to class '%s'",
133 PrettyField(accessed, false).c_str(),
134 PrettyDescriptor(referrer).c_str());
Shih-wei Liao2d831012011-09-28 22:06:53 -0700135}
136
Ian Rogers57b86d42012-03-27 16:05:41 -0700137void ThrowNewIllegalAccessErrorFinalField(Thread* self,
138 const Method* referrer,
139 Field* accessed) {
140 self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
141 "Final field '%s' cannot be written to by method '%s'",
142 PrettyField(accessed, false).c_str(),
143 PrettyMethod(referrer).c_str());
Shih-wei Liao2d831012011-09-28 22:06:53 -0700144}
145
Ian Rogers57b86d42012-03-27 16:05:41 -0700146void ThrowNewIllegalAccessErrorMethod(Thread* self,
147 Class* referrer,
148 Method* accessed) {
149 self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
150 "Method '%s' is inaccessible to class '%s'",
151 PrettyMethod(accessed).c_str(),
152 PrettyDescriptor(referrer).c_str());
Shih-wei Liao2d831012011-09-28 22:06:53 -0700153}
154
Ian Rogers57b86d42012-03-27 16:05:41 -0700155void ThrowNullPointerExceptionForFieldAccess(Thread* self,
156 Field* field,
157 bool is_read) {
158 self->ThrowNewExceptionF("Ljava/lang/NullPointerException;",
159 "Attempt to %s field '%s' on a null object reference",
160 is_read ? "read from" : "write to",
161 PrettyField(field, true).c_str());
Shih-wei Liao2d831012011-09-28 22:06:53 -0700162}
163
Ian Rogers57b86d42012-03-27 16:05:41 -0700164void ThrowNullPointerExceptionForMethodAccess(Thread* self,
165 Method* caller,
166 uint32_t method_idx,
167 InvokeType type) {
168 const DexFile& dex_file =
169 Runtime::Current()->GetClassLinker()->FindDexFile(caller->GetDeclaringClass()->GetDexCache());
Ian Rogers57b86d42012-03-27 16:05:41 -0700170 self->ThrowNewExceptionF("Ljava/lang/NullPointerException;",
171 "Attempt to invoke %s method '%s' on a null object reference",
Elliott Hughes6fcce302012-06-19 16:54:19 -0700172 ToStr<InvokeType>(type).c_str(),
Ian Rogers57b86d42012-03-27 16:05:41 -0700173 PrettyMethod(method_idx, dex_file, true).c_str());
Shih-wei Liao2d831012011-09-28 22:06:53 -0700174}
175
TDYa1273f9137d2012-04-08 15:59:19 -0700176void ThrowNullPointerExceptionFromDexPC(Thread* self, Method* throw_method, uint32_t dex_pc) {
177 const DexFile::CodeItem* code = MethodHelper(throw_method).GetCodeItem();
178 CHECK_LT(dex_pc, code->insns_size_in_code_units_);
179 const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
180 DecodedInstruction dec_insn(instr);
181 switch (instr->Opcode()) {
182 case Instruction::INVOKE_DIRECT:
183 case Instruction::INVOKE_DIRECT_RANGE:
184 ThrowNullPointerExceptionForMethodAccess(self, throw_method, dec_insn.vB, kDirect);
185 break;
186 case Instruction::INVOKE_VIRTUAL:
187 case Instruction::INVOKE_VIRTUAL_RANGE:
188 ThrowNullPointerExceptionForMethodAccess(self, throw_method, dec_insn.vB, kVirtual);
189 break;
190 case Instruction::IGET:
191 case Instruction::IGET_WIDE:
192 case Instruction::IGET_OBJECT:
193 case Instruction::IGET_BOOLEAN:
194 case Instruction::IGET_BYTE:
195 case Instruction::IGET_CHAR:
196 case Instruction::IGET_SHORT: {
197 Field* field =
198 Runtime::Current()->GetClassLinker()->ResolveField(dec_insn.vC, throw_method, false);
199 ThrowNullPointerExceptionForFieldAccess(self, field, true /* read */);
200 break;
201 }
202 case Instruction::IPUT:
203 case Instruction::IPUT_WIDE:
204 case Instruction::IPUT_OBJECT:
205 case Instruction::IPUT_BOOLEAN:
206 case Instruction::IPUT_BYTE:
207 case Instruction::IPUT_CHAR:
208 case Instruction::IPUT_SHORT: {
209 Field* field =
210 Runtime::Current()->GetClassLinker()->ResolveField(dec_insn.vC, throw_method, false);
211 ThrowNullPointerExceptionForFieldAccess(self, field, false /* write */);
212 break;
213 }
214 case Instruction::AGET:
215 case Instruction::AGET_WIDE:
216 case Instruction::AGET_OBJECT:
217 case Instruction::AGET_BOOLEAN:
218 case Instruction::AGET_BYTE:
219 case Instruction::AGET_CHAR:
220 case Instruction::AGET_SHORT:
221 self->ThrowNewException("Ljava/lang/NullPointerException;",
222 "Attempt to read from null array");
223 break;
224 case Instruction::APUT:
225 case Instruction::APUT_WIDE:
226 case Instruction::APUT_OBJECT:
227 case Instruction::APUT_BOOLEAN:
228 case Instruction::APUT_BYTE:
229 case Instruction::APUT_CHAR:
230 case Instruction::APUT_SHORT:
231 self->ThrowNewException("Ljava/lang/NullPointerException;",
232 "Attempt to write to null array");
233 break;
Elliott Hughes6fcce302012-06-19 16:54:19 -0700234 case Instruction::ARRAY_LENGTH:
235 self->ThrowNewException("Ljava/lang/NullPointerException;",
236 "Attempt to get length of null array");
237 break;
TDYa1273f9137d2012-04-08 15:59:19 -0700238 default: {
239 const DexFile& dex_file = Runtime::Current()->GetClassLinker()
240 ->FindDexFile(throw_method->GetDeclaringClass()->GetDexCache());
241 std::string message("Null pointer exception during instruction '");
242 message += instr->DumpString(&dex_file);
243 message += "'";
244 self->ThrowNewException("Ljava/lang/NullPointerException;", message.c_str());
245 break;
246 }
247 }
248}
249
Ian Rogers57b86d42012-03-27 16:05:41 -0700250std::string FieldNameFromIndex(const Method* method, uint32_t ref,
251 verifier::VerifyErrorRefType ref_type, bool access) {
Ian Rogersd81871c2011-10-03 13:57:23 -0700252 CHECK_EQ(static_cast<int>(ref_type), static_cast<int>(verifier::VERIFY_ERROR_REF_FIELD));
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700253
254 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
255 const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache());
256
257 const DexFile::FieldId& id = dex_file.GetFieldId(ref);
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700258 std::string class_name(PrettyDescriptor(dex_file.GetFieldDeclaringClassDescriptor(id)));
Ian Rogers0571d352011-11-03 19:51:38 -0700259 const char* field_name = dex_file.StringDataByIdx(id.name_idx_);
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700260 if (!access) {
261 return class_name + "." + field_name;
262 }
263
264 std::string result;
265 result += "tried to access field ";
266 result += class_name + "." + field_name;
267 result += " from class ";
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800268 result += PrettyDescriptor(method->GetDeclaringClass());
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700269 return result;
270}
271
Ian Rogers57b86d42012-03-27 16:05:41 -0700272std::string MethodNameFromIndex(const Method* method, uint32_t ref,
273 verifier::VerifyErrorRefType ref_type, bool access) {
Ian Rogersd81871c2011-10-03 13:57:23 -0700274 CHECK_EQ(static_cast<int>(ref_type), static_cast<int>(verifier::VERIFY_ERROR_REF_METHOD));
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700275
276 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
277 const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache());
278
279 const DexFile::MethodId& id = dex_file.GetMethodId(ref);
Brian Carlstrom6b4ef022011-10-23 14:59:04 -0700280 std::string class_name(PrettyDescriptor(dex_file.GetMethodDeclaringClassDescriptor(id)));
Ian Rogers0571d352011-11-03 19:51:38 -0700281 const char* method_name = dex_file.StringDataByIdx(id.name_idx_);
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700282 if (!access) {
283 return class_name + "." + method_name;
284 }
285
286 std::string result;
287 result += "tried to access method ";
Ian Rogers4f0d07c2011-10-06 23:38:47 -0700288 result += class_name + "." + method_name + ":" +
Ian Rogers0571d352011-11-03 19:51:38 -0700289 dex_file.CreateMethodSignature(id.proto_idx_, NULL);
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700290 result += " from class ";
Ian Rogers6d4d9fc2011-11-30 16:24:48 -0800291 result += PrettyDescriptor(method->GetDeclaringClass());
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700292 return result;
293}
294
TDYa127b92bcab2012-04-08 00:09:51 -0700295static std::string ClassNameFromIndex(const Method* method, uint32_t ref,
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700296 verifier::VerifyErrorRefType ref_type, bool access)
297 SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
Logan Chien9e5f5c12012-04-10 13:51:45 +0800298 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
299 const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache());
300
301 uint16_t type_idx = 0;
302 if (ref_type == verifier::VERIFY_ERROR_REF_FIELD) {
303 const DexFile::FieldId& id = dex_file.GetFieldId(ref);
304 type_idx = id.class_idx_;
305 } else if (ref_type == verifier::VERIFY_ERROR_REF_METHOD) {
306 const DexFile::MethodId& id = dex_file.GetMethodId(ref);
307 type_idx = id.class_idx_;
308 } else if (ref_type == verifier::VERIFY_ERROR_REF_CLASS) {
309 type_idx = ref;
310 } else {
311 CHECK(false) << static_cast<int>(ref_type);
312 }
313
314 std::string class_name(PrettyDescriptor(dex_file.StringByTypeIdx(type_idx)));
315 if (!access) {
316 return class_name;
317 }
318
319 std::string result;
320 result += "tried to access class ";
321 result += class_name;
322 result += " from class ";
323 result += PrettyDescriptor(method->GetDeclaringClass());
324 return result;
325}
326
327void ThrowVerificationError(Thread* self, const Method* method,
328 int32_t kind, int32_t ref) {
329 verifier::VerifyErrorRefType ref_type =
330 static_cast<verifier::VerifyErrorRefType>(kind >> verifier::kVerifyErrorRefTypeShift);
331
332 const char* exception_class = "Ljava/lang/VerifyError;";
333 std::string msg;
334
335 switch (static_cast<verifier::VerifyError>(kind & ~(0xff << verifier::kVerifyErrorRefTypeShift))) {
336 case verifier::VERIFY_ERROR_NO_CLASS:
337 exception_class = "Ljava/lang/NoClassDefFoundError;";
338 msg = ClassNameFromIndex(method, ref, ref_type, false);
339 break;
340 case verifier::VERIFY_ERROR_NO_FIELD:
341 exception_class = "Ljava/lang/NoSuchFieldError;";
342 msg = FieldNameFromIndex(method, ref, ref_type, false);
343 break;
344 case verifier::VERIFY_ERROR_NO_METHOD:
345 exception_class = "Ljava/lang/NoSuchMethodError;";
346 msg = MethodNameFromIndex(method, ref, ref_type, false);
347 break;
348 case verifier::VERIFY_ERROR_ACCESS_CLASS:
349 exception_class = "Ljava/lang/IllegalAccessError;";
350 msg = ClassNameFromIndex(method, ref, ref_type, true);
351 break;
352 case verifier::VERIFY_ERROR_ACCESS_FIELD:
353 exception_class = "Ljava/lang/IllegalAccessError;";
354 msg = FieldNameFromIndex(method, ref, ref_type, true);
355 break;
356 case verifier::VERIFY_ERROR_ACCESS_METHOD:
357 exception_class = "Ljava/lang/IllegalAccessError;";
358 msg = MethodNameFromIndex(method, ref, ref_type, true);
359 break;
360 case verifier::VERIFY_ERROR_CLASS_CHANGE:
361 exception_class = "Ljava/lang/IncompatibleClassChangeError;";
362 msg = ClassNameFromIndex(method, ref, ref_type, false);
363 break;
364 case verifier::VERIFY_ERROR_INSTANTIATION:
365 exception_class = "Ljava/lang/InstantiationError;";
366 msg = ClassNameFromIndex(method, ref, ref_type, false);
367 break;
368 case verifier::VERIFY_ERROR_BAD_CLASS_SOFT:
369 case verifier::VERIFY_ERROR_BAD_CLASS_HARD:
370 // Generic VerifyError; use default exception, no message.
371 break;
Logan Chien9e5f5c12012-04-10 13:51:45 +0800372 }
373
374 self->ThrowNewException(exception_class, msg.c_str());
375}
376
Ian Rogers57b86d42012-03-27 16:05:41 -0700377// Helper function to allocate array for FILLED_NEW_ARRAY.
378Array* CheckAndAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count,
379 Thread* self, bool access_check) {
380 if (UNLIKELY(component_count < 0)) {
381 self->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", component_count);
382 return NULL; // Failure
Elliott Hughes6c8867d2011-10-03 16:34:05 -0700383 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700384 Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
385 if (UNLIKELY(klass == NULL)) { // Not in dex cache so try to resolve
386 klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
387 if (klass == NULL) { // Error
388 DCHECK(Thread::Current()->IsExceptionPending());
389 return NULL; // Failure
Ian Rogers19846512012-02-24 11:42:47 -0800390 }
Ian Rogersea2a11d2011-10-11 16:48:51 -0700391 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700392 if (UNLIKELY(klass->IsPrimitive() && !klass->IsPrimitiveInt())) {
393 if (klass->IsPrimitiveLong() || klass->IsPrimitiveDouble()) {
394 Thread::Current()->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
395 "Bad filled array request for type %s",
396 PrettyDescriptor(klass).c_str());
Ian Rogers573db4a2011-12-13 15:30:50 -0800397 } else {
Ian Rogers57b86d42012-03-27 16:05:41 -0700398 Thread::Current()->ThrowNewExceptionF("Ljava/lang/InternalError;",
399 "Found type %s; filled-new-array not implemented for anything but \'int\'",
400 PrettyDescriptor(klass).c_str());
Ian Rogers573db4a2011-12-13 15:30:50 -0800401 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700402 return NULL; // Failure
Ian Rogersad25ac52011-10-04 19:13:33 -0700403 } else {
Ian Rogers57b86d42012-03-27 16:05:41 -0700404 if (access_check) {
405 Class* referrer = method->GetDeclaringClass();
406 if (UNLIKELY(!referrer->CanAccess(klass))) {
407 ThrowNewIllegalAccessErrorClass(self, referrer, klass);
408 return NULL; // Failure
409 }
Ian Rogers60db5ab2012-02-20 17:02:00 -0800410 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700411 DCHECK(klass->IsArrayClass()) << PrettyClass(klass);
412 return Array::Alloc(klass, component_count);
413 }
414}
415
416// Slow path field resolution and declaring class initialization
417Field* FindFieldFromCode(uint32_t field_idx, const Method* referrer, Thread* self,
418 bool is_static, bool is_primitive, bool is_set, size_t expected_size) {
419 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
420 Field* resolved_field = class_linker->ResolveField(field_idx, referrer, is_static);
421 if (UNLIKELY(resolved_field == NULL)) {
422 DCHECK(self->IsExceptionPending()); // Throw exception and unwind
423 return NULL; // failure
424 } else {
425 Class* fields_class = resolved_field->GetDeclaringClass();
426 Class* referring_class = referrer->GetDeclaringClass();
Ian Rogerse2645d32012-04-11 14:42:42 -0700427 if (UNLIKELY(!referring_class->CanAccess(fields_class) ||
428 !referring_class->CanAccessMember(fields_class,
429 resolved_field->GetAccessFlags()))) {
430 // The referring class can't access the resolved field, this may occur as a result of a
431 // protected field being made public by a sub-class. Resort to the dex file to determine
432 // the correct class for the access check.
433 const DexFile& dex_file = class_linker->FindDexFile(referring_class->GetDexCache());
434 fields_class = class_linker->ResolveType(dex_file,
435 dex_file.GetFieldId(field_idx).class_idx_,
436 referring_class);
437 if (UNLIKELY(!referring_class->CanAccess(fields_class))) {
438 ThrowNewIllegalAccessErrorClass(self, referring_class, fields_class);
439 return NULL; // failure
440 } else if (UNLIKELY(!referring_class->CanAccessMember(fields_class,
441 resolved_field->GetAccessFlags()))) {
442 ThrowNewIllegalAccessErrorField(self, referring_class, resolved_field);
443 return NULL; // failure
444 }
445 }
446 if (UNLIKELY(is_set && resolved_field->IsFinal() && (fields_class != referring_class))) {
Ian Rogers57b86d42012-03-27 16:05:41 -0700447 ThrowNewIllegalAccessErrorFinalField(self, referrer, resolved_field);
448 return NULL; // failure
449 } else {
450 FieldHelper fh(resolved_field);
451 if (UNLIKELY(fh.IsPrimitiveType() != is_primitive ||
452 fh.FieldSize() != expected_size)) {
453 self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
454 "Attempted read of %zd-bit %s on field '%s'",
455 expected_size * (32 / sizeof(int32_t)),
456 is_primitive ? "primitive" : "non-primitive",
457 PrettyField(resolved_field, true).c_str());
458 return NULL; // failure
459 } else if (!is_static) {
460 // instance fields must be being accessed on an initialized class
461 return resolved_field;
Ian Rogers60db5ab2012-02-20 17:02:00 -0800462 } else {
Ian Rogers57b86d42012-03-27 16:05:41 -0700463 // If the class is already initializing, we must be inside <clinit>, or
464 // we'd still be waiting for the lock.
465 if (fields_class->IsInitializing()) {
466 return resolved_field;
Ian Rogers0045a292012-03-31 21:08:41 -0700467 } else if (Runtime::Current()->GetClassLinker()->EnsureInitialized(fields_class, true, true)) {
Ian Rogers57b86d42012-03-27 16:05:41 -0700468 return resolved_field;
Ian Rogers60db5ab2012-02-20 17:02:00 -0800469 } else {
Ian Rogers57b86d42012-03-27 16:05:41 -0700470 DCHECK(self->IsExceptionPending()); // Throw exception and unwind
471 return NULL; // failure
Ian Rogers60db5ab2012-02-20 17:02:00 -0800472 }
473 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700474 }
475 }
476}
477
478// Slow path method resolution
479Method* FindMethodFromCode(uint32_t method_idx, Object* this_object, const Method* referrer,
480 Thread* self, bool access_check, InvokeType type) {
481 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
482 bool is_direct = type == kStatic || type == kDirect;
483 Method* resolved_method = class_linker->ResolveMethod(method_idx, referrer, is_direct);
484 if (UNLIKELY(resolved_method == NULL)) {
485 DCHECK(self->IsExceptionPending()); // Throw exception and unwind
486 return NULL; // failure
487 } else {
488 if (!access_check) {
489 if (is_direct) {
490 return resolved_method;
491 } else if (type == kInterface) {
492 Method* interface_method =
493 this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
494 if (UNLIKELY(interface_method == NULL)) {
495 ThrowNewIncompatibleClassChangeErrorClassForInterfaceDispatch(self, referrer,
496 resolved_method,
497 this_object);
498 return NULL; // failure
499 } else {
500 return interface_method;
501 }
Ian Rogers60db5ab2012-02-20 17:02:00 -0800502 } else {
Ian Rogers57b86d42012-03-27 16:05:41 -0700503 ObjectArray<Method>* vtable;
504 uint16_t vtable_index = resolved_method->GetMethodIndex();
505 if (type == kSuper) {
506 vtable = referrer->GetDeclaringClass()->GetSuperClass()->GetVTable();
507 } else {
508 vtable = this_object->GetClass()->GetVTable();
509 }
510 // TODO: eliminate bounds check?
511 return vtable->Get(vtable_index);
512 }
513 } else {
514 Class* methods_class = resolved_method->GetDeclaringClass();
515 Class* referring_class = referrer->GetDeclaringClass();
516 if (UNLIKELY(!referring_class->CanAccess(methods_class) ||
517 !referring_class->CanAccessMember(methods_class,
518 resolved_method->GetAccessFlags()))) {
519 // The referring class can't access the resolved method, this may occur as a result of a
520 // protected method being made public by implementing an interface that re-declares the
521 // method public. Resort to the dex file to determine the correct class for the access check
522 const DexFile& dex_file = class_linker->FindDexFile(referring_class->GetDexCache());
523 methods_class = class_linker->ResolveType(dex_file,
524 dex_file.GetMethodId(method_idx).class_idx_,
525 referring_class);
526 if (UNLIKELY(!referring_class->CanAccess(methods_class))) {
527 ThrowNewIllegalAccessErrorClassForMethodDispatch(self, referring_class, methods_class,
528 referrer, resolved_method, type);
529 return NULL; // failure
530 } else if (UNLIKELY(!referring_class->CanAccessMember(methods_class,
531 resolved_method->GetAccessFlags()))) {
532 ThrowNewIllegalAccessErrorMethod(self, referring_class, resolved_method);
533 return NULL; // failure
534 }
535 }
536 if (is_direct) {
537 return resolved_method;
538 } else if (type == kInterface) {
539 Method* interface_method =
540 this_object->GetClass()->FindVirtualMethodForInterface(resolved_method);
541 if (UNLIKELY(interface_method == NULL)) {
542 ThrowNewIncompatibleClassChangeErrorClassForInterfaceDispatch(self, referrer,
543 resolved_method,
544 this_object);
545 return NULL; // failure
546 } else {
547 return interface_method;
548 }
549 } else {
550 ObjectArray<Method>* vtable;
551 uint16_t vtable_index = resolved_method->GetMethodIndex();
552 if (type == kSuper) {
553 Class* super_class = referring_class->GetSuperClass();
554 if (LIKELY(super_class != NULL)) {
555 vtable = referring_class->GetSuperClass()->GetVTable();
556 } else {
557 vtable = NULL;
558 }
559 } else {
560 vtable = this_object->GetClass()->GetVTable();
561 }
562 if (LIKELY(vtable != NULL &&
563 vtable_index < static_cast<uint32_t>(vtable->GetLength()))) {
564 return vtable->GetWithoutChecks(vtable_index);
565 } else {
566 // Behavior to agree with that of the verifier
567 self->ThrowNewExceptionF("Ljava/lang/NoSuchMethodError;",
568 "attempt to invoke %s method '%s' from '%s'"
569 " using incorrect form of method dispatch",
570 (type == kSuper ? "super class" : "virtual"),
571 PrettyMethod(resolved_method).c_str(),
572 PrettyMethod(referrer).c_str());
573 return NULL; // failure
574 }
Ian Rogers60db5ab2012-02-20 17:02:00 -0800575 }
576 }
577 }
Ian Rogers60db5ab2012-02-20 17:02:00 -0800578}
579
Ian Rogers57b86d42012-03-27 16:05:41 -0700580Class* ResolveVerifyAndClinit(uint32_t type_idx, const Method* referrer, Thread* self,
581 bool can_run_clinit, bool verify_access) {
582 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
583 Class* klass = class_linker->ResolveType(type_idx, referrer);
584 if (UNLIKELY(klass == NULL)) {
jeffhao441d9122012-03-21 17:29:10 -0700585 CHECK(self->IsExceptionPending());
Ian Rogers57b86d42012-03-27 16:05:41 -0700586 return NULL; // Failure - Indicate to caller to deliver exception
jeffhao441d9122012-03-21 17:29:10 -0700587 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700588 // Perform access check if necessary.
589 Class* referring_class = referrer->GetDeclaringClass();
590 if (verify_access && UNLIKELY(!referring_class->CanAccess(klass))) {
591 ThrowNewIllegalAccessErrorClass(self, referring_class, klass);
592 return NULL; // Failure - Indicate to caller to deliver exception
Ian Rogers14b1b242011-10-11 18:54:34 -0700593 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700594 // If we're just implementing const-class, we shouldn't call <clinit>.
595 if (!can_run_clinit) {
596 return klass;
Ian Rogersdfcdf1a2011-10-10 17:50:35 -0700597 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700598 // If we are the <clinit> of this class, just return our storage.
599 //
600 // Do not set the DexCache InitializedStaticStorage, since that implies <clinit> has finished
601 // running.
602 if (klass == referring_class && MethodHelper(referrer).IsClassInitializer()) {
603 return klass;
Ian Rogersdfcdf1a2011-10-10 17:50:35 -0700604 }
Ian Rogers0045a292012-03-31 21:08:41 -0700605 if (!class_linker->EnsureInitialized(klass, true, true)) {
Ian Rogers57b86d42012-03-27 16:05:41 -0700606 CHECK(self->IsExceptionPending());
607 return NULL; // Failure - Indicate to caller to deliver exception
Ian Rogersdfcdf1a2011-10-10 17:50:35 -0700608 }
Ian Rogers57b86d42012-03-27 16:05:41 -0700609 referrer->GetDexCacheInitializedStaticStorage()->Set(type_idx, klass);
610 return klass;
Shih-wei Liao2d831012011-09-28 22:06:53 -0700611}
612
Shih-wei Liao2d831012011-09-28 22:06:53 -0700613} // namespace art