xref: /aosp_15_r20/art/runtime/interpreter/interpreter_common.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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 #ifndef ART_RUNTIME_INTERPRETER_INTERPRETER_COMMON_H_
18 #define ART_RUNTIME_INTERPRETER_INTERPRETER_COMMON_H_
19 
20 #include "android-base/macros.h"
21 #include "instrumentation.h"
22 #include "interpreter.h"
23 
24 #include <math.h>
25 
26 #include <atomic>
27 #include <iostream>
28 #include <sstream>
29 
30 #include <android-base/logging.h>
31 #include <android-base/stringprintf.h>
32 
33 #include "art_field-inl.h"
34 #include "art_method-inl.h"
35 #include "base/locks.h"
36 #include "base/logging.h"
37 #include "base/macros.h"
38 #include "base/pointer_size.h"
39 #include "class_linker-inl.h"
40 #include "class_root-inl.h"
41 #include "common_dex_operations.h"
42 #include "common_throws.h"
43 #include "dex/dex_file-inl.h"
44 #include "dex/dex_instruction-inl.h"
45 #include "entrypoints/entrypoint_utils-inl.h"
46 #include "handle_scope-inl.h"
47 #include "interpreter_cache-inl.h"
48 #include "interpreter_switch_impl.h"
49 #include "intrinsics_list.h"
50 #include "jit/jit-inl.h"
51 #include "mirror/call_site.h"
52 #include "mirror/class-inl.h"
53 #include "mirror/dex_cache.h"
54 #include "mirror/method.h"
55 #include "mirror/method_handles_lookup.h"
56 #include "mirror/object-inl.h"
57 #include "mirror/object_array-inl.h"
58 #include "mirror/string-inl.h"
59 #include "obj_ptr.h"
60 #include "stack.h"
61 #include "thread.h"
62 #include "thread-inl.h"
63 #include "unstarted_runtime.h"
64 #include "verifier/method_verifier.h"
65 
66 namespace art HIDDEN {
67 namespace interpreter {
68 
69 EXPORT void ThrowNullPointerExceptionFromInterpreter()
70     REQUIRES_SHARED(Locks::mutator_lock_);
71 
DoMonitorEnter(Thread * self,ShadowFrame * frame,ObjPtr<mirror::Object> ref)72 static inline void DoMonitorEnter(Thread* self, ShadowFrame* frame, ObjPtr<mirror::Object> ref)
73     NO_THREAD_SAFETY_ANALYSIS
74     REQUIRES(!Roles::uninterruptible_) {
75   DCHECK(!ref.IsNull());
76   StackHandleScope<1> hs(self);
77   Handle<mirror::Object> h_ref(hs.NewHandle(ref));
78   h_ref->MonitorEnter(self);
79   DCHECK(self->HoldsLock(h_ref.Get()));
80   if (UNLIKELY(self->IsExceptionPending())) {
81     bool unlocked = h_ref->MonitorExit(self);
82     DCHECK(unlocked);
83     return;
84   }
85   if (frame->GetMethod()->MustCountLocks()) {
86     DCHECK(!frame->GetMethod()->SkipAccessChecks());
87     frame->GetLockCountData().AddMonitor(self, h_ref.Get());
88   }
89 }
90 
DoMonitorExit(Thread * self,ShadowFrame * frame,ObjPtr<mirror::Object> ref)91 static inline void DoMonitorExit(Thread* self, ShadowFrame* frame, ObjPtr<mirror::Object> ref)
92     NO_THREAD_SAFETY_ANALYSIS
93     REQUIRES(!Roles::uninterruptible_) {
94   StackHandleScope<1> hs(self);
95   Handle<mirror::Object> h_ref(hs.NewHandle(ref));
96   h_ref->MonitorExit(self);
97   if (frame->GetMethod()->MustCountLocks()) {
98     DCHECK(!frame->GetMethod()->SkipAccessChecks());
99     frame->GetLockCountData().RemoveMonitorOrThrow(self, h_ref.Get());
100   }
101 }
102 
DoMonitorCheckOnExit(Thread * self,ShadowFrame * frame)103 static inline bool DoMonitorCheckOnExit(Thread* self, ShadowFrame* frame)
104     NO_THREAD_SAFETY_ANALYSIS
105     REQUIRES(!Roles::uninterruptible_) {
106   if (frame->GetMethod()->MustCountLocks()) {
107     DCHECK(!frame->GetMethod()->SkipAccessChecks());
108     return frame->GetLockCountData().CheckAllMonitorsReleasedOrThrow(self);
109   }
110   return true;
111 }
112 
113 // Invokes the given method. This is part of the invocation support and is used by DoInvoke,
114 // DoFastInvoke and DoInvokeVirtualQuick functions.
115 // Returns true on success, otherwise throws an exception and returns false.
116 template<bool is_range>
117 EXPORT bool DoCall(ArtMethod* called_method,
118                    Thread* self,
119                    ShadowFrame& shadow_frame,
120                    const Instruction* inst,
121                    uint16_t inst_data,
122                    bool string_init,
123                    JValue* result);
124 
125 // Called by the switch interpreter to know if we can stay in it.
126 bool ShouldStayInSwitchInterpreter(ArtMethod* method)
127     REQUIRES_SHARED(Locks::mutator_lock_);
128 
129 // Throws exception if we are getting close to the end of the stack.
130 NO_INLINE bool CheckStackOverflow(Thread* self, size_t frame_size)
131     REQUIRES_SHARED(Locks::mutator_lock_);
132 
133 
134 // Sends the normal method exit event.
135 // Returns true if the events succeeded and false if there is a pending exception.
136 template <typename T>
137 bool SendMethodExitEvents(
138     Thread* self,
139     const instrumentation::Instrumentation* instrumentation,
140     ShadowFrame& frame,
141     ArtMethod* method,
142     T& result) REQUIRES_SHARED(Locks::mutator_lock_);
143 
144 static inline ALWAYS_INLINE WARN_UNUSED bool
NeedsMethodExitEvent(const instrumentation::Instrumentation * ins)145 NeedsMethodExitEvent(const instrumentation::Instrumentation* ins)
146     REQUIRES_SHARED(Locks::mutator_lock_) {
147   return ins->HasMethodExitListeners() || ins->HasWatchedFramePopListeners();
148 }
149 
150 COLD_ATTR void UnlockHeldMonitors(Thread* self, ShadowFrame* shadow_frame)
151     REQUIRES_SHARED(Locks::mutator_lock_);
152 
153 EXPORT
154 void PerformNonStandardReturn(Thread* self,
155                               ShadowFrame& frame,
156                               JValue& result,
157                               const instrumentation::Instrumentation* instrumentation,
158                               bool unlock_monitors = true) REQUIRES_SHARED(Locks::mutator_lock_);
159 
160 // Handles all invoke-XXX/range instructions except for invoke-polymorphic[/range].
161 // Returns true on success, otherwise throws an exception and returns false.
162 template<InvokeType type, bool is_range>
DoInvoke(Thread * self,ShadowFrame & shadow_frame,const Instruction * inst,uint16_t inst_data,JValue * result)163 static ALWAYS_INLINE bool DoInvoke(Thread* self,
164                                    ShadowFrame& shadow_frame,
165                                    const Instruction* inst,
166                                    uint16_t inst_data,
167                                    JValue* result)
168     REQUIRES_SHARED(Locks::mutator_lock_) {
169   // Make sure to check for async exceptions before anything else.
170   if (UNLIKELY(self->ObserveAsyncException())) {
171     return false;
172   }
173   const uint32_t vregC = is_range ? inst->VRegC_3rc() : inst->VRegC_35c();
174   ObjPtr<mirror::Object> obj = type == kStatic ? nullptr : shadow_frame.GetVRegReference(vregC);
175   ArtMethod* sf_method = shadow_frame.GetMethod();
176   bool string_init = false;
177   ArtMethod* called_method = FindMethodToCall<type>(
178       self, sf_method, &obj, *inst, /* only_lookup_tls_cache= */ false, &string_init);
179   if (called_method == nullptr) {
180     DCHECK(self->IsExceptionPending());
181     result->SetJ(0);
182     return false;
183   }
184 
185   return DoCall<is_range>(
186       called_method, self, shadow_frame, inst, inst_data, string_init, result);
187 }
188 
ResolveMethodHandle(Thread * self,uint32_t method_handle_index,ArtMethod * referrer)189 static inline ObjPtr<mirror::MethodHandle> ResolveMethodHandle(Thread* self,
190                                                                uint32_t method_handle_index,
191                                                                ArtMethod* referrer)
192     REQUIRES_SHARED(Locks::mutator_lock_) {
193   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
194   return class_linker->ResolveMethodHandle(self, method_handle_index, referrer);
195 }
196 
ResolveMethodType(Thread * self,dex::ProtoIndex method_type_index,ArtMethod * referrer)197 static inline ObjPtr<mirror::MethodType> ResolveMethodType(Thread* self,
198                                                            dex::ProtoIndex method_type_index,
199                                                            ArtMethod* referrer)
200     REQUIRES_SHARED(Locks::mutator_lock_) {
201   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
202   return class_linker->ResolveMethodType(self, method_type_index, referrer);
203 }
204 
205 #define DECLARE_SIGNATURE_POLYMORPHIC_HANDLER(Name, ...)              \
206 bool Do ## Name(Thread* self,                                         \
207                 ShadowFrame& shadow_frame,                            \
208                 const Instruction* inst,                              \
209                 uint16_t inst_data,                                   \
210                 JValue* result) REQUIRES_SHARED(Locks::mutator_lock_);
211 ART_INTRINSICS_LIST(DECLARE_SIGNATURE_POLYMORPHIC_HANDLER)
212 #undef DECLARE_SIGNATURE_POLYMORPHIC_HANDLER
213 
214 // Performs a invoke-polymorphic or invoke-polymorphic-range.
215 template<bool is_range>
216 EXPORT bool DoInvokePolymorphic(Thread* self,
217                                 ShadowFrame& shadow_frame,
218                                 const Instruction* inst,
219                                 uint16_t inst_data,
220                                 JValue* result)
221     REQUIRES_SHARED(Locks::mutator_lock_);
222 
223 EXPORT bool DoInvokeCustom(Thread* self,
224                            ShadowFrame& shadow_frame,
225                            uint32_t call_site_idx,
226                            const InstructionOperands* operands,
227                            JValue* result)
228     REQUIRES_SHARED(Locks::mutator_lock_);
229 
230 // Performs a custom invoke (invoke-custom/invoke-custom-range).
231 template<bool is_range>
DoInvokeCustom(Thread * self,ShadowFrame & shadow_frame,const Instruction * inst,uint16_t inst_data,JValue * result)232 bool DoInvokeCustom(Thread* self,
233                     ShadowFrame& shadow_frame,
234                     const Instruction* inst,
235                     uint16_t inst_data,
236                     JValue* result)
237     REQUIRES_SHARED(Locks::mutator_lock_) {
238   const uint32_t call_site_idx = is_range ? inst->VRegB_3rc() : inst->VRegB_35c();
239   if (is_range) {
240     RangeInstructionOperands operands(inst->VRegC_3rc(), inst->VRegA_3rc());
241     return DoInvokeCustom(self, shadow_frame, call_site_idx, &operands, result);
242   } else {
243     uint32_t args[Instruction::kMaxVarArgRegs];
244     inst->GetVarArgs(args, inst_data);
245     VarArgsInstructionOperands operands(args, inst->VRegA_35c());
246     return DoInvokeCustom(self, shadow_frame, call_site_idx, &operands, result);
247   }
248 }
249 
250 template<Primitive::Type field_type>
GetFieldValue(const ShadowFrame & shadow_frame,uint32_t vreg)251 ALWAYS_INLINE static JValue GetFieldValue(const ShadowFrame& shadow_frame, uint32_t vreg)
252     REQUIRES_SHARED(Locks::mutator_lock_) {
253   JValue field_value;
254   switch (field_type) {
255     case Primitive::kPrimBoolean:
256       field_value.SetZ(static_cast<uint8_t>(shadow_frame.GetVReg(vreg)));
257       break;
258     case Primitive::kPrimByte:
259       field_value.SetB(static_cast<int8_t>(shadow_frame.GetVReg(vreg)));
260       break;
261     case Primitive::kPrimChar:
262       field_value.SetC(static_cast<uint16_t>(shadow_frame.GetVReg(vreg)));
263       break;
264     case Primitive::kPrimShort:
265       field_value.SetS(static_cast<int16_t>(shadow_frame.GetVReg(vreg)));
266       break;
267     case Primitive::kPrimInt:
268       field_value.SetI(shadow_frame.GetVReg(vreg));
269       break;
270     case Primitive::kPrimLong:
271       field_value.SetJ(shadow_frame.GetVRegLong(vreg));
272       break;
273     case Primitive::kPrimNot:
274       field_value.SetL(shadow_frame.GetVRegReference(vreg));
275       break;
276     default:
277       LOG(FATAL) << "Unreachable: " << field_type;
278       UNREACHABLE();
279   }
280   return field_value;
281 }
282 
283 LIBART_PROTECTED
284 extern "C" size_t NterpGetStaticField(Thread* self,
285                                       ArtMethod* caller,
286                                       const uint16_t* dex_pc_ptr,
287                                       size_t resolve_field_type);
288 
289 LIBART_PROTECTED
290 extern "C" uint32_t NterpGetInstanceFieldOffset(Thread* self,
291                                                 ArtMethod* caller,
292                                                 const uint16_t* dex_pc_ptr,
293                                                 size_t resolve_field_type);
294 
GetFieldInfo(Thread * self,ArtMethod * caller,const uint16_t * dex_pc_ptr,bool is_static,bool resolve_field_type,ArtField ** field,bool * is_volatile,MemberOffset * offset)295 static inline void GetFieldInfo(Thread* self,
296                                 ArtMethod* caller,
297                                 const uint16_t* dex_pc_ptr,
298                                 bool is_static,
299                                 bool resolve_field_type,
300                                 ArtField** field,
301                                 bool* is_volatile,
302                                 MemberOffset* offset) {
303   size_t tls_value = 0u;
304   if (!self->GetInterpreterCache()->Get(self, dex_pc_ptr, &tls_value)) {
305     if (is_static) {
306       tls_value = NterpGetStaticField(self, caller, dex_pc_ptr, resolve_field_type);
307     } else {
308       tls_value = NterpGetInstanceFieldOffset(self, caller, dex_pc_ptr, resolve_field_type);
309     }
310 
311     if (self->IsExceptionPending()) {
312       return;
313     }
314   }
315 
316   if (is_static) {
317     DCHECK_NE(tls_value, 0u);
318     *is_volatile = ((tls_value & 1) != 0);
319     *field = reinterpret_cast<ArtField*>(tls_value & ~static_cast<size_t>(1u));
320     *offset = (*field)->GetOffset();
321   } else {
322     *is_volatile = (static_cast<int32_t>(tls_value) < 0);
323     *offset = MemberOffset(std::abs(static_cast<int32_t>(tls_value)));
324   }
325 }
326 
327 // Handles string resolution for const-string and const-string-jumbo instructions. Also ensures the
328 // java.lang.String class is initialized.
ResolveString(Thread * self,ShadowFrame & shadow_frame,dex::StringIndex string_idx)329 static inline ObjPtr<mirror::String> ResolveString(Thread* self,
330                                                    ShadowFrame& shadow_frame,
331                                                    dex::StringIndex string_idx)
332     REQUIRES_SHARED(Locks::mutator_lock_) {
333   ObjPtr<mirror::Class> java_lang_string_class = GetClassRoot<mirror::String>();
334   if (UNLIKELY(!java_lang_string_class->IsVisiblyInitialized())) {
335     StackHandleScope<1> hs(self);
336     Handle<mirror::Class> h_class(hs.NewHandle(java_lang_string_class));
337     if (UNLIKELY(!Runtime::Current()->GetClassLinker()->EnsureInitialized(
338                       self, h_class, /*can_init_fields=*/ true, /*can_init_parents=*/ true))) {
339       DCHECK(self->IsExceptionPending());
340       return nullptr;
341     }
342     DCHECK(h_class->IsInitializing());
343   }
344   ArtMethod* method = shadow_frame.GetMethod();
345   ObjPtr<mirror::String> string_ptr =
346       Runtime::Current()->GetClassLinker()->ResolveString(string_idx, method);
347   return string_ptr;
348 }
349 
350 // Handles div-int, div-int/2addr, div-int/li16 and div-int/lit8 instructions.
351 // Returns true on success, otherwise throws a java.lang.ArithmeticException and return false.
DoIntDivide(ShadowFrame & shadow_frame,size_t result_reg,int32_t dividend,int32_t divisor)352 static inline bool DoIntDivide(ShadowFrame& shadow_frame, size_t result_reg,
353                                int32_t dividend, int32_t divisor)
354     REQUIRES_SHARED(Locks::mutator_lock_) {
355   constexpr int32_t kMinInt = std::numeric_limits<int32_t>::min();
356   if (UNLIKELY(divisor == 0)) {
357     ThrowArithmeticExceptionDivideByZero();
358     return false;
359   }
360   if (UNLIKELY(dividend == kMinInt && divisor == -1)) {
361     shadow_frame.SetVReg(result_reg, kMinInt);
362   } else {
363     shadow_frame.SetVReg(result_reg, dividend / divisor);
364   }
365   return true;
366 }
367 
368 // Handles rem-int, rem-int/2addr, rem-int/li16 and rem-int/lit8 instructions.
369 // Returns true on success, otherwise throws a java.lang.ArithmeticException and return false.
DoIntRemainder(ShadowFrame & shadow_frame,size_t result_reg,int32_t dividend,int32_t divisor)370 static inline bool DoIntRemainder(ShadowFrame& shadow_frame, size_t result_reg,
371                                   int32_t dividend, int32_t divisor)
372     REQUIRES_SHARED(Locks::mutator_lock_) {
373   constexpr int32_t kMinInt = std::numeric_limits<int32_t>::min();
374   if (UNLIKELY(divisor == 0)) {
375     ThrowArithmeticExceptionDivideByZero();
376     return false;
377   }
378   if (UNLIKELY(dividend == kMinInt && divisor == -1)) {
379     shadow_frame.SetVReg(result_reg, 0);
380   } else {
381     shadow_frame.SetVReg(result_reg, dividend % divisor);
382   }
383   return true;
384 }
385 
386 // Handles div-long and div-long-2addr instructions.
387 // Returns true on success, otherwise throws a java.lang.ArithmeticException and return false.
DoLongDivide(ShadowFrame & shadow_frame,size_t result_reg,int64_t dividend,int64_t divisor)388 static inline bool DoLongDivide(ShadowFrame& shadow_frame,
389                                 size_t result_reg,
390                                 int64_t dividend,
391                                 int64_t divisor)
392     REQUIRES_SHARED(Locks::mutator_lock_) {
393   const int64_t kMinLong = std::numeric_limits<int64_t>::min();
394   if (UNLIKELY(divisor == 0)) {
395     ThrowArithmeticExceptionDivideByZero();
396     return false;
397   }
398   if (UNLIKELY(dividend == kMinLong && divisor == -1)) {
399     shadow_frame.SetVRegLong(result_reg, kMinLong);
400   } else {
401     shadow_frame.SetVRegLong(result_reg, dividend / divisor);
402   }
403   return true;
404 }
405 
406 // Handles rem-long and rem-long-2addr instructions.
407 // Returns true on success, otherwise throws a java.lang.ArithmeticException and return false.
DoLongRemainder(ShadowFrame & shadow_frame,size_t result_reg,int64_t dividend,int64_t divisor)408 static inline bool DoLongRemainder(ShadowFrame& shadow_frame,
409                                    size_t result_reg,
410                                    int64_t dividend,
411                                    int64_t divisor)
412     REQUIRES_SHARED(Locks::mutator_lock_) {
413   const int64_t kMinLong = std::numeric_limits<int64_t>::min();
414   if (UNLIKELY(divisor == 0)) {
415     ThrowArithmeticExceptionDivideByZero();
416     return false;
417   }
418   if (UNLIKELY(dividend == kMinLong && divisor == -1)) {
419     shadow_frame.SetVRegLong(result_reg, 0);
420   } else {
421     shadow_frame.SetVRegLong(result_reg, dividend % divisor);
422   }
423   return true;
424 }
425 
426 // Handles filled-new-array and filled-new-array-range instructions.
427 // Returns true on success, otherwise throws an exception and returns false.
428 template <bool is_range>
429 EXPORT bool DoFilledNewArray(const Instruction* inst,
430                              const ShadowFrame& shadow_frame,
431                              Thread* self,
432                              JValue* result);
433 
434 // Handles packed-switch instruction.
435 // Returns the branch offset to the next instruction to execute.
DoPackedSwitch(const Instruction * inst,const ShadowFrame & shadow_frame,uint16_t inst_data)436 static inline int32_t DoPackedSwitch(const Instruction* inst,
437                                      const ShadowFrame& shadow_frame,
438                                      uint16_t inst_data)
439     REQUIRES_SHARED(Locks::mutator_lock_) {
440   DCHECK(inst->Opcode() == Instruction::PACKED_SWITCH);
441   const uint16_t* switch_data = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
442   int32_t test_val = shadow_frame.GetVReg(inst->VRegA_31t(inst_data));
443   DCHECK_EQ(switch_data[0], static_cast<uint16_t>(Instruction::kPackedSwitchSignature));
444   uint16_t size = switch_data[1];
445   if (size == 0) {
446     // Empty packed switch, move forward by 3 (size of PACKED_SWITCH).
447     return 3;
448   }
449   const int32_t* keys = reinterpret_cast<const int32_t*>(&switch_data[2]);
450   DCHECK_ALIGNED(keys, 4);
451   int32_t first_key = keys[0];
452   const int32_t* targets = reinterpret_cast<const int32_t*>(&switch_data[4]);
453   DCHECK_ALIGNED(targets, 4);
454   int32_t index = test_val - first_key;
455   if (index >= 0 && index < size) {
456     return targets[index];
457   } else {
458     // No corresponding value: move forward by 3 (size of PACKED_SWITCH).
459     return 3;
460   }
461 }
462 
463 // Handles sparse-switch instruction.
464 // Returns the branch offset to the next instruction to execute.
DoSparseSwitch(const Instruction * inst,const ShadowFrame & shadow_frame,uint16_t inst_data)465 static inline int32_t DoSparseSwitch(const Instruction* inst, const ShadowFrame& shadow_frame,
466                                      uint16_t inst_data)
467     REQUIRES_SHARED(Locks::mutator_lock_) {
468   DCHECK(inst->Opcode() == Instruction::SPARSE_SWITCH);
469   const uint16_t* switch_data = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
470   int32_t test_val = shadow_frame.GetVReg(inst->VRegA_31t(inst_data));
471   DCHECK_EQ(switch_data[0], static_cast<uint16_t>(Instruction::kSparseSwitchSignature));
472   uint16_t size = switch_data[1];
473   // Return length of SPARSE_SWITCH if size is 0.
474   if (size == 0) {
475     return 3;
476   }
477   const int32_t* keys = reinterpret_cast<const int32_t*>(&switch_data[2]);
478   DCHECK_ALIGNED(keys, 4);
479   const int32_t* entries = keys + size;
480   DCHECK_ALIGNED(entries, 4);
481   int lo = 0;
482   int hi = size - 1;
483   while (lo <= hi) {
484     int mid = (lo + hi) / 2;
485     int32_t foundVal = keys[mid];
486     if (test_val < foundVal) {
487       hi = mid - 1;
488     } else if (test_val > foundVal) {
489       lo = mid + 1;
490     } else {
491       return entries[mid];
492     }
493   }
494   // No corresponding value: move forward by 3 (size of SPARSE_SWITCH).
495   return 3;
496 }
497 
498 // We execute any instrumentation events triggered by throwing and/or handing the pending exception
499 // and change the shadow_frames dex_pc to the appropriate exception handler if the current method
500 // has one. If the exception has been handled and the shadow_frame is now pointing to a catch clause
501 // we return true. If the current method is unable to handle the exception we return false.
502 // This function accepts a null Instrumentation* as a way to cause instrumentation events not to be
503 // reported.
504 // TODO We might wish to reconsider how we cause some events to be ignored.
505 EXPORT bool MoveToExceptionHandler(Thread* self,
506                                    ShadowFrame& shadow_frame,
507                                    bool skip_listeners,
508                                    bool skip_throw_listener) REQUIRES_SHARED(Locks::mutator_lock_);
509 
510 NO_RETURN EXPORT void UnexpectedOpcode(const Instruction* inst, const ShadowFrame& shadow_frame)
511     COLD_ATTR
512     REQUIRES_SHARED(Locks::mutator_lock_);
513 
514 // Set true if you want TraceExecution invocation before each bytecode execution.
515 constexpr bool kTraceExecutionEnabled = false;
516 
TraceExecution(const ShadowFrame & shadow_frame,const Instruction * inst,const uint32_t dex_pc)517 static inline void TraceExecution(const ShadowFrame& shadow_frame, const Instruction* inst,
518                                   const uint32_t dex_pc)
519     REQUIRES_SHARED(Locks::mutator_lock_) {
520   if (kTraceExecutionEnabled) {
521 #define TRACE_LOG std::cerr
522     std::ostringstream oss;
523     oss << shadow_frame.GetMethod()->PrettyMethod()
524         << android::base::StringPrintf("\n0x%x: ", dex_pc)
525         << inst->DumpString(shadow_frame.GetMethod()->GetDexFile()) << "\n";
526     for (uint32_t i = 0; i < shadow_frame.NumberOfVRegs(); ++i) {
527       uint32_t raw_value = shadow_frame.GetVReg(i);
528       ObjPtr<mirror::Object> ref_value = shadow_frame.GetVRegReference(i);
529       oss << android::base::StringPrintf(" vreg%u=0x%08X", i, raw_value);
530       if (ref_value != nullptr) {
531         if (ref_value->GetClass()->IsStringClass() &&
532             !ref_value->AsString()->IsValueNull()) {
533           oss << "/java.lang.String \"" << ref_value->AsString()->ToModifiedUtf8() << "\"";
534         } else {
535           oss << "/" << ref_value->PrettyTypeOf();
536         }
537       }
538     }
539     TRACE_LOG << oss.str() << "\n";
540 #undef TRACE_LOG
541   }
542 }
543 
IsBackwardBranch(int32_t branch_offset)544 static inline bool IsBackwardBranch(int32_t branch_offset) {
545   return branch_offset <= 0;
546 }
547 
548 // The arg_offset is the offset to the first input register in the frame.
549 void ArtInterpreterToCompiledCodeBridge(Thread* self,
550                                         ArtMethod* caller,
551                                         ShadowFrame* shadow_frame,
552                                         uint16_t arg_offset,
553                                         JValue* result);
554 
555 // Set string value created from StringFactory.newStringFromXXX() into all aliases of
556 // StringFactory.newEmptyString().
557 void SetStringInitValueToAllAliases(ShadowFrame* shadow_frame,
558                                     uint16_t this_obj_vreg,
559                                     JValue result);
560 
561 }  // namespace interpreter
562 }  // namespace art
563 
564 #endif  // ART_RUNTIME_INTERPRETER_INTERPRETER_COMMON_H_
565