blob: e1fe5632464b757563a4e3726efcfbab325c7641 [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
375uint32_t FindNextInstructionFollowingException(Thread* self,
376 ShadowFrame& shadow_frame,
377 uint32_t dex_pc,
378 mirror::Object* this_object,
379 const instrumentation::Instrumentation* instrumentation) {
380 self->VerifyStack();
381 ThrowLocation throw_location;
382 mirror::Throwable* exception = self->GetException(&throw_location);
383 bool clear_exception = false;
384 uint32_t found_dex_pc;
385 {
386 StackHandleScope<3> hs(self);
387 Handle<mirror::Class> exception_class(hs.NewHandle(exception->GetClass()));
388 Handle<mirror::ArtMethod> h_method(hs.NewHandle(shadow_frame.GetMethod()));
389 HandleWrapper<mirror::Object> h(hs.NewHandleWrapper(&this_object));
390 found_dex_pc = mirror::ArtMethod::FindCatchBlock(h_method, exception_class, dex_pc,
391 &clear_exception);
392 }
393 if (found_dex_pc == DexFile::kDexNoIndex) {
394 instrumentation->MethodUnwindEvent(self, this_object,
395 shadow_frame.GetMethod(), dex_pc);
396 } else {
397 instrumentation->ExceptionCaughtEvent(self, throw_location,
398 shadow_frame.GetMethod(),
399 found_dex_pc, exception);
400 if (clear_exception) {
401 self->ClearException();
402 }
403 }
404 return found_dex_pc;
405}
406
407void UnexpectedOpcode(const Instruction* inst, MethodHelper& mh) {
408 LOG(FATAL) << "Unexpected instruction: " << inst->DumpString(mh.GetMethod()->GetDexFile());
409 exit(0); // Unreachable, keep GCC happy.
410}
411
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200412static void UnstartedRuntimeInvoke(Thread* self, MethodHelper& mh,
413 const DexFile::CodeItem* code_item, ShadowFrame* shadow_frame,
414 JValue* result, size_t arg_offset)
415 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200416
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200417// Assign register 'src_reg' from shadow_frame to register 'dest_reg' into new_shadow_frame.
Ian Rogersef7d42f2014-01-06 12:55:46 -0800418static inline void AssignRegister(ShadowFrame* new_shadow_frame, const ShadowFrame& shadow_frame,
419 size_t dest_reg, size_t src_reg)
420 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200421 // If both register locations contains the same value, the register probably holds a reference.
Andreas Gampe7104cbf2014-03-21 11:44:43 -0700422 // Uint required, so that sign extension does not make this wrong on 64b systems
423 uint32_t src_value = shadow_frame.GetVReg(src_reg);
Mathieu Chartier4e305412014-02-19 10:54:44 -0800424 mirror::Object* o = shadow_frame.GetVRegReference<kVerifyNone>(src_reg);
Andreas Gampe7104cbf2014-03-21 11:44:43 -0700425 if (src_value == reinterpret_cast<uintptr_t>(o)) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800426 new_shadow_frame->SetVRegReference(dest_reg, o);
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200427 } else {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800428 new_shadow_frame->SetVReg(dest_reg, src_value);
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200429 }
430}
431
Mathieu Chartierb2c7ead2014-04-29 11:13:16 -0700432void AbortTransaction(Thread* self, const char* fmt, ...) {
433 CHECK(Runtime::Current()->IsActiveTransaction());
434 // Throw an exception so we can abort the transaction and undo every change.
435 va_list args;
436 va_start(args, fmt);
437 self->ThrowNewExceptionV(self->GetCurrentLocationForThrow(), "Ljava/lang/InternalError;", fmt,
438 args);
439 va_end(args);
440}
441
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200442template<bool is_range, bool do_assignability_check>
Sebastien Hertz9119c5f2013-12-16 11:31:45 +0100443bool DoCall(ArtMethod* method, Thread* self, ShadowFrame& shadow_frame,
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200444 const Instruction* inst, uint16_t inst_data, JValue* result) {
445 // Compute method information.
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700446 const DexFile::CodeItem* code_item = method->GetCodeItem();
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200447 const uint16_t num_ins = (is_range) ? inst->VRegA_3rc(inst_data) : inst->VRegA_35c(inst_data);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200448 uint16_t num_regs;
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200449 if (LIKELY(code_item != NULL)) {
450 num_regs = code_item->registers_size_;
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200451 DCHECK_EQ(num_ins, code_item->ins_size_);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200452 } else {
453 DCHECK(method->IsNative() || method->IsProxyMethod());
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200454 num_regs = num_ins;
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200455 }
456
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200457 // Allocate shadow frame on the stack.
Mathieu Chartiere861ebd2013-10-09 15:01:21 -0700458 const char* old_cause = self->StartAssertNoThreadSuspension("DoCall");
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200459 void* memory = alloca(ShadowFrame::ComputeSize(num_regs));
460 ShadowFrame* new_shadow_frame(ShadowFrame::Create(num_regs, &shadow_frame, method, 0, memory));
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200461
462 // Initialize new shadow frame.
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200463 const size_t first_dest_reg = num_regs - num_ins;
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700464 StackHandleScope<1> hs(self);
465 MethodHelper mh(hs.NewHandle(method));
Jeff Haoa3faaf42013-09-03 19:07:00 -0700466 if (do_assignability_check) {
Andreas Gampe2a0d4ec2014-06-02 22:05:22 -0700467 // Slow path.
468 // We might need to do class loading, which incurs a thread state change to kNative. So
469 // register the shadow frame as under construction and allow suspension again.
470 self->SetShadowFrameUnderConstruction(new_shadow_frame);
471 self->EndAssertNoThreadSuspension(old_cause);
472
473 // We need to do runtime check on reference assignment. We need to load the shorty
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200474 // to get the exact type of each reference argument.
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700475 const DexFile::TypeList* params = method->GetParameterTypeList();
476 uint32_t shorty_len = 0;
477 const char* shorty = method->GetShorty(&shorty_len);
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200478
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200479 // TODO: find a cleaner way to separate non-range and range information without duplicating code.
480 uint32_t arg[5]; // only used in invoke-XXX.
481 uint32_t vregC; // only used in invoke-XXX-range.
482 if (is_range) {
483 vregC = inst->VRegC_3rc();
484 } else {
Ian Rogers29a26482014-05-02 15:27:29 -0700485 inst->GetVarArgs(arg, inst_data);
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200486 }
Sebastien Hertz9119c5f2013-12-16 11:31:45 +0100487
488 // Handle receiver apart since it's not part of the shorty.
489 size_t dest_reg = first_dest_reg;
490 size_t arg_offset = 0;
491 if (!method->IsStatic()) {
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700492 size_t receiver_reg = is_range ? vregC : arg[0];
Sebastien Hertz9119c5f2013-12-16 11:31:45 +0100493 new_shadow_frame->SetVRegReference(dest_reg, shadow_frame.GetVRegReference(receiver_reg));
494 ++dest_reg;
495 ++arg_offset;
496 }
Ian Rogersef7d42f2014-01-06 12:55:46 -0800497 for (uint32_t shorty_pos = 0; dest_reg < num_regs; ++shorty_pos, ++dest_reg, ++arg_offset) {
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700498 DCHECK_LT(shorty_pos + 1, shorty_len);
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200499 const size_t src_reg = (is_range) ? vregC + arg_offset : arg[arg_offset];
500 switch (shorty[shorty_pos + 1]) {
501 case 'L': {
502 Object* o = shadow_frame.GetVRegReference(src_reg);
503 if (do_assignability_check && o != NULL) {
504 Class* arg_type = mh.GetClassFromTypeIdx(params->GetTypeItem(shorty_pos).type_idx_);
505 if (arg_type == NULL) {
506 CHECK(self->IsExceptionPending());
507 return false;
508 }
509 if (!o->VerifierInstanceOf(arg_type)) {
510 // This should never happen.
511 self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
512 "Ljava/lang/VirtualMachineError;",
513 "Invoking %s with bad arg %d, type '%s' not instance of '%s'",
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700514 method->GetName(), shorty_pos,
Mathieu Chartierf8322842014-05-16 10:59:25 -0700515 o->GetClass()->GetDescriptor().c_str(),
516 arg_type->GetDescriptor().c_str());
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200517 return false;
518 }
Jeff Haoa3faaf42013-09-03 19:07:00 -0700519 }
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200520 new_shadow_frame->SetVRegReference(dest_reg, o);
521 break;
Jeff Haoa3faaf42013-09-03 19:07:00 -0700522 }
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200523 case 'J': case 'D': {
524 uint64_t wide_value = (static_cast<uint64_t>(shadow_frame.GetVReg(src_reg + 1)) << 32) |
525 static_cast<uint32_t>(shadow_frame.GetVReg(src_reg));
526 new_shadow_frame->SetVRegLong(dest_reg, wide_value);
527 ++dest_reg;
528 ++arg_offset;
529 break;
530 }
531 default:
532 new_shadow_frame->SetVReg(dest_reg, shadow_frame.GetVReg(src_reg));
533 break;
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200534 }
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200535 }
Andreas Gampe2a0d4ec2014-06-02 22:05:22 -0700536 // We're done with the construction.
537 self->ClearShadowFrameUnderConstruction();
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200538 } else {
539 // Fast path: no extra checks.
540 if (is_range) {
541 const uint16_t first_src_reg = inst->VRegC_3rc();
542 for (size_t src_reg = first_src_reg, dest_reg = first_dest_reg; dest_reg < num_regs;
543 ++dest_reg, ++src_reg) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800544 AssignRegister(new_shadow_frame, shadow_frame, dest_reg, src_reg);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200545 }
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200546 } else {
547 DCHECK_LE(num_ins, 5U);
548 uint16_t regList = inst->Fetch16(2);
549 uint16_t count = num_ins;
550 if (count == 5) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800551 AssignRegister(new_shadow_frame, shadow_frame, first_dest_reg + 4U, (inst_data >> 8) & 0x0f);
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200552 --count;
553 }
554 for (size_t arg_index = 0; arg_index < count; ++arg_index, regList >>= 4) {
Ian Rogersef7d42f2014-01-06 12:55:46 -0800555 AssignRegister(new_shadow_frame, shadow_frame, first_dest_reg + arg_index, regList & 0x0f);
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200556 }
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200557 }
Andreas Gampe2a0d4ec2014-06-02 22:05:22 -0700558 self->EndAssertNoThreadSuspension(old_cause);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200559 }
560
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200561 // Do the call now.
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200562 if (LIKELY(Runtime::Current()->IsStarted())) {
Ian Rogers1d99e452014-01-02 17:36:41 -0800563 if (kIsDebugBuild && method->GetEntryPointFromInterpreter() == nullptr) {
564 LOG(FATAL) << "Attempt to invoke non-executable method: " << PrettyMethod(method);
565 }
Hiroshi Yamauchi563b47c2014-02-28 17:18:37 -0800566 if (kIsDebugBuild && Runtime::Current()->GetInstrumentation()->IsForcedInterpretOnly() &&
567 !method->IsNative() && !method->IsProxyMethod() &&
568 method->GetEntryPointFromInterpreter() == artInterpreterToCompiledCodeBridge) {
569 LOG(FATAL) << "Attempt to call compiled code when -Xint: " << PrettyMethod(method);
570 }
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200571 (method->GetEntryPointFromInterpreter())(self, mh, code_item, new_shadow_frame, result);
572 } else {
Sebastien Hertz9ace87b2013-09-27 11:48:09 +0200573 UnstartedRuntimeInvoke(self, mh, code_item, new_shadow_frame, result, first_dest_reg);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200574 }
575 return !self->IsExceptionPending();
576}
577
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100578template <bool is_range, bool do_access_check, bool transaction_active>
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200579bool DoFilledNewArray(const Instruction* inst, const ShadowFrame& shadow_frame,
580 Thread* self, JValue* result) {
581 DCHECK(inst->Opcode() == Instruction::FILLED_NEW_ARRAY ||
582 inst->Opcode() == Instruction::FILLED_NEW_ARRAY_RANGE);
583 const int32_t length = is_range ? inst->VRegA_3rc() : inst->VRegA_35c();
584 if (!is_range) {
585 // Checks FILLED_NEW_ARRAY's length does not exceed 5 arguments.
586 CHECK_LE(length, 5);
587 }
588 if (UNLIKELY(length < 0)) {
589 ThrowNegativeArraySizeException(length);
590 return false;
591 }
592 uint16_t type_idx = is_range ? inst->VRegB_3rc() : inst->VRegB_35c();
593 Class* arrayClass = ResolveVerifyAndClinit(type_idx, shadow_frame.GetMethod(),
594 self, false, do_access_check);
595 if (UNLIKELY(arrayClass == NULL)) {
596 DCHECK(self->IsExceptionPending());
597 return false;
598 }
599 CHECK(arrayClass->IsArrayClass());
600 Class* componentClass = arrayClass->GetComponentType();
601 if (UNLIKELY(componentClass->IsPrimitive() && !componentClass->IsPrimitiveInt())) {
602 if (componentClass->IsPrimitiveLong() || componentClass->IsPrimitiveDouble()) {
603 ThrowRuntimeException("Bad filled array request for type %s",
604 PrettyDescriptor(componentClass).c_str());
605 } else {
606 self->ThrowNewExceptionF(shadow_frame.GetCurrentLocationForThrow(),
607 "Ljava/lang/InternalError;",
Brian Carlstrom4fa0bcd2013-12-10 11:24:21 -0800608 "Found type %s; filled-new-array not implemented for anything but 'int'",
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200609 PrettyDescriptor(componentClass).c_str());
610 }
611 return false;
612 }
Ian Rogers6fac4472014-02-25 17:01:10 -0800613 Object* newArray = Array::Alloc<true>(self, arrayClass, length, arrayClass->GetComponentSize(),
614 Runtime::Current()->GetHeap()->GetCurrentAllocator());
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200615 if (UNLIKELY(newArray == NULL)) {
616 DCHECK(self->IsExceptionPending());
617 return false;
618 }
Sebastien Hertzabff6432014-01-27 18:01:39 +0100619 uint32_t arg[5]; // only used in filled-new-array.
620 uint32_t vregC; // only used in filled-new-array-range.
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200621 if (is_range) {
Sebastien Hertzabff6432014-01-27 18:01:39 +0100622 vregC = inst->VRegC_3rc();
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200623 } else {
Ian Rogers29a26482014-05-02 15:27:29 -0700624 inst->GetVarArgs(arg);
Sebastien Hertzabff6432014-01-27 18:01:39 +0100625 }
626 const bool is_primitive_int_component = componentClass->IsPrimitiveInt();
627 for (int32_t i = 0; i < length; ++i) {
628 size_t src_reg = is_range ? vregC + i : arg[i];
629 if (is_primitive_int_component) {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100630 newArray->AsIntArray()->SetWithoutChecks<transaction_active>(i, shadow_frame.GetVReg(src_reg));
Sebastien Hertzabff6432014-01-27 18:01:39 +0100631 } else {
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100632 newArray->AsObjectArray<Object>()->SetWithoutChecks<transaction_active>(i, shadow_frame.GetVRegReference(src_reg));
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200633 }
634 }
635
636 result->SetL(newArray);
637 return true;
638}
639
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100640// TODO fix thread analysis: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_).
641template<typename T>
642static void RecordArrayElementsInTransactionImpl(mirror::PrimitiveArray<T>* array, int32_t count)
643 NO_THREAD_SAFETY_ANALYSIS {
644 Runtime* runtime = Runtime::Current();
645 for (int32_t i = 0; i < count; ++i) {
646 runtime->RecordWriteArray(array, i, array->GetWithoutChecks(i));
647 }
648}
649
650void RecordArrayElementsInTransaction(mirror::Array* array, int32_t count)
651 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
652 DCHECK(Runtime::Current()->IsActiveTransaction());
653 DCHECK(array != nullptr);
654 DCHECK_LE(count, array->GetLength());
655 Primitive::Type primitive_component_type = array->GetClass()->GetComponentType()->GetPrimitiveType();
656 switch (primitive_component_type) {
657 case Primitive::kPrimBoolean:
658 RecordArrayElementsInTransactionImpl(array->AsBooleanArray(), count);
659 break;
660 case Primitive::kPrimByte:
661 RecordArrayElementsInTransactionImpl(array->AsByteArray(), count);
662 break;
663 case Primitive::kPrimChar:
664 RecordArrayElementsInTransactionImpl(array->AsCharArray(), count);
665 break;
666 case Primitive::kPrimShort:
667 RecordArrayElementsInTransactionImpl(array->AsShortArray(), count);
668 break;
669 case Primitive::kPrimInt:
670 case Primitive::kPrimFloat:
671 RecordArrayElementsInTransactionImpl(array->AsIntArray(), count);
672 break;
673 case Primitive::kPrimLong:
674 case Primitive::kPrimDouble:
675 RecordArrayElementsInTransactionImpl(array->AsLongArray(), count);
676 break;
677 default:
678 LOG(FATAL) << "Unsupported primitive type " << primitive_component_type
679 << " in fill-array-data";
680 break;
681 }
682}
683
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200684static void UnstartedRuntimeInvoke(Thread* self, MethodHelper& mh,
685 const DexFile::CodeItem* code_item, ShadowFrame* shadow_frame,
686 JValue* result, size_t arg_offset) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200687 // In a runtime that's not started we intercept certain methods to avoid complicated dependency
688 // problems in core libraries.
689 std::string name(PrettyMethod(shadow_frame->GetMethod()));
Kenny Rootfa31b3c2013-12-09 13:51:32 -0800690 if (name == "java.lang.Class java.lang.Class.forName(java.lang.String)"
691 || name == "java.lang.Class java.lang.VMClassLoader.loadClass(java.lang.String, boolean)") {
692 // TODO Class#forName should actually call Class::EnsureInitialized always. Support for the
693 // other variants that take more arguments should also be added.
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200694 std::string descriptor(DotToDescriptor(shadow_frame->GetVRegReference(arg_offset)->AsString()->ToModifiedUtf8().c_str()));
Mathieu Chartier590fee92013-09-13 13:46:47 -0700695
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700696 // shadow_frame.GetMethod()->GetDeclaringClass()->GetClassLoader();
Mathieu Chartier0cd81352014-05-22 16:48:55 -0700697 Class* found = Runtime::Current()->GetClassLinker()->FindClass(
698 self, descriptor.c_str(), NullHandle<mirror::ClassLoader>());
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200699 CHECK(found != NULL) << "Class.forName failed in un-started runtime for class: "
700 << PrettyDescriptor(descriptor);
701 result->SetL(found);
Ian Rogersc45b8b52014-05-03 01:39:59 -0700702 } else if (name == "java.lang.Class java.lang.Void.lookupType()") {
703 result->SetL(Runtime::Current()->GetClassLinker()->FindPrimitiveClass('V'));
Kenny Rootfa31b3c2013-12-09 13:51:32 -0800704 } else if (name == "java.lang.Class java.lang.VMClassLoader.findLoadedClass(java.lang.ClassLoader, java.lang.String)") {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700705 StackHandleScope<1> hs(self);
706 Handle<ClassLoader> class_loader(
707 hs.NewHandle(down_cast<mirror::ClassLoader*>(shadow_frame->GetVRegReference(arg_offset))));
Kenny Rootfa31b3c2013-12-09 13:51:32 -0800708 std::string descriptor(DotToDescriptor(shadow_frame->GetVRegReference(arg_offset + 1)->AsString()->ToModifiedUtf8().c_str()));
709
Ian Rogers98379392014-02-24 16:53:16 -0800710 Class* found = Runtime::Current()->GetClassLinker()->FindClass(self, descriptor.c_str(),
Kenny Rootfa31b3c2013-12-09 13:51:32 -0800711 class_loader);
712 result->SetL(found);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200713 } else if (name == "java.lang.Object java.lang.Class.newInstance()") {
714 Class* klass = shadow_frame->GetVRegReference(arg_offset)->AsClass();
715 ArtMethod* c = klass->FindDeclaredDirectMethod("<init>", "()V");
716 CHECK(c != NULL);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700717 StackHandleScope<1> hs(self);
718 Handle<Object> obj(hs.NewHandle(klass->AllocObject(self)));
719 CHECK(obj.Get() != NULL);
720 EnterInterpreterFromInvoke(self, c, obj.Get(), NULL, NULL);
721 result->SetL(obj.Get());
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200722 } else if (name == "java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String)") {
723 // Special managed code cut-out to allow field lookup in a un-started runtime that'd fail
724 // going the reflective Dex way.
725 Class* klass = shadow_frame->GetVRegReference(arg_offset)->AsClass();
726 String* name = shadow_frame->GetVRegReference(arg_offset + 1)->AsString();
727 ArtField* found = NULL;
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200728 ObjectArray<ArtField>* fields = klass->GetIFields();
729 for (int32_t i = 0; i < fields->GetLength() && found == NULL; ++i) {
730 ArtField* f = fields->Get(i);
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700731 if (name->Equals(f->GetName())) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200732 found = f;
733 }
734 }
735 if (found == NULL) {
736 fields = klass->GetSFields();
737 for (int32_t i = 0; i < fields->GetLength() && found == NULL; ++i) {
738 ArtField* f = fields->Get(i);
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700739 if (name->Equals(f->GetName())) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200740 found = f;
741 }
742 }
743 }
744 CHECK(found != NULL)
745 << "Failed to find field in Class.getDeclaredField in un-started runtime. name="
746 << name->ToModifiedUtf8() << " class=" << PrettyDescriptor(klass);
747 // TODO: getDeclaredField calls GetType once the field is found to ensure a
748 // NoClassDefFoundError is thrown if the field's type cannot be resolved.
749 Class* jlr_Field = self->DecodeJObject(WellKnownClasses::java_lang_reflect_Field)->AsClass();
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700750 StackHandleScope<1> hs(self);
751 Handle<Object> field(hs.NewHandle(jlr_Field->AllocNonMovableObject(self)));
752 CHECK(field.Get() != NULL);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200753 ArtMethod* c = jlr_Field->FindDeclaredDirectMethod("<init>", "(Ljava/lang/reflect/ArtField;)V");
754 uint32_t args[1];
Ian Rogersef7d42f2014-01-06 12:55:46 -0800755 args[0] = StackReference<mirror::Object>::FromMirrorPtr(found).AsVRegValue();
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700756 EnterInterpreterFromInvoke(self, c, field.Get(), args, NULL);
757 result->SetL(field.Get());
Ian Rogersc45b8b52014-05-03 01:39:59 -0700758 } else if (name == "int java.lang.Object.hashCode()") {
759 Object* obj = shadow_frame->GetVRegReference(arg_offset);
760 result->SetI(obj->IdentityHashCode());
761 } else if (name == "java.lang.String java.lang.reflect.ArtMethod.getMethodName(java.lang.reflect.ArtMethod)") {
Mathieu Chartierbfd9a432014-05-21 17:43:44 -0700762 StackHandleScope<1> hs(self);
763 MethodHelper mh(hs.NewHandle(shadow_frame->GetVRegReference(arg_offset)->AsArtMethod()));
764 result->SetL(mh.GetNameAsString(self));
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200765 } else if (name == "void java.lang.System.arraycopy(java.lang.Object, int, java.lang.Object, int, int)" ||
766 name == "void java.lang.System.arraycopy(char[], int, char[], int, int)") {
767 // Special case array copying without initializing System.
768 Class* ctype = shadow_frame->GetVRegReference(arg_offset)->GetClass()->GetComponentType();
769 jint srcPos = shadow_frame->GetVReg(arg_offset + 1);
770 jint dstPos = shadow_frame->GetVReg(arg_offset + 3);
771 jint length = shadow_frame->GetVReg(arg_offset + 4);
772 if (!ctype->IsPrimitive()) {
773 ObjectArray<Object>* src = shadow_frame->GetVRegReference(arg_offset)->AsObjectArray<Object>();
774 ObjectArray<Object>* dst = shadow_frame->GetVRegReference(arg_offset + 2)->AsObjectArray<Object>();
775 for (jint i = 0; i < length; ++i) {
776 dst->Set(dstPos + i, src->Get(srcPos + i));
777 }
778 } else if (ctype->IsPrimitiveChar()) {
779 CharArray* src = shadow_frame->GetVRegReference(arg_offset)->AsCharArray();
780 CharArray* dst = shadow_frame->GetVRegReference(arg_offset + 2)->AsCharArray();
781 for (jint i = 0; i < length; ++i) {
782 dst->Set(dstPos + i, src->Get(srcPos + i));
783 }
784 } else if (ctype->IsPrimitiveInt()) {
785 IntArray* src = shadow_frame->GetVRegReference(arg_offset)->AsIntArray();
786 IntArray* dst = shadow_frame->GetVRegReference(arg_offset + 2)->AsIntArray();
787 for (jint i = 0; i < length; ++i) {
788 dst->Set(dstPos + i, src->Get(srcPos + i));
789 }
790 } else {
Ian Rogersc45b8b52014-05-03 01:39:59 -0700791 self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(), "Ljava/lang/InternalError;",
792 "Unimplemented System.arraycopy for type '%s'",
793 PrettyDescriptor(ctype).c_str());
794 }
795 } else if (name == "java.lang.Object java.lang.ThreadLocal.get()") {
796 std::string caller(PrettyMethod(shadow_frame->GetLink()->GetMethod()));
797 if (caller == "java.lang.String java.lang.IntegralToString.convertInt(java.lang.AbstractStringBuilder, int)") {
798 // Allocate non-threadlocal buffer.
799 result->SetL(mirror::CharArray::Alloc(self, 11));
800 } else {
801 self->ThrowNewException(self->GetCurrentLocationForThrow(), "Ljava/lang/InternalError;",
802 "Unimplemented ThreadLocal.get");
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200803 }
804 } else {
805 // Not special, continue with regular interpreter execution.
806 artInterpreterToInterpreterBridge(self, mh, code_item, shadow_frame, result);
807 }
808}
809
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200810// Explicit DoCall template function declarations.
Sebastien Hertzc6714852013-09-30 16:42:32 +0200811#define EXPLICIT_DO_CALL_TEMPLATE_DECL(_is_range, _do_assignability_check) \
812 template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) \
Sebastien Hertz9119c5f2013-12-16 11:31:45 +0100813 bool DoCall<_is_range, _do_assignability_check>(ArtMethod* method, Thread* self, \
814 ShadowFrame& shadow_frame, \
Sebastien Hertzc6714852013-09-30 16:42:32 +0200815 const Instruction* inst, uint16_t inst_data, \
816 JValue* result)
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200817EXPLICIT_DO_CALL_TEMPLATE_DECL(false, false);
818EXPLICIT_DO_CALL_TEMPLATE_DECL(false, true);
819EXPLICIT_DO_CALL_TEMPLATE_DECL(true, false);
820EXPLICIT_DO_CALL_TEMPLATE_DECL(true, true);
821#undef EXPLICIT_DO_CALL_TEMPLATE_DECL
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200822
823// Explicit DoFilledNewArray template function declarations.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100824#define EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL(_is_range_, _check, _transaction_active) \
825 template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) \
826 bool DoFilledNewArray<_is_range_, _check, _transaction_active>(const Instruction* inst, \
827 const ShadowFrame& shadow_frame, \
828 Thread* self, JValue* result)
829#define EXPLICIT_DO_FILLED_NEW_ARRAY_ALL_TEMPLATE_DECL(_transaction_active) \
830 EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL(false, false, _transaction_active); \
831 EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL(false, true, _transaction_active); \
832 EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL(true, false, _transaction_active); \
833 EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL(true, true, _transaction_active)
834EXPLICIT_DO_FILLED_NEW_ARRAY_ALL_TEMPLATE_DECL(false);
835EXPLICIT_DO_FILLED_NEW_ARRAY_ALL_TEMPLATE_DECL(true);
836#undef EXPLICIT_DO_FILLED_NEW_ARRAY_ALL_TEMPLATE_DECL
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200837#undef EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL
838
839} // namespace interpreter
840} // namespace art