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