interpreter_common.cc revision e94652f1e321b2c8b71acbe5b07d2ebf69fbdb99
1/*
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"
18
19#include "field_helper.h"
20#include "mirror/array-inl.h"
21
22namespace art {
23namespace interpreter {
24
25void ThrowNullPointerExceptionFromInterpreter(const ShadowFrame& shadow_frame) {
26  ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
27}
28
29template<FindFieldType find_type, Primitive::Type field_type, bool do_access_check>
30bool DoFieldGet(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst,
31                uint16_t inst_data) {
32  const bool is_static = (find_type == StaticObjectRead) || (find_type == StaticPrimitiveRead);
33  const uint32_t field_idx = is_static ? inst->VRegB_21c() : inst->VRegC_22c();
34  ArtField* f = FindFieldFromCode<find_type, do_access_check>(field_idx, shadow_frame.GetMethod(), self,
35                                                              Primitive::ComponentSize(field_type));
36  if (UNLIKELY(f == nullptr)) {
37    CHECK(self->IsExceptionPending());
38    return false;
39  }
40  Object* obj;
41  if (is_static) {
42    obj = f->GetDeclaringClass();
43  } else {
44    obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
45    if (UNLIKELY(obj == nullptr)) {
46      ThrowNullPointerExceptionForFieldAccess(shadow_frame.GetCurrentLocationForThrow(), f, true);
47      return false;
48    }
49  }
50  f->GetDeclaringClass()->AssertInitializedOrInitializingInThread(self);
51  // Report this field access to instrumentation if needed.
52  instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
53  if (UNLIKELY(instrumentation->HasFieldReadListeners())) {
54    Object* this_object = f->IsStatic() ? nullptr : obj;
55    instrumentation->FieldReadEvent(self, this_object, shadow_frame.GetMethod(),
56                                    shadow_frame.GetDexPC(), f);
57  }
58  uint32_t vregA = is_static ? inst->VRegA_21c(inst_data) : inst->VRegA_22c(inst_data);
59  switch (field_type) {
60    case Primitive::kPrimBoolean:
61      shadow_frame.SetVReg(vregA, f->GetBoolean(obj));
62      break;
63    case Primitive::kPrimByte:
64      shadow_frame.SetVReg(vregA, f->GetByte(obj));
65      break;
66    case Primitive::kPrimChar:
67      shadow_frame.SetVReg(vregA, f->GetChar(obj));
68      break;
69    case Primitive::kPrimShort:
70      shadow_frame.SetVReg(vregA, f->GetShort(obj));
71      break;
72    case Primitive::kPrimInt:
73      shadow_frame.SetVReg(vregA, f->GetInt(obj));
74      break;
75    case Primitive::kPrimLong:
76      shadow_frame.SetVRegLong(vregA, f->GetLong(obj));
77      break;
78    case Primitive::kPrimNot:
79      shadow_frame.SetVRegReference(vregA, f->GetObject(obj));
80      break;
81    default:
82      LOG(FATAL) << "Unreachable: " << field_type;
83      UNREACHABLE();
84  }
85  return true;
86}
87
88// Explicitly instantiate all DoFieldGet functions.
89#define EXPLICIT_DO_FIELD_GET_TEMPLATE_DECL(_find_type, _field_type, _do_check) \
90  template bool DoFieldGet<_find_type, _field_type, _do_check>(Thread* self, \
91                                                               ShadowFrame& shadow_frame, \
92                                                               const Instruction* inst, \
93                                                               uint16_t inst_data)
94
95#define EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(_find_type, _field_type)  \
96    EXPLICIT_DO_FIELD_GET_TEMPLATE_DECL(_find_type, _field_type, false);  \
97    EXPLICIT_DO_FIELD_GET_TEMPLATE_DECL(_find_type, _field_type, true);
98
99// iget-XXX
100EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(InstancePrimitiveRead, Primitive::kPrimBoolean)
101EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(InstancePrimitiveRead, Primitive::kPrimByte)
102EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(InstancePrimitiveRead, Primitive::kPrimChar)
103EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(InstancePrimitiveRead, Primitive::kPrimShort)
104EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(InstancePrimitiveRead, Primitive::kPrimInt)
105EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(InstancePrimitiveRead, Primitive::kPrimLong)
106EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(InstanceObjectRead, Primitive::kPrimNot)
107
108// sget-XXX
109EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(StaticPrimitiveRead, Primitive::kPrimBoolean)
110EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(StaticPrimitiveRead, Primitive::kPrimByte)
111EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(StaticPrimitiveRead, Primitive::kPrimChar)
112EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(StaticPrimitiveRead, Primitive::kPrimShort)
113EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(StaticPrimitiveRead, Primitive::kPrimInt)
114EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(StaticPrimitiveRead, Primitive::kPrimLong)
115EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL(StaticObjectRead, Primitive::kPrimNot)
116
117#undef EXPLICIT_DO_FIELD_GET_ALL_TEMPLATE_DECL
118#undef EXPLICIT_DO_FIELD_GET_TEMPLATE_DECL
119
120// Handles iget-quick, iget-wide-quick and iget-object-quick instructions.
121// Returns true on success, otherwise throws an exception and returns false.
122template<Primitive::Type field_type>
123bool DoIGetQuick(ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data) {
124  Object* obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
125  if (UNLIKELY(obj == nullptr)) {
126    // We lost the reference to the field index so we cannot get a more
127    // precised exception message.
128    ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
129    return false;
130  }
131  MemberOffset field_offset(inst->VRegC_22c());
132  // Report this field access to instrumentation if needed. Since we only have the offset of
133  // the field from the base of the object, we need to look for it first.
134  instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
135  if (UNLIKELY(instrumentation->HasFieldReadListeners())) {
136    ArtField* f = ArtField::FindInstanceFieldWithOffset(obj->GetClass(),
137                                                        field_offset.Uint32Value());
138    DCHECK(f != nullptr);
139    DCHECK(!f->IsStatic());
140    instrumentation->FieldReadEvent(Thread::Current(), obj, shadow_frame.GetMethod(),
141                                    shadow_frame.GetDexPC(), f);
142  }
143  // Note: iget-x-quick instructions are only for non-volatile fields.
144  const uint32_t vregA = inst->VRegA_22c(inst_data);
145  switch (field_type) {
146    case Primitive::kPrimInt:
147      shadow_frame.SetVReg(vregA, static_cast<int32_t>(obj->GetField32(field_offset)));
148      break;
149    case Primitive::kPrimLong:
150      shadow_frame.SetVRegLong(vregA, static_cast<int64_t>(obj->GetField64(field_offset)));
151      break;
152    case Primitive::kPrimNot:
153      shadow_frame.SetVRegReference(vregA, obj->GetFieldObject<mirror::Object>(field_offset));
154      break;
155    default:
156      LOG(FATAL) << "Unreachable: " << field_type;
157      UNREACHABLE();
158  }
159  return true;
160}
161
162// Explicitly instantiate all DoIGetQuick functions.
163#define EXPLICIT_DO_IGET_QUICK_TEMPLATE_DECL(_field_type) \
164  template bool DoIGetQuick<_field_type>(ShadowFrame& shadow_frame, const Instruction* inst, \
165                                         uint16_t inst_data)
166
167EXPLICIT_DO_IGET_QUICK_TEMPLATE_DECL(Primitive::kPrimInt);    // iget-quick.
168EXPLICIT_DO_IGET_QUICK_TEMPLATE_DECL(Primitive::kPrimLong);   // iget-wide-quick.
169EXPLICIT_DO_IGET_QUICK_TEMPLATE_DECL(Primitive::kPrimNot);    // iget-object-quick.
170#undef EXPLICIT_DO_IGET_QUICK_TEMPLATE_DECL
171
172template<Primitive::Type field_type>
173static JValue GetFieldValue(const ShadowFrame& shadow_frame, uint32_t vreg)
174    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
175  JValue field_value;
176  switch (field_type) {
177    case Primitive::kPrimBoolean:
178      field_value.SetZ(static_cast<uint8_t>(shadow_frame.GetVReg(vreg)));
179      break;
180    case Primitive::kPrimByte:
181      field_value.SetB(static_cast<int8_t>(shadow_frame.GetVReg(vreg)));
182      break;
183    case Primitive::kPrimChar:
184      field_value.SetC(static_cast<uint16_t>(shadow_frame.GetVReg(vreg)));
185      break;
186    case Primitive::kPrimShort:
187      field_value.SetS(static_cast<int16_t>(shadow_frame.GetVReg(vreg)));
188      break;
189    case Primitive::kPrimInt:
190      field_value.SetI(shadow_frame.GetVReg(vreg));
191      break;
192    case Primitive::kPrimLong:
193      field_value.SetJ(shadow_frame.GetVRegLong(vreg));
194      break;
195    case Primitive::kPrimNot:
196      field_value.SetL(shadow_frame.GetVRegReference(vreg));
197      break;
198    default:
199      LOG(FATAL) << "Unreachable: " << field_type;
200      UNREACHABLE();
201  }
202  return field_value;
203}
204
205template<FindFieldType find_type, Primitive::Type field_type, bool do_access_check,
206         bool transaction_active>
207bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame, const Instruction* inst,
208                uint16_t inst_data) {
209  bool do_assignability_check = do_access_check;
210  bool is_static = (find_type == StaticObjectWrite) || (find_type == StaticPrimitiveWrite);
211  uint32_t field_idx = is_static ? inst->VRegB_21c() : inst->VRegC_22c();
212  ArtField* f = FindFieldFromCode<find_type, do_access_check>(field_idx, shadow_frame.GetMethod(), self,
213                                                              Primitive::ComponentSize(field_type));
214  if (UNLIKELY(f == nullptr)) {
215    CHECK(self->IsExceptionPending());
216    return false;
217  }
218  Object* obj;
219  if (is_static) {
220    obj = f->GetDeclaringClass();
221  } else {
222    obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
223    if (UNLIKELY(obj == nullptr)) {
224      ThrowNullPointerExceptionForFieldAccess(shadow_frame.GetCurrentLocationForThrow(),
225                                              f, false);
226      return false;
227    }
228  }
229  f->GetDeclaringClass()->AssertInitializedOrInitializingInThread(self);
230  uint32_t vregA = is_static ? inst->VRegA_21c(inst_data) : inst->VRegA_22c(inst_data);
231  // Report this field access to instrumentation if needed. Since we only have the offset of
232  // the field from the base of the object, we need to look for it first.
233  instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
234  if (UNLIKELY(instrumentation->HasFieldWriteListeners())) {
235    JValue field_value = GetFieldValue<field_type>(shadow_frame, vregA);
236    Object* this_object = f->IsStatic() ? nullptr : obj;
237    instrumentation->FieldWriteEvent(self, this_object, shadow_frame.GetMethod(),
238                                     shadow_frame.GetDexPC(), f, field_value);
239  }
240  switch (field_type) {
241    case Primitive::kPrimBoolean:
242      f->SetBoolean<transaction_active>(obj, shadow_frame.GetVReg(vregA));
243      break;
244    case Primitive::kPrimByte:
245      f->SetByte<transaction_active>(obj, shadow_frame.GetVReg(vregA));
246      break;
247    case Primitive::kPrimChar:
248      f->SetChar<transaction_active>(obj, shadow_frame.GetVReg(vregA));
249      break;
250    case Primitive::kPrimShort:
251      f->SetShort<transaction_active>(obj, shadow_frame.GetVReg(vregA));
252      break;
253    case Primitive::kPrimInt:
254      f->SetInt<transaction_active>(obj, shadow_frame.GetVReg(vregA));
255      break;
256    case Primitive::kPrimLong:
257      f->SetLong<transaction_active>(obj, shadow_frame.GetVRegLong(vregA));
258      break;
259    case Primitive::kPrimNot: {
260      Object* reg = shadow_frame.GetVRegReference(vregA);
261      if (do_assignability_check && reg != nullptr) {
262        // FieldHelper::GetType can resolve classes, use a handle wrapper which will restore the
263        // object in the destructor.
264        Class* field_class;
265        {
266          StackHandleScope<3> hs(self);
267          HandleWrapper<mirror::ArtField> h_f(hs.NewHandleWrapper(&f));
268          HandleWrapper<mirror::Object> h_reg(hs.NewHandleWrapper(&reg));
269          HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(&obj));
270          FieldHelper fh(h_f);
271          field_class = fh.GetType();
272        }
273        if (!reg->VerifierInstanceOf(field_class)) {
274          // This should never happen.
275          std::string temp1, temp2, temp3;
276          self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
277                                   "Ljava/lang/VirtualMachineError;",
278                                   "Put '%s' that is not instance of field '%s' in '%s'",
279                                   reg->GetClass()->GetDescriptor(&temp1),
280                                   field_class->GetDescriptor(&temp2),
281                                   f->GetDeclaringClass()->GetDescriptor(&temp3));
282          return false;
283        }
284      }
285      f->SetObj<transaction_active>(obj, reg);
286      break;
287    }
288    default:
289      LOG(FATAL) << "Unreachable: " << field_type;
290      UNREACHABLE();
291  }
292  return true;
293}
294
295// Explicitly instantiate all DoFieldPut functions.
296#define EXPLICIT_DO_FIELD_PUT_TEMPLATE_DECL(_find_type, _field_type, _do_check, _transaction_active) \
297  template bool DoFieldPut<_find_type, _field_type, _do_check, _transaction_active>(Thread* self, \
298      const ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data)
299
300#define EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(_find_type, _field_type)  \
301    EXPLICIT_DO_FIELD_PUT_TEMPLATE_DECL(_find_type, _field_type, false, false);  \
302    EXPLICIT_DO_FIELD_PUT_TEMPLATE_DECL(_find_type, _field_type, true, false);  \
303    EXPLICIT_DO_FIELD_PUT_TEMPLATE_DECL(_find_type, _field_type, false, true);  \
304    EXPLICIT_DO_FIELD_PUT_TEMPLATE_DECL(_find_type, _field_type, true, true);
305
306// iput-XXX
307EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(InstancePrimitiveWrite, Primitive::kPrimBoolean)
308EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(InstancePrimitiveWrite, Primitive::kPrimByte)
309EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(InstancePrimitiveWrite, Primitive::kPrimChar)
310EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(InstancePrimitiveWrite, Primitive::kPrimShort)
311EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(InstancePrimitiveWrite, Primitive::kPrimInt)
312EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(InstancePrimitiveWrite, Primitive::kPrimLong)
313EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(InstanceObjectWrite, Primitive::kPrimNot)
314
315// sput-XXX
316EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(StaticPrimitiveWrite, Primitive::kPrimBoolean)
317EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(StaticPrimitiveWrite, Primitive::kPrimByte)
318EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(StaticPrimitiveWrite, Primitive::kPrimChar)
319EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(StaticPrimitiveWrite, Primitive::kPrimShort)
320EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(StaticPrimitiveWrite, Primitive::kPrimInt)
321EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(StaticPrimitiveWrite, Primitive::kPrimLong)
322EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL(StaticObjectWrite, Primitive::kPrimNot)
323
324#undef EXPLICIT_DO_FIELD_PUT_ALL_TEMPLATE_DECL
325#undef EXPLICIT_DO_FIELD_PUT_TEMPLATE_DECL
326
327template<Primitive::Type field_type, bool transaction_active>
328bool DoIPutQuick(const ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data) {
329  Object* obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
330  if (UNLIKELY(obj == nullptr)) {
331    // We lost the reference to the field index so we cannot get a more
332    // precised exception message.
333    ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
334    return false;
335  }
336  MemberOffset field_offset(inst->VRegC_22c());
337  const uint32_t vregA = inst->VRegA_22c(inst_data);
338  // Report this field modification to instrumentation if needed. Since we only have the offset of
339  // the field from the base of the object, we need to look for it first.
340  instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
341  if (UNLIKELY(instrumentation->HasFieldWriteListeners())) {
342    ArtField* f = ArtField::FindInstanceFieldWithOffset(obj->GetClass(),
343                                                        field_offset.Uint32Value());
344    DCHECK(f != nullptr);
345    DCHECK(!f->IsStatic());
346    JValue field_value = GetFieldValue<field_type>(shadow_frame, vregA);
347    instrumentation->FieldWriteEvent(Thread::Current(), obj, shadow_frame.GetMethod(),
348                                     shadow_frame.GetDexPC(), f, field_value);
349  }
350  // Note: iput-x-quick instructions are only for non-volatile fields.
351  switch (field_type) {
352    case Primitive::kPrimBoolean:
353      obj->SetFieldBoolean<transaction_active>(field_offset, shadow_frame.GetVReg(vregA));
354      break;
355    case Primitive::kPrimByte:
356      obj->SetFieldByte<transaction_active>(field_offset, shadow_frame.GetVReg(vregA));
357      break;
358    case Primitive::kPrimChar:
359      obj->SetFieldChar<transaction_active>(field_offset, shadow_frame.GetVReg(vregA));
360      break;
361    case Primitive::kPrimShort:
362      obj->SetFieldShort<transaction_active>(field_offset, shadow_frame.GetVReg(vregA));
363      break;
364    case Primitive::kPrimInt:
365      obj->SetField32<transaction_active>(field_offset, shadow_frame.GetVReg(vregA));
366      break;
367    case Primitive::kPrimLong:
368      obj->SetField64<transaction_active>(field_offset, shadow_frame.GetVRegLong(vregA));
369      break;
370    case Primitive::kPrimNot:
371      obj->SetFieldObject<transaction_active>(field_offset, shadow_frame.GetVRegReference(vregA));
372      break;
373    default:
374      LOG(FATAL) << "Unreachable: " << field_type;
375      UNREACHABLE();
376  }
377  return true;
378}
379
380// Explicitly instantiate all DoIPutQuick functions.
381#define EXPLICIT_DO_IPUT_QUICK_TEMPLATE_DECL(_field_type, _transaction_active) \
382  template bool DoIPutQuick<_field_type, _transaction_active>(const ShadowFrame& shadow_frame, \
383                                                              const Instruction* inst, \
384                                                              uint16_t inst_data)
385
386#define EXPLICIT_DO_IPUT_QUICK_ALL_TEMPLATE_DECL(_field_type)   \
387  EXPLICIT_DO_IPUT_QUICK_TEMPLATE_DECL(_field_type, false);     \
388  EXPLICIT_DO_IPUT_QUICK_TEMPLATE_DECL(_field_type, true);
389
390EXPLICIT_DO_IPUT_QUICK_ALL_TEMPLATE_DECL(Primitive::kPrimInt)      // iput-quick.
391EXPLICIT_DO_IPUT_QUICK_ALL_TEMPLATE_DECL(Primitive::kPrimBoolean)  // iput-boolean-quick.
392EXPLICIT_DO_IPUT_QUICK_ALL_TEMPLATE_DECL(Primitive::kPrimByte)     // iput-byte-quick.
393EXPLICIT_DO_IPUT_QUICK_ALL_TEMPLATE_DECL(Primitive::kPrimChar)     // iput-char-quick.
394EXPLICIT_DO_IPUT_QUICK_ALL_TEMPLATE_DECL(Primitive::kPrimShort)    // iput-short-quick.
395EXPLICIT_DO_IPUT_QUICK_ALL_TEMPLATE_DECL(Primitive::kPrimLong)     // iput-wide-quick.
396EXPLICIT_DO_IPUT_QUICK_ALL_TEMPLATE_DECL(Primitive::kPrimNot)      // iput-object-quick.
397#undef EXPLICIT_DO_IPUT_QUICK_ALL_TEMPLATE_DECL
398#undef EXPLICIT_DO_IPUT_QUICK_TEMPLATE_DECL
399
400/**
401 * Finds the location where this exception will be caught. We search until we reach either the top
402 * frame or a native frame, in which cases this exception is considered uncaught.
403 */
404class CatchLocationFinder : public StackVisitor {
405 public:
406  explicit CatchLocationFinder(Thread* self, Handle<mirror::Throwable>* exception)
407      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
408    : StackVisitor(self, nullptr), self_(self), handle_scope_(self), exception_(exception),
409      catch_method_(handle_scope_.NewHandle<mirror::ArtMethod>(nullptr)),
410      catch_dex_pc_(DexFile::kDexNoIndex), clear_exception_(false) {
411  }
412
413  bool VisitFrame() OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
414    mirror::ArtMethod* method = GetMethod();
415    if (method == nullptr) {
416      return true;
417    }
418    if (method->IsRuntimeMethod()) {
419      // Ignore callee save method.
420      DCHECK(method->IsCalleeSaveMethod());
421      return true;
422    }
423    if (method->IsNative()) {
424      return false;  // End stack walk.
425    }
426    DCHECK(!method->IsNative());
427    uint32_t dex_pc = GetDexPc();
428    if (dex_pc != DexFile::kDexNoIndex) {
429      uint32_t found_dex_pc;
430      {
431        StackHandleScope<3> hs(self_);
432        Handle<mirror::Class> exception_class(hs.NewHandle((*exception_)->GetClass()));
433        Handle<mirror::ArtMethod> h_method(hs.NewHandle(method));
434        found_dex_pc = mirror::ArtMethod::FindCatchBlock(h_method, exception_class, dex_pc,
435                                                         &clear_exception_);
436      }
437      if (found_dex_pc != DexFile::kDexNoIndex) {
438        catch_method_.Assign(method);
439        catch_dex_pc_ = found_dex_pc;
440        return false;  // End stack walk.
441      }
442    }
443    return true;  // Continue stack walk.
444  }
445
446  ArtMethod* GetCatchMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
447    return catch_method_.Get();
448  }
449
450  uint32_t GetCatchDexPc() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
451    return catch_dex_pc_;
452  }
453
454  bool NeedClearException() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
455    return clear_exception_;
456  }
457
458 private:
459  Thread* const self_;
460  StackHandleScope<1> handle_scope_;
461  Handle<mirror::Throwable>* exception_;
462  MutableHandle<mirror::ArtMethod> catch_method_;
463  uint32_t catch_dex_pc_;
464  bool clear_exception_;
465
466
467  DISALLOW_COPY_AND_ASSIGN(CatchLocationFinder);
468};
469
470uint32_t FindNextInstructionFollowingException(Thread* self,
471                                               ShadowFrame& shadow_frame,
472                                               uint32_t dex_pc,
473                                               const instrumentation::Instrumentation* instrumentation) {
474  self->VerifyStack();
475  ThrowLocation throw_location;
476  StackHandleScope<3> hs(self);
477  Handle<mirror::Throwable> exception(hs.NewHandle(self->GetException(&throw_location)));
478  if (!self->IsExceptionReportedToInstrumentation() && instrumentation->HasExceptionCaughtListeners()) {
479    CatchLocationFinder clf(self, &exception);
480    clf.WalkStack(false);
481    instrumentation->ExceptionCaughtEvent(self, throw_location, clf.GetCatchMethod(),
482                                          clf.GetCatchDexPc(), exception.Get());
483    self->SetExceptionReportedToInstrumentation(true);
484  }
485  bool clear_exception = false;
486  uint32_t found_dex_pc;
487  {
488    Handle<mirror::Class> exception_class(hs.NewHandle(exception->GetClass()));
489    Handle<mirror::ArtMethod> h_method(hs.NewHandle(shadow_frame.GetMethod()));
490    found_dex_pc = mirror::ArtMethod::FindCatchBlock(h_method, exception_class, dex_pc,
491                                                     &clear_exception);
492  }
493  if (found_dex_pc == DexFile::kDexNoIndex) {
494    instrumentation->MethodUnwindEvent(self, shadow_frame.GetThisObject(),
495                                       shadow_frame.GetMethod(), dex_pc);
496  } else {
497    if (self->IsExceptionReportedToInstrumentation()) {
498      instrumentation->MethodUnwindEvent(self, shadow_frame.GetThisObject(),
499                                         shadow_frame.GetMethod(), dex_pc);
500    }
501    if (clear_exception) {
502      self->ClearException();
503    }
504  }
505  return found_dex_pc;
506}
507
508void UnexpectedOpcode(const Instruction* inst, const ShadowFrame& shadow_frame) {
509  LOG(FATAL) << "Unexpected instruction: "
510             << inst->DumpString(shadow_frame.GetMethod()->GetDexFile());
511  UNREACHABLE();
512}
513
514static void UnstartedRuntimeInvoke(Thread* self, const DexFile::CodeItem* code_item,
515                                   ShadowFrame* shadow_frame, JValue* result, size_t arg_offset)
516    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
517
518// Assign register 'src_reg' from shadow_frame to register 'dest_reg' into new_shadow_frame.
519static inline void AssignRegister(ShadowFrame* new_shadow_frame, const ShadowFrame& shadow_frame,
520                                  size_t dest_reg, size_t src_reg)
521    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
522  // If both register locations contains the same value, the register probably holds a reference.
523  // Uint required, so that sign extension does not make this wrong on 64b systems
524  uint32_t src_value = shadow_frame.GetVReg(src_reg);
525  mirror::Object* o = shadow_frame.GetVRegReference<kVerifyNone>(src_reg);
526  if (src_value == reinterpret_cast<uintptr_t>(o)) {
527    new_shadow_frame->SetVRegReference(dest_reg, o);
528  } else {
529    new_shadow_frame->SetVReg(dest_reg, src_value);
530  }
531}
532
533void AbortTransaction(Thread* self, const char* fmt, ...) {
534  CHECK(Runtime::Current()->IsActiveTransaction());
535  // Throw an exception so we can abort the transaction and undo every change.
536  va_list args;
537  va_start(args, fmt);
538  self->ThrowNewExceptionV(self->GetCurrentLocationForThrow(), "Ljava/lang/InternalError;", fmt,
539                           args);
540  va_end(args);
541}
542
543static mirror::Class* GetClassFromTypeIdx(mirror::ArtMethod* method, uint16_t type_idx)
544    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
545  mirror::Class* type = method->GetDexCacheResolvedType(type_idx);
546  if (type == nullptr) {
547    type = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
548    CHECK(type != nullptr || Thread::Current()->IsExceptionPending());
549  }
550  return type;
551}
552
553template<bool is_range, bool do_assignability_check>
554bool DoCall(ArtMethod* called_method, Thread* self, ShadowFrame& shadow_frame,
555            const Instruction* inst, uint16_t inst_data, JValue* result) {
556  // Compute method information.
557  const DexFile::CodeItem* code_item = called_method->GetCodeItem();
558  const uint16_t num_ins = (is_range) ? inst->VRegA_3rc(inst_data) : inst->VRegA_35c(inst_data);
559  uint16_t num_regs;
560  if (LIKELY(code_item != NULL)) {
561    num_regs = code_item->registers_size_;
562    DCHECK_EQ(num_ins, code_item->ins_size_);
563  } else {
564    DCHECK(called_method->IsNative() || called_method->IsProxyMethod());
565    num_regs = num_ins;
566  }
567
568  // Allocate shadow frame on the stack.
569  const char* old_cause = self->StartAssertNoThreadSuspension("DoCall");
570  void* memory = alloca(ShadowFrame::ComputeSize(num_regs));
571  ShadowFrame* new_shadow_frame(ShadowFrame::Create(num_regs, &shadow_frame, called_method, 0,
572                                                    memory));
573
574  // Initialize new shadow frame.
575  const size_t first_dest_reg = num_regs - num_ins;
576  if (do_assignability_check) {
577    // Slow path.
578    // We might need to do class loading, which incurs a thread state change to kNative. So
579    // register the shadow frame as under construction and allow suspension again.
580    self->SetShadowFrameUnderConstruction(new_shadow_frame);
581    self->EndAssertNoThreadSuspension(old_cause);
582
583    // We need to do runtime check on reference assignment. We need to load the shorty
584    // to get the exact type of each reference argument.
585    const DexFile::TypeList* params = new_shadow_frame->GetMethod()->GetParameterTypeList();
586    uint32_t shorty_len = 0;
587    const char* shorty = new_shadow_frame->GetMethod()->GetShorty(&shorty_len);
588
589    // TODO: find a cleaner way to separate non-range and range information without duplicating
590    //       code.
591    uint32_t arg[5];  // only used in invoke-XXX.
592    uint32_t vregC;   // only used in invoke-XXX-range.
593    if (is_range) {
594      vregC = inst->VRegC_3rc();
595    } else {
596      inst->GetVarArgs(arg, inst_data);
597    }
598
599    // Handle receiver apart since it's not part of the shorty.
600    size_t dest_reg = first_dest_reg;
601    size_t arg_offset = 0;
602    if (!new_shadow_frame->GetMethod()->IsStatic()) {
603      size_t receiver_reg = is_range ? vregC : arg[0];
604      new_shadow_frame->SetVRegReference(dest_reg, shadow_frame.GetVRegReference(receiver_reg));
605      ++dest_reg;
606      ++arg_offset;
607    }
608    for (uint32_t shorty_pos = 0; dest_reg < num_regs; ++shorty_pos, ++dest_reg, ++arg_offset) {
609      DCHECK_LT(shorty_pos + 1, shorty_len);
610      const size_t src_reg = (is_range) ? vregC + arg_offset : arg[arg_offset];
611      switch (shorty[shorty_pos + 1]) {
612        case 'L': {
613          Object* o = shadow_frame.GetVRegReference(src_reg);
614          if (do_assignability_check && o != NULL) {
615            Class* arg_type = GetClassFromTypeIdx(new_shadow_frame->GetMethod(),
616                                                  params->GetTypeItem(shorty_pos).type_idx_);
617            if (arg_type == NULL) {
618              CHECK(self->IsExceptionPending());
619              return false;
620            }
621            if (!o->VerifierInstanceOf(arg_type)) {
622              // This should never happen.
623              std::string temp1, temp2;
624              self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
625                                       "Ljava/lang/VirtualMachineError;",
626                                       "Invoking %s with bad arg %d, type '%s' not instance of '%s'",
627                                       new_shadow_frame->GetMethod()->GetName(), shorty_pos,
628                                       o->GetClass()->GetDescriptor(&temp1),
629                                       arg_type->GetDescriptor(&temp2));
630              return false;
631            }
632          }
633          new_shadow_frame->SetVRegReference(dest_reg, o);
634          break;
635        }
636        case 'J': case 'D': {
637          uint64_t wide_value = (static_cast<uint64_t>(shadow_frame.GetVReg(src_reg + 1)) << 32) |
638                                static_cast<uint32_t>(shadow_frame.GetVReg(src_reg));
639          new_shadow_frame->SetVRegLong(dest_reg, wide_value);
640          ++dest_reg;
641          ++arg_offset;
642          break;
643        }
644        default:
645          new_shadow_frame->SetVReg(dest_reg, shadow_frame.GetVReg(src_reg));
646          break;
647      }
648    }
649    // We're done with the construction.
650    self->ClearShadowFrameUnderConstruction();
651  } else {
652    // Fast path: no extra checks.
653    if (is_range) {
654      const uint16_t first_src_reg = inst->VRegC_3rc();
655      for (size_t src_reg = first_src_reg, dest_reg = first_dest_reg; dest_reg < num_regs;
656          ++dest_reg, ++src_reg) {
657        AssignRegister(new_shadow_frame, shadow_frame, dest_reg, src_reg);
658      }
659    } else {
660      DCHECK_LE(num_ins, 5U);
661      uint16_t regList = inst->Fetch16(2);
662      uint16_t count = num_ins;
663      if (count == 5) {
664        AssignRegister(new_shadow_frame, shadow_frame, first_dest_reg + 4U,
665                       (inst_data >> 8) & 0x0f);
666        --count;
667       }
668      for (size_t arg_index = 0; arg_index < count; ++arg_index, regList >>= 4) {
669        AssignRegister(new_shadow_frame, shadow_frame, first_dest_reg + arg_index, regList & 0x0f);
670      }
671    }
672    self->EndAssertNoThreadSuspension(old_cause);
673  }
674
675  // Do the call now.
676  if (LIKELY(Runtime::Current()->IsStarted())) {
677    if (kIsDebugBuild && new_shadow_frame->GetMethod()->GetEntryPointFromInterpreter() == nullptr) {
678      LOG(FATAL) << "Attempt to invoke non-executable method: "
679          << PrettyMethod(new_shadow_frame->GetMethod());
680      UNREACHABLE();
681    }
682    if (kIsDebugBuild && Runtime::Current()->GetInstrumentation()->IsForcedInterpretOnly() &&
683        !new_shadow_frame->GetMethod()->IsNative() &&
684        !new_shadow_frame->GetMethod()->IsProxyMethod() &&
685        new_shadow_frame->GetMethod()->GetEntryPointFromInterpreter()
686            == artInterpreterToCompiledCodeBridge) {
687      LOG(FATAL) << "Attempt to call compiled code when -Xint: "
688          << PrettyMethod(new_shadow_frame->GetMethod());
689      UNREACHABLE();
690    }
691    (new_shadow_frame->GetMethod()->GetEntryPointFromInterpreter())(self, code_item,
692                                                                    new_shadow_frame, result);
693  } else {
694    UnstartedRuntimeInvoke(self, code_item, new_shadow_frame, result, first_dest_reg);
695  }
696  return !self->IsExceptionPending();
697}
698
699template <bool is_range, bool do_access_check, bool transaction_active>
700bool DoFilledNewArray(const Instruction* inst, const ShadowFrame& shadow_frame,
701                      Thread* self, JValue* result) {
702  DCHECK(inst->Opcode() == Instruction::FILLED_NEW_ARRAY ||
703         inst->Opcode() == Instruction::FILLED_NEW_ARRAY_RANGE);
704  const int32_t length = is_range ? inst->VRegA_3rc() : inst->VRegA_35c();
705  if (!is_range) {
706    // Checks FILLED_NEW_ARRAY's length does not exceed 5 arguments.
707    CHECK_LE(length, 5);
708  }
709  if (UNLIKELY(length < 0)) {
710    ThrowNegativeArraySizeException(length);
711    return false;
712  }
713  uint16_t type_idx = is_range ? inst->VRegB_3rc() : inst->VRegB_35c();
714  Class* arrayClass = ResolveVerifyAndClinit(type_idx, shadow_frame.GetMethod(),
715                                             self, false, do_access_check);
716  if (UNLIKELY(arrayClass == NULL)) {
717    DCHECK(self->IsExceptionPending());
718    return false;
719  }
720  CHECK(arrayClass->IsArrayClass());
721  Class* componentClass = arrayClass->GetComponentType();
722  if (UNLIKELY(componentClass->IsPrimitive() && !componentClass->IsPrimitiveInt())) {
723    if (componentClass->IsPrimitiveLong() || componentClass->IsPrimitiveDouble()) {
724      ThrowRuntimeException("Bad filled array request for type %s",
725                            PrettyDescriptor(componentClass).c_str());
726    } else {
727      self->ThrowNewExceptionF(shadow_frame.GetCurrentLocationForThrow(),
728                               "Ljava/lang/InternalError;",
729                               "Found type %s; filled-new-array not implemented for anything but 'int'",
730                               PrettyDescriptor(componentClass).c_str());
731    }
732    return false;
733  }
734  Object* newArray = Array::Alloc<true>(self, arrayClass, length,
735                                        arrayClass->GetComponentSizeShift(),
736                                        Runtime::Current()->GetHeap()->GetCurrentAllocator());
737  if (UNLIKELY(newArray == NULL)) {
738    DCHECK(self->IsExceptionPending());
739    return false;
740  }
741  uint32_t arg[5];  // only used in filled-new-array.
742  uint32_t vregC;   // only used in filled-new-array-range.
743  if (is_range) {
744    vregC = inst->VRegC_3rc();
745  } else {
746    inst->GetVarArgs(arg);
747  }
748  const bool is_primitive_int_component = componentClass->IsPrimitiveInt();
749  for (int32_t i = 0; i < length; ++i) {
750    size_t src_reg = is_range ? vregC + i : arg[i];
751    if (is_primitive_int_component) {
752      newArray->AsIntArray()->SetWithoutChecks<transaction_active>(i, shadow_frame.GetVReg(src_reg));
753    } else {
754      newArray->AsObjectArray<Object>()->SetWithoutChecks<transaction_active>(i, shadow_frame.GetVRegReference(src_reg));
755    }
756  }
757
758  result->SetL(newArray);
759  return true;
760}
761
762// TODO fix thread analysis: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_).
763template<typename T>
764static void RecordArrayElementsInTransactionImpl(mirror::PrimitiveArray<T>* array, int32_t count)
765    NO_THREAD_SAFETY_ANALYSIS {
766  Runtime* runtime = Runtime::Current();
767  for (int32_t i = 0; i < count; ++i) {
768    runtime->RecordWriteArray(array, i, array->GetWithoutChecks(i));
769  }
770}
771
772void RecordArrayElementsInTransaction(mirror::Array* array, int32_t count)
773    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
774  DCHECK(Runtime::Current()->IsActiveTransaction());
775  DCHECK(array != nullptr);
776  DCHECK_LE(count, array->GetLength());
777  Primitive::Type primitive_component_type = array->GetClass()->GetComponentType()->GetPrimitiveType();
778  switch (primitive_component_type) {
779    case Primitive::kPrimBoolean:
780      RecordArrayElementsInTransactionImpl(array->AsBooleanArray(), count);
781      break;
782    case Primitive::kPrimByte:
783      RecordArrayElementsInTransactionImpl(array->AsByteArray(), count);
784      break;
785    case Primitive::kPrimChar:
786      RecordArrayElementsInTransactionImpl(array->AsCharArray(), count);
787      break;
788    case Primitive::kPrimShort:
789      RecordArrayElementsInTransactionImpl(array->AsShortArray(), count);
790      break;
791    case Primitive::kPrimInt:
792    case Primitive::kPrimFloat:
793      RecordArrayElementsInTransactionImpl(array->AsIntArray(), count);
794      break;
795    case Primitive::kPrimLong:
796    case Primitive::kPrimDouble:
797      RecordArrayElementsInTransactionImpl(array->AsLongArray(), count);
798      break;
799    default:
800      LOG(FATAL) << "Unsupported primitive type " << primitive_component_type
801                 << " in fill-array-data";
802      break;
803  }
804}
805
806// Helper function to deal with class loading in an unstarted runtime.
807static void UnstartedRuntimeFindClass(Thread* self, Handle<mirror::String> className,
808                                      Handle<mirror::ClassLoader> class_loader, JValue* result,
809                                      const std::string& method_name, bool initialize_class,
810                                      bool abort_if_not_found)
811    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
812  CHECK(className.Get() != nullptr);
813  std::string descriptor(DotToDescriptor(className->ToModifiedUtf8().c_str()));
814  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
815
816  Class* found = class_linker->FindClass(self, descriptor.c_str(), class_loader);
817  if (found == nullptr && abort_if_not_found) {
818    if (!self->IsExceptionPending()) {
819      AbortTransaction(self, "%s failed in un-started runtime for class: %s",
820                       method_name.c_str(), PrettyDescriptor(descriptor.c_str()).c_str());
821    }
822    return;
823  }
824  if (found != nullptr && initialize_class) {
825    StackHandleScope<1> hs(self);
826    Handle<mirror::Class> h_class(hs.NewHandle(found));
827    if (!class_linker->EnsureInitialized(self, h_class, true, true)) {
828      CHECK(self->IsExceptionPending());
829      return;
830    }
831  }
832  result->SetL(found);
833}
834
835static void UnstartedRuntimeInvoke(Thread* self,  const DexFile::CodeItem* code_item,
836                                   ShadowFrame* shadow_frame,
837                                   JValue* result, size_t arg_offset) {
838  // In a runtime that's not started we intercept certain methods to avoid complicated dependency
839  // problems in core libraries.
840  std::string name(PrettyMethod(shadow_frame->GetMethod()));
841  if (name == "java.lang.Class java.lang.Class.forName(java.lang.String)") {
842    // TODO: Support for the other variants that take more arguments should also be added.
843    mirror::String* class_name = shadow_frame->GetVRegReference(arg_offset)->AsString();
844    StackHandleScope<1> hs(self);
845    Handle<mirror::String> h_class_name(hs.NewHandle(class_name));
846    UnstartedRuntimeFindClass(self, h_class_name, NullHandle<mirror::ClassLoader>(), result, name,
847                              true, true);
848  } else if (name == "java.lang.Class java.lang.VMClassLoader.loadClass(java.lang.String, boolean)") {
849    mirror::String* class_name = shadow_frame->GetVRegReference(arg_offset)->AsString();
850    StackHandleScope<1> hs(self);
851    Handle<mirror::String> h_class_name(hs.NewHandle(class_name));
852    UnstartedRuntimeFindClass(self, h_class_name, NullHandle<mirror::ClassLoader>(), result, name,
853                              false, true);
854  } else if (name == "java.lang.Class java.lang.VMClassLoader.findLoadedClass(java.lang.ClassLoader, java.lang.String)") {
855    mirror::String* class_name = shadow_frame->GetVRegReference(arg_offset + 1)->AsString();
856    mirror::ClassLoader* class_loader =
857        down_cast<mirror::ClassLoader*>(shadow_frame->GetVRegReference(arg_offset));
858    StackHandleScope<2> hs(self);
859    Handle<mirror::String> h_class_name(hs.NewHandle(class_name));
860    Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(class_loader));
861    UnstartedRuntimeFindClass(self, h_class_name, h_class_loader, result, name, false, false);
862  } else if (name == "java.lang.Class java.lang.Void.lookupType()") {
863    result->SetL(Runtime::Current()->GetClassLinker()->FindPrimitiveClass('V'));
864  } else if (name == "java.lang.Object java.lang.Class.newInstance()") {
865    Class* klass = shadow_frame->GetVRegReference(arg_offset)->AsClass();
866    ArtMethod* c = klass->FindDeclaredDirectMethod("<init>", "()V");
867    CHECK(c != NULL);
868    StackHandleScope<1> hs(self);
869    Handle<Object> obj(hs.NewHandle(klass->AllocObject(self)));
870    CHECK(obj.Get() != NULL);
871    EnterInterpreterFromInvoke(self, c, obj.Get(), NULL, NULL);
872    result->SetL(obj.Get());
873  } else if (name == "java.lang.reflect.Field java.lang.Class.getDeclaredField(java.lang.String)") {
874    // Special managed code cut-out to allow field lookup in a un-started runtime that'd fail
875    // going the reflective Dex way.
876    Class* klass = shadow_frame->GetVRegReference(arg_offset)->AsClass();
877    String* name2 = shadow_frame->GetVRegReference(arg_offset + 1)->AsString();
878    ArtField* found = NULL;
879    ObjectArray<ArtField>* fields = klass->GetIFields();
880    for (int32_t i = 0; i < fields->GetLength() && found == NULL; ++i) {
881      ArtField* f = fields->Get(i);
882      if (name2->Equals(f->GetName())) {
883        found = f;
884      }
885    }
886    if (found == NULL) {
887      fields = klass->GetSFields();
888      for (int32_t i = 0; i < fields->GetLength() && found == NULL; ++i) {
889        ArtField* f = fields->Get(i);
890        if (name2->Equals(f->GetName())) {
891          found = f;
892        }
893      }
894    }
895    CHECK(found != NULL)
896      << "Failed to find field in Class.getDeclaredField in un-started runtime. name="
897      << name2->ToModifiedUtf8() << " class=" << PrettyDescriptor(klass);
898    // TODO: getDeclaredField calls GetType once the field is found to ensure a
899    //       NoClassDefFoundError is thrown if the field's type cannot be resolved.
900    Class* jlr_Field = self->DecodeJObject(WellKnownClasses::java_lang_reflect_Field)->AsClass();
901    StackHandleScope<1> hs(self);
902    Handle<Object> field(hs.NewHandle(jlr_Field->AllocNonMovableObject(self)));
903    CHECK(field.Get() != NULL);
904    ArtMethod* c = jlr_Field->FindDeclaredDirectMethod("<init>", "(Ljava/lang/reflect/ArtField;)V");
905    uint32_t args[1];
906    args[0] = StackReference<mirror::Object>::FromMirrorPtr(found).AsVRegValue();
907    EnterInterpreterFromInvoke(self, c, field.Get(), args, NULL);
908    result->SetL(field.Get());
909  } else if (name == "int java.lang.Object.hashCode()") {
910    Object* obj = shadow_frame->GetVRegReference(arg_offset);
911    result->SetI(obj->IdentityHashCode());
912  } else if (name == "java.lang.String java.lang.reflect.ArtMethod.getMethodName(java.lang.reflect.ArtMethod)") {
913    mirror::ArtMethod* method = shadow_frame->GetVRegReference(arg_offset)->AsArtMethod();
914    result->SetL(method->GetNameAsString(self));
915  } else if (name == "void java.lang.System.arraycopy(java.lang.Object, int, java.lang.Object, int, int)" ||
916             name == "void java.lang.System.arraycopy(char[], int, char[], int, int)") {
917    // Special case array copying without initializing System.
918    Class* ctype = shadow_frame->GetVRegReference(arg_offset)->GetClass()->GetComponentType();
919    jint srcPos = shadow_frame->GetVReg(arg_offset + 1);
920    jint dstPos = shadow_frame->GetVReg(arg_offset + 3);
921    jint length = shadow_frame->GetVReg(arg_offset + 4);
922    if (!ctype->IsPrimitive()) {
923      ObjectArray<Object>* src = shadow_frame->GetVRegReference(arg_offset)->AsObjectArray<Object>();
924      ObjectArray<Object>* dst = shadow_frame->GetVRegReference(arg_offset + 2)->AsObjectArray<Object>();
925      for (jint i = 0; i < length; ++i) {
926        dst->Set(dstPos + i, src->Get(srcPos + i));
927      }
928    } else if (ctype->IsPrimitiveChar()) {
929      CharArray* src = shadow_frame->GetVRegReference(arg_offset)->AsCharArray();
930      CharArray* dst = shadow_frame->GetVRegReference(arg_offset + 2)->AsCharArray();
931      for (jint i = 0; i < length; ++i) {
932        dst->Set(dstPos + i, src->Get(srcPos + i));
933      }
934    } else if (ctype->IsPrimitiveInt()) {
935      IntArray* src = shadow_frame->GetVRegReference(arg_offset)->AsIntArray();
936      IntArray* dst = shadow_frame->GetVRegReference(arg_offset + 2)->AsIntArray();
937      for (jint i = 0; i < length; ++i) {
938        dst->Set(dstPos + i, src->Get(srcPos + i));
939      }
940    } else {
941      self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(), "Ljava/lang/InternalError;",
942                               "Unimplemented System.arraycopy for type '%s'",
943                               PrettyDescriptor(ctype).c_str());
944    }
945  } else  if (name == "java.lang.Object java.lang.ThreadLocal.get()") {
946    std::string caller(PrettyMethod(shadow_frame->GetLink()->GetMethod()));
947    if (caller == "java.lang.String java.lang.IntegralToString.convertInt(java.lang.AbstractStringBuilder, int)") {
948      // Allocate non-threadlocal buffer.
949      result->SetL(mirror::CharArray::Alloc(self, 11));
950    } else {
951      self->ThrowNewException(self->GetCurrentLocationForThrow(), "Ljava/lang/InternalError;",
952                              "Unimplemented ThreadLocal.get");
953    }
954  } else {
955    // Not special, continue with regular interpreter execution.
956    artInterpreterToInterpreterBridge(self, code_item, shadow_frame, result);
957  }
958}
959
960// Explicit DoCall template function declarations.
961#define EXPLICIT_DO_CALL_TEMPLATE_DECL(_is_range, _do_assignability_check)                      \
962  template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)                                          \
963  bool DoCall<_is_range, _do_assignability_check>(ArtMethod* method, Thread* self,              \
964                                                  ShadowFrame& shadow_frame,                    \
965                                                  const Instruction* inst, uint16_t inst_data,  \
966                                                  JValue* result)
967EXPLICIT_DO_CALL_TEMPLATE_DECL(false, false);
968EXPLICIT_DO_CALL_TEMPLATE_DECL(false, true);
969EXPLICIT_DO_CALL_TEMPLATE_DECL(true, false);
970EXPLICIT_DO_CALL_TEMPLATE_DECL(true, true);
971#undef EXPLICIT_DO_CALL_TEMPLATE_DECL
972
973// Explicit DoFilledNewArray template function declarations.
974#define EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL(_is_range_, _check, _transaction_active)       \
975  template SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)                                            \
976  bool DoFilledNewArray<_is_range_, _check, _transaction_active>(const Instruction* inst,         \
977                                                                 const ShadowFrame& shadow_frame, \
978                                                                 Thread* self, JValue* result)
979#define EXPLICIT_DO_FILLED_NEW_ARRAY_ALL_TEMPLATE_DECL(_transaction_active)       \
980  EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL(false, false, _transaction_active);  \
981  EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL(false, true, _transaction_active);   \
982  EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL(true, false, _transaction_active);   \
983  EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL(true, true, _transaction_active)
984EXPLICIT_DO_FILLED_NEW_ARRAY_ALL_TEMPLATE_DECL(false);
985EXPLICIT_DO_FILLED_NEW_ARRAY_ALL_TEMPLATE_DECL(true);
986#undef EXPLICIT_DO_FILLED_NEW_ARRAY_ALL_TEMPLATE_DECL
987#undef EXPLICIT_DO_FILLED_NEW_ARRAY_TEMPLATE_DECL
988
989}  // namespace interpreter
990}  // namespace art
991