blob: 9f04b90c55c60696fd59c6f500a577f744f9abc3 [file] [log] [blame]
Sebastien Hertz8ece0502013-08-07 11:26:41 +02001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
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 "interpreter_common.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010018#include "mirror/array-inl.h"
Sebastien Hertz8ece0502013-08-07 11:26:41 +020019
20namespace art {
21namespace interpreter {
22
Ian Rogers54874942014-06-10 16:31:03 -070023void ThrowNullPointerExceptionFromInterpreter(const ShadowFrame& shadow_frame) {
24 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
25}
26
27template<FindFieldType find_type, Primitive::Type field_type, bool do_access_check>
28bool DoFieldGet(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst,
29 uint16_t inst_data) {
30 const bool is_static = (find_type == StaticObjectRead) || (find_type == StaticPrimitiveRead);
31 const uint32_t field_idx = is_static ? inst->VRegB_21c() : inst->VRegC_22c();
32 ArtField* f = FindFieldFromCode<find_type, do_access_check>(field_idx, shadow_frame.GetMethod(), self,
33 Primitive::FieldSize(field_type));
34 if (UNLIKELY(f == nullptr)) {
35 CHECK(self->IsExceptionPending());
36 return false;
37 }
38 Object* obj;
39 if (is_static) {
40 obj = f->GetDeclaringClass();
41 } else {
42 obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
43 if (UNLIKELY(obj == nullptr)) {
44 ThrowNullPointerExceptionForFieldAccess(shadow_frame.GetCurrentLocationForThrow(), f, true);
45 return false;
46 }
47 }
48 // Report this field access to instrumentation if needed.
49 instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
50 if (UNLIKELY(instrumentation->HasFieldReadListeners())) {
51 Object* this_object = f->IsStatic() ? nullptr : obj;
52 instrumentation->FieldReadEvent(self, this_object, shadow_frame.GetMethod(),
53 shadow_frame.GetDexPC(), f);
54 }
55 uint32_t vregA = is_static ? inst->VRegA_21c(inst_data) : inst->VRegA_22c(inst_data);
56 switch (field_type) {
57 case Primitive::kPrimBoolean:
58 shadow_frame.SetVReg(vregA, f->GetBoolean(obj));
59 break;
60 case Primitive::kPrimByte:
61 shadow_frame.SetVReg(vregA, f->GetByte(obj));
62 break;
63 case Primitive::kPrimChar:
64 shadow_frame.SetVReg(vregA, f->GetChar(obj));
65 break;
66 case Primitive::kPrimShort:
67 shadow_frame.SetVReg(vregA, f->GetShort(obj));
68 break;
69 case Primitive::kPrimInt:
70 shadow_frame.SetVReg(vregA, f->GetInt(obj));
71 break;
72 case Primitive::kPrimLong:
73 shadow_frame.SetVRegLong(vregA, f->GetLong(obj));
74 break;
75 case Primitive::kPrimNot:
76 shadow_frame.SetVRegReference(vregA, f->GetObject(obj));
77 break;
78 default:
79 LOG(FATAL) << "Unreachable: " << field_type;
80 }
81 return true;
82}
83
84// Explicitly instantiate all DoFieldGet functions.
85#define EXPLICIT_DO_FIELD_GET_TEMPLATE_DECL(_find_type, _field_type, _do_check) \
86 template bool DoFieldGet<_find_type, _field_type, _do_check>(Thread* self, \
87 ShadowFrame& shadow_frame, \
88 const Instruction* inst, \
89 uint16_t inst_data)
90
91#define EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(_find_type, _field_type) \
92 EXPLICIT_DO_FIELD_GET_TEMPLATE_DECL(_find_type, _field_type, false); \
93 EXPLICIT_DO_FIELD_GET_TEMPLATE_DECL(_find_type, _field_type, true);
94
95// iget-XXX
96EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(InstancePrimitiveRead, Primitive::kPrimBoolean);
97EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(InstancePrimitiveRead, Primitive::kPrimByte);
98EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(InstancePrimitiveRead, Primitive::kPrimChar);
99EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(InstancePrimitiveRead, Primitive::kPrimShort);
100EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(InstancePrimitiveRead, Primitive::kPrimInt);
101EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(InstancePrimitiveRead, Primitive::kPrimLong);
102EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(InstanceObjectRead, Primitive::kPrimNot);
103
104// sget-XXX
105EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(StaticPrimitiveRead, Primitive::kPrimBoolean);
106EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(StaticPrimitiveRead, Primitive::kPrimByte);
107EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(StaticPrimitiveRead, Primitive::kPrimChar);
108EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(StaticPrimitiveRead, Primitive::kPrimShort);
109EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(StaticPrimitiveRead, Primitive::kPrimInt);
110EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(StaticPrimitiveRead, Primitive::kPrimLong);
111EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(StaticObjectRead, Primitive::kPrimNot);
112
113#undef EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL
114#undef EXPLICIT_DO_FIELD_GET_TEMPLATE_DECL
115
116// Handles iget-quick, iget-wide-quick and iget-object-quick instructions.
117// Returns true on success, otherwise throws an exception and returns false.
118template<Primitive::Type field_type>
119bool DoIGetQuick(ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data) {
120 Object* obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
121 if (UNLIKELY(obj == nullptr)) {
122 // We lost the reference to the field index so we cannot get a more
123 // precised exception message.
124 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
125 return false;
126 }
127 MemberOffset field_offset(inst->VRegC_22c());
128 // Report this field access to instrumentation if needed. Since we only have the offset of
129 // the field from the base of the object, we need to look for it first.
130 instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
131 if (UNLIKELY(instrumentation->HasFieldReadListeners())) {
132 ArtField* f = ArtField::FindInstanceFieldWithOffset(obj->GetClass(),
133 field_offset.Uint32Value());
134 DCHECK(f != nullptr);
135 DCHECK(!f->IsStatic());
136 instrumentation->FieldReadEvent(Thread::Current(), obj, shadow_frame.GetMethod(),
137 shadow_frame.GetDexPC(), f);
138 }
139 // Note: iget-x-quick instructions are only for non-volatile fields.
140 const uint32_t vregA = inst->VRegA_22c(inst_data);
141 switch (field_type) {
142 case Primitive::kPrimInt:
143 shadow_frame.SetVReg(vregA, static_cast<int32_t>(obj->GetField32(field_offset)));
144 break;
145 case Primitive::kPrimLong:
146 shadow_frame.SetVRegLong(vregA, static_cast<int64_t>(obj->GetField64(field_offset)));
147 break;
148 case Primitive::kPrimNot:
149 shadow_frame.SetVRegReference(vregA, obj->GetFieldObject<mirror::Object>(field_offset));
150 break;
151 default:
152 LOG(FATAL) << "Unreachable: " << field_type;
153 }
154 return true;
155}
156
157// Explicitly instantiate all DoIGetQuick functions.
158#define EXPLICIT_DO_IGET_QUICK_TEMPLATE_DECL(_field_type) \
159 template bool DoIGetQuick<_field_type>(ShadowFrame& shadow_frame, const Instruction* inst, \
160 uint16_t inst_data)
161
162EXPLICIT_DO_IGET_QUICK_TEMPLATE_DECL(Primitive::kPrimInt); // iget-quick.
163EXPLICIT_DO_IGET_QUICK_TEMPLATE_DECL(Primitive::kPrimLong); // iget-wide-quick.
164EXPLICIT_DO_IGET_QUICK_TEMPLATE_DECL(Primitive::kPrimNot); // iget-object-quick.
165#undef EXPLICIT_DO_IGET_QUICK_TEMPLATE_DECL
166
167template<Primitive::Type field_type>
168static JValue GetFieldValue(const ShadowFrame& shadow_frame, uint32_t vreg)
169 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
170 JValue field_value;
171 switch (field_type) {
172 case Primitive::kPrimBoolean:
173 field_value.SetZ(static_cast<uint8_t>(shadow_frame.GetVReg(vreg)));
174 break;
175 case Primitive::kPrimByte:
176 field_value.SetB(static_cast<int8_t>(shadow_frame.GetVReg(vreg)));
177 break;
178 case Primitive::kPrimChar:
179 field_value.SetC(static_cast<uint16_t>(shadow_frame.GetVReg(vreg)));
180 break;
181 case Primitive::kPrimShort:
182 field_value.SetS(static_cast<int16_t>(shadow_frame.GetVReg(vreg)));
183 break;
184 case Primitive::kPrimInt:
185 field_value.SetI(shadow_frame.GetVReg(vreg));
186 break;
187 case Primitive::kPrimLong:
188 field_value.SetJ(shadow_frame.GetVRegLong(vreg));
189 break;
190 case Primitive::kPrimNot:
191 field_value.SetL(shadow_frame.GetVRegReference(vreg));
192 break;
193 default:
194 LOG(FATAL) << "Unreachable: " << field_type;
195 break;
196 }
197 return field_value;
198}
199
200template<FindFieldType find_type, Primitive::Type field_type, bool do_access_check,
201 bool transaction_active>
202bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame, const Instruction* inst,
203 uint16_t inst_data) {
204 bool do_assignability_check = do_access_check;
205 bool is_static = (find_type == StaticObjectWrite) || (find_type == StaticPrimitiveWrite);
206 uint32_t field_idx = is_static ? inst->VRegB_21c() : inst->VRegC_22c();
207 ArtField* f = FindFieldFromCode<find_type, do_access_check>(field_idx, shadow_frame.GetMethod(), self,
208 Primitive::FieldSize(field_type));
209 if (UNLIKELY(f == nullptr)) {
210 CHECK(self->IsExceptionPending());
211 return false;
212 }
213 Object* obj;
214 if (is_static) {
215 obj = f->GetDeclaringClass();
216 } else {
217 obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
218 if (UNLIKELY(obj == nullptr)) {
219 ThrowNullPointerExceptionForFieldAccess(shadow_frame.GetCurrentLocationForThrow(),
220 f, false);
221 return false;
222 }
223 }
224 uint32_t vregA = is_static ? inst->VRegA_21c(inst_data) : inst->VRegA_22c(inst_data);
225 // Report this field access to instrumentation if needed. Since we only have the offset of
226 // the field from the base of the object, we need to look for it first.
227 instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
228 if (UNLIKELY(instrumentation->HasFieldWriteListeners())) {
229 JValue field_value = GetFieldValue<field_type>(shadow_frame, vregA);
230 Object* this_object = f->IsStatic() ? nullptr : obj;
231 instrumentation->FieldWriteEvent(self, this_object, shadow_frame.GetMethod(),
232 shadow_frame.GetDexPC(), f, field_value);
233 }
234 switch (field_type) {
235 case Primitive::kPrimBoolean:
236 f->SetBoolean<transaction_active>(obj, shadow_frame.GetVReg(vregA));
237 break;
238 case Primitive::kPrimByte:
239 f->SetByte<transaction_active>(obj, shadow_frame.GetVReg(vregA));
240 break;
241 case Primitive::kPrimChar:
242 f->SetChar<transaction_active>(obj, shadow_frame.GetVReg(vregA));
243 break;
244 case Primitive::kPrimShort:
245 f->SetShort<transaction_active>(obj, shadow_frame.GetVReg(vregA));
246 break;
247 case Primitive::kPrimInt:
248 f->SetInt<transaction_active>(obj, shadow_frame.GetVReg(vregA));
249 break;
250 case Primitive::kPrimLong:
251 f->SetLong<transaction_active>(obj, shadow_frame.GetVRegLong(vregA));
252 break;
253 case Primitive::kPrimNot: {
254 Object* reg = shadow_frame.GetVRegReference(vregA);
255 if (do_assignability_check && reg != nullptr) {
256 // FieldHelper::GetType can resolve classes, use a handle wrapper which will restore the
257 // object in the destructor.
258 Class* field_class;
259 {
260 StackHandleScope<3> hs(self);
261 HandleWrapper<mirror::ArtField> h_f(hs.NewHandleWrapper(&f));
262 HandleWrapper<mirror::Object> h_reg(hs.NewHandleWrapper(&reg));
263 HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(&obj));
264 FieldHelper fh(h_f);
265 field_class = fh.GetType();
266 }
267 if (!reg->VerifierInstanceOf(field_class)) {
268 // This should never happen.
269 self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
270 "Ljava/lang/VirtualMachineError;",
271 "Put '%s' that is not instance of field '%s' in '%s'",
272 reg->GetClass()->GetDescriptor().c_str(),
273 field_class->GetDescriptor().c_str(),
274 f->GetDeclaringClass()->GetDescriptor().c_str());
275 return false;
276 }
277 }
278 f->SetObj<transaction_active>(obj, reg);
279 break;
280 }
281 default:
282 LOG(FATAL) << "Unreachable: " << field_type;
283 }
284 return true;
285}
286
287// Explicitly instantiate all DoFieldPut functions.
288#define EXPLICIT_DO_FIELD_PUT_TEMPLATE_DECL(_find_type, _field_type, _do_check, _transaction_active) \
289 template bool DoFieldPut<_find_type, _field_type, _do_check, _transaction_active>(Thread* self, \
290 const ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data)
291
292#define EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(_find_type, _field_type) \
293 EXPLICIT_DO_FIELD_PUT_TEMPLATE_DECL(_find_type, _field_type, false, false); \
294 EXPLICIT_DO_FIELD_PUT_TEMPLATE_DECL(_find_type, _field_type, true, false); \
295 EXPLICIT_DO_FIELD_PUT_TEMPLATE_DECL(_find_type, _field_type, false, true); \
296 EXPLICIT_DO_FIELD_PUT_TEMPLATE_DECL(_find_type, _field_type, true, true);
297
298// iput-XXX
299EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(InstancePrimitiveWrite, Primitive::kPrimBoolean);
300EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(InstancePrimitiveWrite, Primitive::kPrimByte);
301EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(InstancePrimitiveWrite, Primitive::kPrimChar);
302EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(InstancePrimitiveWrite, Primitive::kPrimShort);
303EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(InstancePrimitiveWrite, Primitive::kPrimInt);
304EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(InstancePrimitiveWrite, Primitive::kPrimLong);
305EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(InstanceObjectWrite, Primitive::kPrimNot);
306
307// sput-XXX
308EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(StaticPrimitiveWrite, Primitive::kPrimBoolean);
309EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(StaticPrimitiveWrite, Primitive::kPrimByte);
310EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(StaticPrimitiveWrite, Primitive::kPrimChar);
311EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(StaticPrimitiveWrite, Primitive::kPrimShort);
312EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(StaticPrimitiveWrite, Primitive::kPrimInt);
313EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(StaticPrimitiveWrite, Primitive::kPrimLong);
314EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(StaticObjectWrite, Primitive::kPrimNot);
315
316#undef EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL
317#undef EXPLICIT_DO_FIELD_PUT_TEMPLATE_DECL
318
319template<Primitive::Type field_type, bool transaction_active>
320bool DoIPutQuick(const ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data) {
321 Object* obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
322 if (UNLIKELY(obj == nullptr)) {
323 // We lost the reference to the field index so we cannot get a more
324 // precised exception message.
325 ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
326 return false;
327 }
328 MemberOffset field_offset(inst->VRegC_22c());
329 const uint32_t vregA = inst->VRegA_22c(inst_data);
330 // Report this field modification to instrumentation if needed. Since we only have the offset of
331 // the field from the base of the object, we need to look for it first.
332 instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
333 if (UNLIKELY(instrumentation->HasFieldWriteListeners())) {
334 ArtField* f = ArtField::FindInstanceFieldWithOffset(obj->GetClass(),
335 field_offset.Uint32Value());
336 DCHECK(f != nullptr);
337 DCHECK(!f->IsStatic());
338 JValue field_value = GetFieldValue<field_type>(shadow_frame, vregA);
339 instrumentation->FieldWriteEvent(Thread::Current(), obj, shadow_frame.GetMethod(),
340 shadow_frame.GetDexPC(), f, field_value);
341 }
342 // Note: iput-x-quick instructions are only for non-volatile fields.
343 switch (field_type) {
344 case Primitive::kPrimInt:
345 obj->SetField32<transaction_active>(field_offset, shadow_frame.GetVReg(vregA));
346 break;
347 case Primitive::kPrimLong:
348 obj->SetField64<transaction_active>(field_offset, shadow_frame.GetVRegLong(vregA));
349 break;
350 case Primitive::kPrimNot:
351 obj->SetFieldObject<transaction_active>(field_offset, shadow_frame.GetVRegReference(vregA));
352 break;
353 default:
354 LOG(FATAL) << "Unreachable: " << field_type;
355 }
356 return true;
357}
358
359// Explicitly instantiate all DoIPutQuick functions.
360#define EXPLICIT_DO_IPUT_QUICK_TEMPLATE_DECL(_field_type, _transaction_active) \
361 template bool DoIPutQuick<_field_type, _transaction_active>(const ShadowFrame& shadow_frame, \
362 const Instruction* inst, \
363 uint16_t inst_data)
364
365#define EXPLICIT_DO_IPUT_QUICK_ALL_TEMPLATE_DECL(_field_type) \
366 EXPLICIT_DO_IPUT_QUICK_TEMPLATE_DECL(_field_type, false); \
367 EXPLICIT_DO_IPUT_QUICK_TEMPLATE_DECL(_field_type, true);
368
369EXPLICIT_DO_IPUT_QUICK_ALL_TEMPLATE_DECL(Primitive::kPrimInt); // iget-quick.
370EXPLICIT_DO_IPUT_QUICK_ALL_TEMPLATE_DECL(Primitive::kPrimLong); // iget-wide-quick.
371EXPLICIT_DO_IPUT_QUICK_ALL_TEMPLATE_DECL(Primitive::kPrimNot); // iget-object-quick.
372#undef EXPLICIT_DO_IPUT_QUICK_ALL_TEMPLATE_DECL
373#undef EXPLICIT_DO_IPUT_QUICK_TEMPLATE_DECL
374
Sebastien Hertz9f102032014-05-23 08:59:42 +0200375/**
376 * Finds the location where this exception will be caught. We search until we reach either the top
377 * frame or a native frame, in which cases this exception is considered uncaught.
378 */
379class CatchLocationFinder : public StackVisitor {
380 public:
381 explicit CatchLocationFinder(Thread* self, Handle<mirror::Throwable>* exception)
382 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
383 : StackVisitor(self, nullptr), self_(self), handle_scope_(self), exception_(exception),
384 catch_method_(handle_scope_.NewHandle<mirror::ArtMethod>(nullptr)),
385 catch_dex_pc_(DexFile::kDexNoIndex), clear_exception_(false) {
386 }
387
388 bool VisitFrame() OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
389 mirror::ArtMethod* method = GetMethod();
390 if (method == nullptr) {
391 return true;
392 }
393 if (method->IsRuntimeMethod()) {
394 // Ignore callee save method.
395 DCHECK(method->IsCalleeSaveMethod());
396 return true;
397 }
398 if (method->IsNative()) {
399 return false; // End stack walk.
400 }
401 DCHECK(!method->IsNative());
402 uint32_t dex_pc = GetDexPc();
403 if (dex_pc != DexFile::kDexNoIndex) {
404 uint32_t found_dex_pc;
405 {
406 StackHandleScope<3> hs(self_);
407 Handle<mirror::Class> exception_class(hs.NewHandle((*exception_)->GetClass()));
408 Handle<mirror::ArtMethod> h_method(hs.NewHandle(method));
409 found_dex_pc = mirror::ArtMethod::FindCatchBlock(h_method, exception_class, dex_pc,
410 &clear_exception_);
411 }
412 if (found_dex_pc != DexFile::kDexNoIndex) {
413 catch_method_.Assign(method);
414 catch_dex_pc_ = found_dex_pc;
415 return false; // End stack walk.
416 }
417 }
418 return true; // Continue stack walk.
419 }
420
421 ArtMethod* GetCatchMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
422 return catch_method_.Get();
423 }
424
425 uint32_t GetCatchDexPc() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
426 return catch_dex_pc_;
427 }
428
429 bool NeedClearException() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
430 return clear_exception_;
431 }
432
433 private:
434 Thread* const self_;
435 StackHandleScope<1> handle_scope_;
436 Handle<mirror::Throwable>* exception_;
437 Handle<mirror::ArtMethod> catch_method_;
438 uint32_t catch_dex_pc_;
439 bool clear_exception_;
440
441
442 DISALLOW_COPY_AND_ASSIGN(CatchLocationFinder);
443};
444
Ian Rogers54874942014-06-10 16:31:03 -0700445uint32_t FindNextInstructionFollowingException(Thread* self,
446 ShadowFrame& shadow_frame,
447 uint32_t dex_pc,
Ian Rogers54874942014-06-10 16:31:03 -0700448 const instrumentation::Instrumentation* instrumentation) {
449 self->VerifyStack();
450 ThrowLocation throw_location;
Sebastien Hertz9f102032014-05-23 08:59:42 +0200451 StackHandleScope<3> hs(self);
452 Handle<mirror::Throwable> exception(hs.NewHandle(self->GetException(&throw_location)));
453 if (!self->IsExceptionReportedToInstrumentation() && instrumentation->HasExceptionCaughtListeners()) {
454 CatchLocationFinder clf(self, &exception);
455 clf.WalkStack(false);
456 instrumentation->ExceptionCaughtEvent(self, throw_location, clf.GetCatchMethod(),
457 clf.GetCatchDexPc(), exception.Get());
458 self->SetExceptionReportedToInstrumentation(true);
459 }
Ian Rogers54874942014-06-10 16:31:03 -0700460 bool clear_exception = false;
461 uint32_t found_dex_pc;
462 {
Ian Rogers54874942014-06-10 16:31:03 -0700463 Handle<mirror::Class> exception_class(hs.NewHandle(exception->GetClass()));
464 Handle<mirror::ArtMethod> h_method(hs.NewHandle(shadow_frame.GetMethod()));
Ian Rogers54874942014-06-10 16:31:03 -0700465 found_dex_pc = mirror::ArtMethod::FindCatchBlock(h_method, exception_class, dex_pc,
466 &clear_exception);
467 }
468 if (found_dex_pc == DexFile::kDexNoIndex) {
Sebastien Hertz9f102032014-05-23 08:59:42 +0200469 instrumentation->MethodUnwindEvent(self, shadow_frame.GetThisObject(),
Ian Rogers54874942014-06-10 16:31:03 -0700470 shadow_frame.GetMethod(), dex_pc);
471 } else {
Sebastien Hertz9f102032014-05-23 08:59:42 +0200472 if (self->IsExceptionReportedToInstrumentation()) {
473 instrumentation->MethodUnwindEvent(self, shadow_frame.GetThisObject(),
474 shadow_frame.GetMethod(), dex_pc);
475 }
Ian Rogers54874942014-06-10 16:31:03 -0700476 if (clear_exception) {
477 self->ClearException();
478 }
479 }
480 return found_dex_pc;
481}
482
483void UnexpectedOpcode(const Instruction* inst, MethodHelper& mh) {
484 LOG(FATAL) << "Unexpected instruction: " << inst->DumpString(mh.GetMethod()->GetDexFile());
485 exit(0); // Unreachable, keep GCC happy.
486}
487
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200488static void UnstartedRuntimeInvoke(Thread* self, MethodHelper& mh,
489 const DexFile::CodeItem* code_item, ShadowFrame* shadow_frame,
490 JValue* result, size_t arg_offset)
491 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200492
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200493// Assign register 'src_reg' from shadow_frame to register 'dest_reg' into new_shadow_frame.
Ian Rogersef7d42f2014-01-06 12:55:46 -0800494static inline void AssignRegister(ShadowFrame* new_shadow_frame, const ShadowFrame& shadow_frame,
495 size_t dest_reg, size_t src_reg)
496 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200497 // If both register locations contains the same value, the register probably holds a reference.
Andreas Gampe7104cbf2014-03-21 11:44:43 -0700498 // Uint required, so that sign extension does not make this wrong on 64b systems
499 uint32_t src_value = shadow_frame.GetVReg(src_reg);
Mathieu Chartier4e305412014-02-19 10:54:44 -0800500 mirror::Object* o = shadow_frame.GetVRegReference<kVerifyNone>(src_reg);
Andreas Gampe7104cbf2014-03-21 11:44:43 -0700501 if (src_value == reinterpret_cast<uintptr_t>(o)) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800502 new_shadow_frame->SetVRegReference(dest_reg, o);
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200503 } else {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800504 new_shadow_frame->SetVReg(dest_reg, src_value);
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200505 }
506}
507
Mathieu Chartierb2c7ead2014-04-29 11:13:16 -0700508void AbortTransaction(Thread* self, const char* fmt, ...) {
509 CHECK(Runtime::Current()->IsActiveTransaction());
510 // Throw an exception so we can abort the transaction and undo every change.
511 va_list args;
512 va_start(args, fmt);
513 self->ThrowNewExceptionV(self->GetCurrentLocationForThrow(), "Ljava/lang/InternalError;", fmt,
514 args);
515 va_end(args);
516}
517
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200518template<bool is_range, bool do_assignability_check>
Sebastien Hertz9119c5f2013-12-16 11:31:45 +0100519bool DoCall(ArtMethod* method, Thread* self, ShadowFrame& shadow_frame,
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200520 const Instruction* inst, uint16_t inst_data, JValue* result) {
521 // Compute method information.
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700522 const DexFile::CodeItem* code_item = method->GetCodeItem();
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200523 const uint16_t num_ins = (is_range) ? inst->VRegA_3rc(inst_data) : inst->VRegA_35c(inst_data);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200524 uint16_t num_regs;
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200525 if (LIKELY(code_item != NULL)) {
526 num_regs = code_item->registers_size_;
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200527 DCHECK_EQ(num_ins, code_item->ins_size_);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200528 } else {
529 DCHECK(method->IsNative() || method->IsProxyMethod());
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200530 num_regs = num_ins;
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200531 }
532
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200533 // Allocate shadow frame on the stack.
Mathieu Chartiere861ebd2013-10-09 15:01:21 -0700534 const char* old_cause = self->StartAssertNoThreadSuspension("DoCall");
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200535 void* memory = alloca(ShadowFrame::ComputeSize(num_regs));
536 ShadowFrame* new_shadow_frame(ShadowFrame::Create(num_regs, &shadow_frame, method, 0, memory));
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200537
538 // Initialize new shadow frame.
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200539 const size_t first_dest_reg = num_regs - num_ins;
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700540 StackHandleScope<1> hs(self);
541 MethodHelper mh(hs.NewHandle(method));
Jeff Haoa3faaf42013-09-03 19:07:00 -0700542 if (do_assignability_check) {
Andreas Gampe2a0d4ec2014-06-02 22:05:22 -0700543 // Slow path.
544 // We might need to do class loading, which incurs a thread state change to kNative. So
545 // register the shadow frame as under construction and allow suspension again.
546 self->SetShadowFrameUnderConstruction(new_shadow_frame);
547 self->EndAssertNoThreadSuspension(old_cause);
548
549 // We need to do runtime check on reference assignment. We need to load the shorty
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200550 // to get the exact type of each reference argument.
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700551 const DexFile::TypeList* params = method->GetParameterTypeList();
552 uint32_t shorty_len = 0;
553 const char* shorty = method->GetShorty(&shorty_len);
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200554
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200555 // TODO: find a cleaner way to separate non-range and range information without duplicating code.
556 uint32_t arg[5]; // only used in invoke-XXX.
557 uint32_t vregC; // only used in invoke-XXX-range.
558 if (is_range) {
559 vregC = inst->VRegC_3rc();
560 } else {
Ian Rogers29a26482014-05-02 15:27:29 -0700561 inst->GetVarArgs(arg, inst_data);
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200562 }
Sebastien Hertz9119c5f2013-12-16 11:31:45 +0100563
564 // Handle receiver apart since it's not part of the shorty.
565 size_t dest_reg = first_dest_reg;
566 size_t arg_offset = 0;
567 if (!method->IsStatic()) {
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700568 size_t receiver_reg = is_range ? vregC : arg[0];
Sebastien Hertz9119c5f2013-12-16 11:31:45 +0100569 new_shadow_frame->SetVRegReference(dest_reg, shadow_frame.GetVRegReference(receiver_reg));
570 ++dest_reg;
571 ++arg_offset;
572 }
Ian Rogersef7d42f2014-01-06 12:55:46 -0800573 for (uint32_t shorty_pos = 0; dest_reg < num_regs; ++shorty_pos, ++dest_reg, ++arg_offset) {
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700574 DCHECK_LT(shorty_pos + 1, shorty_len);
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200575 const size_t src_reg = (is_range) ? vregC + arg_offset : arg[arg_offset];
576 switch (shorty[shorty_pos + 1]) {
577 case 'L': {
578 Object* o = shadow_frame.GetVRegReference(src_reg);
579 if (do_assignability_check && o != NULL) {
580 Class* arg_type = mh.GetClassFromTypeIdx(params->GetTypeItem(shorty_pos).type_idx_);
581 if (arg_type == NULL) {
582 CHECK(self->IsExceptionPending());
583 return false;
584 }
585 if (!o->VerifierInstanceOf(arg_type)) {
586 // This should never happen.
587 self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
588 "Ljava/lang/VirtualMachineError;",
589 "Invoking %s with bad arg %d, type '%s' not instance of '%s'",
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700590 method->GetName(), shorty_pos,
Mathieu Chartierf8322842014-05-16 10:59:25 -0700591 o->GetClass()->GetDescriptor().c_str(),
592 arg_type->GetDescriptor().c_str());
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200593 return false;
594 }
Jeff Haoa3faaf42013-09-03 19:07:00 -0700595 }
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200596 new_shadow_frame->SetVRegReference(dest_reg, o);
597 break;
Jeff Haoa3faaf42013-09-03 19:07:00 -0700598 }
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200599 case 'J': case 'D': {
600 uint64_t wide_value = (static_cast<uint64_t>(shadow_frame.GetVReg(src_reg + 1)) << 32) |
601 static_cast<uint32_t>(shadow_frame.GetVReg(src_reg));
602 new_shadow_frame->SetVRegLong(dest_reg, wide_value);
603 ++dest_reg;
604 ++arg_offset;
605 break;
606 }
607 default:
608 new_shadow_frame->SetVReg(dest_reg, shadow_frame.GetVReg(src_reg));
609 break;
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200610 }
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200611 }
Andreas Gampe2a0d4ec2014-06-02 22:05:22 -0700612 // We're done with the construction.
613 self->ClearShadowFrameUnderConstruction();
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200614 } else {
615 // Fast path: no extra checks.
616 if (is_range) {
617 const uint16_t first_src_reg = inst->VRegC_3rc();
618 for (size_t src_reg = first_src_reg, dest_reg = first_dest_reg; dest_reg < num_regs;
619 ++dest_reg, ++src_reg) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800620 AssignRegister(new_shadow_frame, shadow_frame, dest_reg, src_reg);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200621 }
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200622 } else {
623 DCHECK_LE(num_ins, 5U);
624 uint16_t regList = inst->Fetch16(2);
625 uint16_t count = num_ins;
626 if (count == 5) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800627 AssignRegister(new_shadow_frame, shadow_frame, first_dest_reg + 4U, (inst_data >> 8) & 0x0f);
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200628 --count;
629 }
630 for (size_t arg_index = 0; arg_index < count; ++arg_index, regList >>= 4) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800631 AssignRegister(new_shadow_frame, shadow_frame, first_dest_reg + arg_index, regList & 0x0f);
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200632 }
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200633 }
Andreas Gampe2a0d4ec2014-06-02 22:05:22 -0700634 self->EndAssertNoThreadSuspension(old_cause);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200635 }
636
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200637 // Do the call now.
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200638 if (LIKELY(Runtime::Current()->IsStarted())) {
Ian Rogers1d99e452014-01-02 17:36:41 -0800639 if (kIsDebugBuild && method->GetEntryPointFromInterpreter() == nullptr) {
640 LOG(FATAL) << "Attempt to invoke non-executable method: " << PrettyMethod(method);
641 }
Hiroshi Yamauchi563b47c2014-02-28 17:18:37 -0800642 if (kIsDebugBuild && Runtime::Current()->GetInstrumentation()->IsForcedInterpretOnly() &&
643 !method->IsNative() && !method->IsProxyMethod() &&
644 method->GetEntryPointFromInterpreter() == artInterpreterToCompiledCodeBridge) {
645 LOG(FATAL) << "Attempt to call compiled code when -Xint: " << PrettyMethod(method);
646 }
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200647 (method->GetEntryPointFromInterpreter())(self, mh, code_item, new_shadow_frame, result);
648 } else {
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200649 UnstartedRuntimeInvoke(self, mh, code_item, new_shadow_frame, result, first_dest_reg);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200650 }
651 return !self->IsExceptionPending();
652}
653
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100654template <bool is_range, bool do_access_check, bool transaction_active>
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200655bool DoFilledNewArray(const Instruction* inst, const ShadowFrame& shadow_frame,
656 Thread* self, JValue* result) {
657 DCHECK(inst->Opcode() == Instruction::FILLED_NEW_ARRAY ||
658 inst->Opcode() == Instruction::FILLED_NEW_ARRAY_RANGE);
659 const int32_t length = is_range ? inst->VRegA_3rc() : inst->VRegA_35c();
660 if (!is_range) {
661 // Checks FILLED_NEW_ARRAY's length does not exceed 5 arguments.
662 CHECK_LE(length, 5);
663 }
664 if (UNLIKELY(length < 0)) {
665 ThrowNegativeArraySizeException(length);
666 return false;
667 }
668 uint16_t type_idx = is_range ? inst->VRegB_3rc() : inst->VRegB_35c();
669 Class* arrayClass = ResolveVerifyAndClinit(type_idx, shadow_frame.GetMethod(),
670 self, false, do_access_check);
671 if (UNLIKELY(arrayClass == NULL)) {
672 DCHECK(self->IsExceptionPending());
673 return false;
674 }
675 CHECK(arrayClass->IsArrayClass());
676 Class* componentClass = arrayClass->GetComponentType();
677 if (UNLIKELY(componentClass->IsPrimitive() && !componentClass->IsPrimitiveInt())) {
678 if (componentClass->IsPrimitiveLong() || componentClass->IsPrimitiveDouble()) {
679 ThrowRuntimeException("Bad filled array request for type %s",
680 PrettyDescriptor(componentClass).c_str());
681 } else {
682 self->ThrowNewExceptionF(shadow_frame.GetCurrentLocationForThrow(),
683 "Ljava/lang/InternalError;",
Brian Carlstrom4fa0bcd2013-12-10 11:24:21 -0800684 "Found type %s; filled-new-array not implemented for anything but 'int'",
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200685 PrettyDescriptor(componentClass).c_str());
686 }
687 return false;
688 }
Ian Rogers6fac4472014-02-25 17:01:10 -0800689 Object* newArray = Array::Alloc<true>(self, arrayClass, length, arrayClass->GetComponentSize(),
690 Runtime::Current()->GetHeap()->GetCurrentAllocator());
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200691 if (UNLIKELY(newArray == NULL)) {
692 DCHECK(self->IsExceptionPending());
693 return false;
694 }
Sebastien Hertzabff6432014-01-27 18:01:39 +0100695 uint32_t arg[5]; // only used in filled-new-array.
696 uint32_t vregC; // only used in filled-new-array-range.
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200697 if (is_range) {
Sebastien Hertzabff6432014-01-27 18:01:39 +0100698 vregC = inst->VRegC_3rc();
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200699 } else {
Ian Rogers29a26482014-05-02 15:27:29 -0700700 inst->GetVarArgs(arg);
Sebastien Hertzabff6432014-01-27 18:01:39 +0100701 }
702 const bool is_primitive_int_component = componentClass->IsPrimitiveInt();
703 for (int32_t i = 0; i < length; ++i) {
704 size_t src_reg = is_range ? vregC + i : arg[i];
705 if (is_primitive_int_component) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100706 newArray->AsIntArray()->SetWithoutChecks<transaction_active>(i, shadow_frame.GetVReg(src_reg));
Sebastien Hertzabff6432014-01-27 18:01:39 +0100707 } else {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100708 newArray->AsObjectArray<Object>()->SetWithoutChecks<transaction_active>(i, shadow_frame.GetVRegReference(src_reg));
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200709 }
710 }
711
712 result->SetL(newArray);
713 return true;
714}
715
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100716// TODO fix thread analysis: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_).
717template<typename T>
718static void RecordArrayElementsInTransactionImpl(mirror::PrimitiveArray<T>* array, int32_t count)
719 NO_THREAD_SAFETY_ANALYSIS {
720 Runtime* runtime = Runtime::Current();
721 for (int32_t i = 0; i < count; ++i) {
722 runtime->RecordWriteArray(array, i, array->GetWithoutChecks(i));
723 }
724}
725
726void RecordArrayElementsInTransaction(mirror::Array* array, int32_t count)
727 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
728 DCHECK(Runtime::Current()->IsActiveTransaction());
729 DCHECK(array != nullptr);
730 DCHECK_LE(count, array->GetLength());
731 Primitive::Type primitive_component_type = array->GetClass()->GetComponentType()->GetPrimitiveType();
732 switch (primitive_component_type) {
733 case Primitive::kPrimBoolean:
734 RecordArrayElementsInTransactionImpl(array->AsBooleanArray(), count);
735 break;
736 case Primitive::kPrimByte:
737 RecordArrayElementsInTransactionImpl(array->AsByteArray(), count);
738 break;
739 case Primitive::kPrimChar:
740 RecordArrayElementsInTransactionImpl(array->AsCharArray(), count);
741 break;
742 case Primitive::kPrimShort:
743 RecordArrayElementsInTransactionImpl(array->AsShortArray(), count);
744 break;
745 case Primitive::kPrimInt:
746 case Primitive::kPrimFloat:
747 RecordArrayElementsInTransactionImpl(array->AsIntArray(), count);
748 break;
749 case Primitive::kPrimLong:
750 case Primitive::kPrimDouble:
751 RecordArrayElementsInTransactionImpl(array->AsLongArray(), count);
752 break;
753 default:
754 LOG(FATAL) << "Unsupported primitive type " << primitive_component_type
755 << " in fill-array-data";
756 break;
757 }
758}
759
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200760static void UnstartedRuntimeInvoke(Thread* self, MethodHelper& mh,
761 const DexFile::CodeItem* code_item, ShadowFrame* shadow_frame,
762 JValue* result, size_t arg_offset) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200763 // In a runtime that's not started we intercept certain methods to avoid complicated dependency
764 // problems in core libraries.
765 std::string name(PrettyMethod(shadow_frame->GetMethod()));
Kenny Rootfa31b3c2013-12-09 13:51:32 -0800766 if (name == "java.lang.Class java.lang.Class.forName(java.lang.String)"
767 || name == "java.lang.Class java.lang.VMClassLoader.loadClass(java.lang.String, boolean)") {
768 // TODO Class#forName should actually call Class::EnsureInitialized always. Support for the
769 // other variants that take more arguments should also be added.
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200770 std::string descriptor(DotToDescriptor(shadow_frame->GetVRegReference(arg_offset)->AsString()->ToModifiedUtf8().c_str()));
Mathieu Chartier590fee92013-09-13 13:46:47 -0700771
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700772 // shadow_frame.GetMethod()->GetDeclaringClass()->GetClassLoader();
Mathieu Chartier0cd81352014-05-22 16:48:55 -0700773 Class* found = Runtime::Current()->GetClassLinker()->FindClass(
774 self, descriptor.c_str(), NullHandle<mirror::ClassLoader>());
Sean Wan7b1cabf2014-07-09 12:08:29 -0700775 if (found == NULL) {
776 if (!self->IsExceptionPending()) {
777 AbortTransaction(self, "Class.forName failed in un-started runtime for class: %s",
778 PrettyDescriptor(descriptor).c_str());
779 }
780 return;
781 }
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200782 result->SetL(found);
Ian Rogersc45b8b52014-05-03 01:39:59 -0700783 } else if (name == "java.lang.Class java.lang.Void.lookupType()") {
784 result->SetL(Runtime::Current()->GetClassLinker()->FindPrimitiveClass('V'));
Kenny Rootfa31b3c2013-12-09 13:51:32 -0800785 } else if (name == "java.lang.Class java.lang.VMClassLoader.findLoadedClass(java.lang.ClassLoader, java.lang.String)") {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700786 StackHandleScope<1> hs(self);
787 Handle<ClassLoader> class_loader(
788 hs.NewHandle(down_cast<mirror::ClassLoader*>(shadow_frame->GetVRegReference(arg_offset))));
Kenny Rootfa31b3c2013-12-09 13:51:32 -0800789 std::string descriptor(DotToDescriptor(shadow_frame->GetVRegReference(arg_offset + 1)->AsString()->ToModifiedUtf8().c_str()));
790
Ian Rogers98379392014-02-24 16:53:16 -0800791 Class* found = Runtime::Current()->GetClassLinker()->FindClass(self, descriptor.c_str(),
Kenny Rootfa31b3c2013-12-09 13:51:32 -0800792 class_loader);
793 result->SetL(found);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200794 } else if (name == "java.lang.Object java.lang.Class.newInstance()") {
795 Class* klass = shadow_frame->GetVRegReference(arg_offset)->AsClass();
796 ArtMethod* c = klass->FindDeclaredDirectMethod("<init>", "()V");
797 CHECK(c != NULL);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700798 StackHandleScope<1> hs(self);
799 Handle<Object> obj(hs.NewHandle(klass->AllocObject(self)));
800 CHECK(obj.Get() != NULL);
801 EnterInterpreterFromInvoke(self, c, obj.Get(), NULL, NULL);
802 result->SetL(obj.Get());
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200803 } else if (name == "java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String)") {
804 // Special managed code cut-out to allow field lookup in a un-started runtime that'd fail
805 // going the reflective Dex way.
806 Class* klass = shadow_frame->GetVRegReference(arg_offset)->AsClass();
807 String* name = shadow_frame->GetVRegReference(arg_offset + 1)->AsString();
808 ArtField* found = NULL;
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200809 ObjectArray<ArtField>* fields = klass->GetIFields();
810 for (int32_t i = 0; i < fields->GetLength() && found == NULL; ++i) {
811 ArtField* f = fields->Get(i);
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700812 if (name->Equals(f->GetName())) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200813 found = f;
814 }
815 }
816 if (found == NULL) {
817 fields = klass->GetSFields();
818 for (int32_t i = 0; i < fields->GetLength() && found == NULL; ++i) {
819 ArtField* f = fields->Get(i);
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700820 if (name->Equals(f->GetName())) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200821 found = f;
822 }
823 }
824 }
825 CHECK(found != NULL)
826 << "Failed to find field in Class.getDeclaredField in un-started runtime. name="
827 << name->ToModifiedUtf8() << " class=" << PrettyDescriptor(klass);
828 // TODO: getDeclaredField calls GetType once the field is found to ensure a
829 // NoClassDefFoundError is thrown if the field's type cannot be resolved.
830 Class* jlr_Field = self->DecodeJObject(WellKnownClasses::java_lang_reflect_Field)->AsClass();
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700831 StackHandleScope<1> hs(self);
832 Handle<Object> field(hs.NewHandle(jlr_Field->AllocNonMovableObject(self)));
833 CHECK(field.Get() != NULL);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200834 ArtMethod* c = jlr_Field->FindDeclaredDirectMethod("<init>", "(Ljava/lang/reflect/ArtField;)V");
835 uint32_t args[1];
Ian Rogersef7d42f2014-01-06 12:55:46 -0800836 args[0] = StackReference<mirror::Object>::FromMirrorPtr(found).AsVRegValue();
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700837 EnterInterpreterFromInvoke(self, c, field.Get(), args, NULL);
838 result->SetL(field.Get());
Ian Rogersc45b8b52014-05-03 01:39:59 -0700839 } else if (name == "int java.lang.Object.hashCode()") {
840 Object* obj = shadow_frame->GetVRegReference(arg_offset);
841 result->SetI(obj->IdentityHashCode());
842 } else if (name == "java.lang.String java.lang.reflect.ArtMethod.getMethodName(java.lang.reflect.ArtMethod)") {
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700843 StackHandleScope<1> hs(self);
844 MethodHelper mh(hs.NewHandle(shadow_frame->GetVRegReference(arg_offset)->AsArtMethod()));
845 result->SetL(mh.GetNameAsString(self));
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200846 } else if (name == "void java.lang.System.arraycopy(java.lang.Object, int, java.lang.Object, int, int)" ||
847 name == "void java.lang.System.arraycopy(char[], int, char[], int, int)") {
848 // Special case array copying without initializing System.
849 Class* ctype = shadow_frame->GetVRegReference(arg_offset)->GetClass()->GetComponentType();
850 jint srcPos = shadow_frame->GetVReg(arg_offset + 1);
851 jint dstPos = shadow_frame->GetVReg(arg_offset + 3);
852 jint length = shadow_frame->GetVReg(arg_offset + 4);
853 if (!ctype->IsPrimitive()) {
854 ObjectArray<Object>* src = shadow_frame->GetVRegReference(arg_offset)->AsObjectArray<Object>();
855 ObjectArray<Object>* dst = shadow_frame->GetVRegReference(arg_offset + 2)->AsObjectArray<Object>();
856 for (jint i = 0; i < length; ++i) {
857 dst->Set(dstPos + i, src->Get(srcPos + i));
858 }
859 } else if (ctype->IsPrimitiveChar()) {
860 CharArray* src = shadow_frame->GetVRegReference(arg_offset)->AsCharArray();
861 CharArray* dst = shadow_frame->GetVRegReference(arg_offset + 2)->AsCharArray();
862 for (jint i = 0; i < length; ++i) {
863 dst->Set(dstPos + i, src->Get(srcPos + i));
864 }
865 } else if (ctype->IsPrimitiveInt()) {
866 IntArray* src = shadow_frame->GetVRegReference(arg_offset)->AsIntArray();
867 IntArray* dst = shadow_frame->GetVRegReference(arg_offset + 2)->AsIntArray();
868 for (jint i = 0; i < length; ++i) {
869 dst->Set(dstPos + i, src->Get(srcPos + i));
870 }
871 } else {
Ian Rogersc45b8b52014-05-03 01:39:59 -0700872 self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(), "Ljava/lang/InternalError;",
873 "Unimplemented System.arraycopy for type '%s'",
874 PrettyDescriptor(ctype).c_str());
875 }
876 } else if (name == "java.lang.Object java.lang.ThreadLocal.get()") {
877 std::string caller(PrettyMethod(shadow_frame->GetLink()->GetMethod()));
878 if (caller == "java.lang.String java.lang.IntegralToString.convertInt(java.lang.AbstractStringBuilder, int)") {
879 // Allocate non-threadlocal buffer.
880 result->SetL(mirror::CharArray::Alloc(self, 11));
881 } else {
882 self->ThrowNewException(self->GetCurrentLocationForThrow(), "Ljava/lang/InternalError;",
883 "Unimplemented ThreadLocal.get");
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200884 }
885 } else {
886 // Not special, continue with regular interpreter execution.
887 artInterpreterToInterpreterBridge(self, mh, code_item, shadow_frame, result);
888 }
889}
890
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200891// Explicit DoCall template function declarations.
Sebastien Hertzc6714852013-09-30 16:42:32 +0200892#define EXPLICIT_DO_CALL_TEMPLATE_DECL(_is_range, _do_assignability_check) \
893 template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) \
Sebastien Hertz9119c5f2013-12-16 11:31:45 +0100894 bool DoCall<_is_range, _do_assignability_check>(ArtMethod* method, Thread* self, \
895 ShadowFrame& shadow_frame, \
Sebastien Hertzc6714852013-09-30 16:42:32 +0200896 const Instruction* inst, uint16_t inst_data, \
897 JValue* result)
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200898EXPLICIT_DO_CALL_TEMPLATE_DECL(false, false);
899EXPLICIT_DO_CALL_TEMPLATE_DECL(false, true);
900EXPLICIT_DO_CALL_TEMPLATE_DECL(true, false);
901EXPLICIT_DO_CALL_TEMPLATE_DECL(true, true);
902#undef EXPLICIT_DO_CALL_TEMPLATE_DECL
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200903
904// Explicit DoFilledNewArray template function declarations.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100905#define EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL(_is_range_, _check, _transaction_active) \
906 template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) \
907 bool DoFilledNewArray<_is_range_, _check, _transaction_active>(const Instruction* inst, \
908 const ShadowFrame& shadow_frame, \
909 Thread* self, JValue* result)
910#define EXPLICIT_DO_FILLED_NEW_ARRAY_ALL_TEMPLATE_DECL(_transaction_active) \
911 EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL(false, false, _transaction_active); \
912 EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL(false, true, _transaction_active); \
913 EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL(true, false, _transaction_active); \
914 EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL(true, true, _transaction_active)
915EXPLICIT_DO_FILLED_NEW_ARRAY_ALL_TEMPLATE_DECL(false);
916EXPLICIT_DO_FILLED_NEW_ARRAY_ALL_TEMPLATE_DECL(true);
917#undef EXPLICIT_DO_FILLED_NEW_ARRAY_ALL_TEMPLATE_DECL
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200918#undef EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL
919
920} // namespace interpreter
921} // namespace art