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