blob: e9b78f3259335007a95ae62ddc958cf57b303a75 [file] [log] [blame]
Sebastien Hertz8ece0502013-08-07 11:26:41 +02001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ART_RUNTIME_INTERPRETER_INTERPRETER_COMMON_H_
18#define ART_RUNTIME_INTERPRETER_INTERPRETER_COMMON_H_
19
Alex Lightb7c640d2019-03-20 15:52:13 -070020#include "android-base/macros.h"
21#include "instrumentation.h"
Sebastien Hertz8ece0502013-08-07 11:26:41 +020022#include "interpreter.h"
buzbee78f1bdc2017-03-01 10:55:57 -080023#include "interpreter_intrinsics.h"
David Srbeckyf56393c2019-08-02 15:49:27 +010024#include "transaction.h"
Sebastien Hertz8ece0502013-08-07 11:26:41 +020025
26#include <math.h>
27
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070028#include <atomic>
Ian Rogerscf7f1912014-10-22 22:06:39 -070029#include <iostream>
Ian Rogersc7dd2952014-10-21 23:31:19 -070030#include <sstream>
31
Andreas Gampe57943812017-12-06 21:39:13 -080032#include <android-base/logging.h>
33#include <android-base/stringprintf.h>
Andreas Gampe46ee31b2016-12-14 10:11:49 -080034
Mathieu Chartierc7853442015-03-27 14:35:38 -070035#include "art_field-inl.h"
Mathieu Chartiere401d142015-04-22 13:56:20 -070036#include "art_method-inl.h"
Andreas Gampe542451c2016-07-26 09:02:02 -070037#include "base/enums.h"
Andreas Gampe7fbc4a52018-11-28 08:26:47 -080038#include "base/locks.h"
Mathieu Chartier765b2a02019-05-02 11:04:13 -070039#include "base/logging.h"
Andreas Gampe794ad762015-02-23 08:12:24 -080040#include "base/macros.h"
Sebastien Hertz8ece0502013-08-07 11:26:41 +020041#include "class_linker-inl.h"
Vladimir Marko5868ada2020-05-12 11:50:34 +010042#include "class_root-inl.h"
Orion Hodson811bd5f2016-12-07 11:35:37 +000043#include "common_dex_operations.h"
Sebastien Hertz8ece0502013-08-07 11:26:41 +020044#include "common_throws.h"
David Sehr9e734c72018-01-04 17:56:19 -080045#include "dex/dex_file-inl.h"
46#include "dex/dex_instruction-inl.h"
Mingyao Yang98d1cc82014-05-15 17:02:16 -070047#include "entrypoints/entrypoint_utils-inl.h"
Mathieu Chartier0cd81352014-05-22 16:48:55 -070048#include "handle_scope-inl.h"
David Srbecky960327b2018-10-25 10:11:59 +000049#include "interpreter_switch_impl.h"
David Srbeckye3fc2d12018-11-30 13:41:14 +000050#include "jit/jit-inl.h"
Orion Hodsonc069a302017-01-18 09:23:12 +000051#include "mirror/call_site.h"
Sebastien Hertz8ece0502013-08-07 11:26:41 +020052#include "mirror/class-inl.h"
Christina Wadsworthbf44e0e2016-08-18 10:37:42 -070053#include "mirror/dex_cache.h"
54#include "mirror/method.h"
Orion Hodsonc069a302017-01-18 09:23:12 +000055#include "mirror/method_handles_lookup.h"
Sebastien Hertz8ece0502013-08-07 11:26:41 +020056#include "mirror/object-inl.h"
57#include "mirror/object_array-inl.h"
Douglas Leung4965c022014-06-11 11:41:11 -070058#include "mirror/string-inl.h"
Mathieu Chartieref41db72016-10-25 15:08:01 -070059#include "obj_ptr.h"
Andreas Gampe03ec9302015-08-27 17:41:47 -070060#include "stack.h"
Sebastien Hertz8ece0502013-08-07 11:26:41 +020061#include "thread.h"
Hans Boehm1b3ec0f2022-01-26 16:53:07 +000062#include "thread-inl.h"
Orion Hodson811bd5f2016-12-07 11:35:37 +000063#include "unstarted_runtime.h"
Alex Lightb7c640d2019-03-20 15:52:13 -070064#include "verifier/method_verifier.h"
Sebastien Hertz8ece0502013-08-07 11:26:41 +020065#include "well_known_classes.h"
66
Sebastien Hertz8ece0502013-08-07 11:26:41 +020067namespace art {
68namespace interpreter {
69
Nicolas Geoffray0aa50ce2015-03-10 11:03:29 +000070void ThrowNullPointerExceptionFromInterpreter()
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070071 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzda843e12014-05-28 19:28:31 +020072
Andreas Gampe03ec9302015-08-27 17:41:47 -070073template <bool kMonitorCounting>
Mathieu Chartieref41db72016-10-25 15:08:01 -070074static inline void DoMonitorEnter(Thread* self, ShadowFrame* frame, ObjPtr<mirror::Object> ref)
Mathieu Chartier2d096c92015-10-12 16:18:20 -070075 NO_THREAD_SAFETY_ANALYSIS
76 REQUIRES(!Roles::uninterruptible_) {
Alex Light77fee872017-09-05 14:51:49 -070077 DCHECK(!ref.IsNull());
Mathieu Chartier2d096c92015-10-12 16:18:20 -070078 StackHandleScope<1> hs(self);
Mathieu Chartieref41db72016-10-25 15:08:01 -070079 Handle<mirror::Object> h_ref(hs.NewHandle(ref));
Mathieu Chartier2d096c92015-10-12 16:18:20 -070080 h_ref->MonitorEnter(self);
Alex Light77fee872017-09-05 14:51:49 -070081 DCHECK(self->HoldsLock(h_ref.Get()));
82 if (UNLIKELY(self->IsExceptionPending())) {
83 bool unlocked = h_ref->MonitorExit(self);
84 DCHECK(unlocked);
85 return;
86 }
Andreas Gampe56fdd0e2016-04-28 14:56:54 -070087 if (kMonitorCounting && frame->GetMethod()->MustCountLocks()) {
88 frame->GetLockCountData().AddMonitor(self, h_ref.Get());
89 }
Sebastien Hertz8ece0502013-08-07 11:26:41 +020090}
91
Andreas Gampe03ec9302015-08-27 17:41:47 -070092template <bool kMonitorCounting>
Mathieu Chartieref41db72016-10-25 15:08:01 -070093static inline void DoMonitorExit(Thread* self, ShadowFrame* frame, ObjPtr<mirror::Object> ref)
Mathieu Chartier2d096c92015-10-12 16:18:20 -070094 NO_THREAD_SAFETY_ANALYSIS
95 REQUIRES(!Roles::uninterruptible_) {
96 StackHandleScope<1> hs(self);
Mathieu Chartieref41db72016-10-25 15:08:01 -070097 Handle<mirror::Object> h_ref(hs.NewHandle(ref));
Mathieu Chartier2d096c92015-10-12 16:18:20 -070098 h_ref->MonitorExit(self);
Andreas Gampe56fdd0e2016-04-28 14:56:54 -070099 if (kMonitorCounting && frame->GetMethod()->MustCountLocks()) {
100 frame->GetLockCountData().RemoveMonitorOrThrow(self, h_ref.Get());
101 }
102}
103
104template <bool kMonitorCounting>
105static inline bool DoMonitorCheckOnExit(Thread* self, ShadowFrame* frame)
106 NO_THREAD_SAFETY_ANALYSIS
107 REQUIRES(!Roles::uninterruptible_) {
108 if (kMonitorCounting && frame->GetMethod()->MustCountLocks()) {
109 return frame->GetLockCountData().CheckAllMonitorsReleasedOrThrow(self);
110 }
111 return true;
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200112}
113
Sebastien Hertz45b15972015-04-03 16:07:05 +0200114void AbortTransactionF(Thread* self, const char* fmt, ...)
115 __attribute__((__format__(__printf__, 2, 3)))
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700116 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertz45b15972015-04-03 16:07:05 +0200117
118void AbortTransactionV(Thread* self, const char* fmt, va_list args)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700119 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierb2c7ead2014-04-29 11:13:16 -0700120
Mathieu Chartieref41db72016-10-25 15:08:01 -0700121void RecordArrayElementsInTransaction(ObjPtr<mirror::Array> array, int32_t count)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700122 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100123
buzbee78f1bdc2017-03-01 10:55:57 -0800124// Invokes the given method. This is part of the invocation support and is used by DoInvoke,
125// DoFastInvoke and DoInvokeVirtualQuick functions.
Sebastien Hertzc6714852013-09-30 16:42:32 +0200126// Returns true on success, otherwise throws an exception and returns false.
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200127template<bool is_range, bool do_assignability_check>
Ian Rogerse94652f2014-12-02 11:13:19 -0800128bool DoCall(ArtMethod* called_method, Thread* self, ShadowFrame& shadow_frame,
Sebastien Hertzc6714852013-09-30 16:42:32 +0200129 const Instruction* inst, uint16_t inst_data, JValue* result);
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200130
Nicolas Geoffray854af032021-12-21 08:32:42 +0000131// Called by the switch interpreter to know if we can stay in it.
132bool ShouldStayInSwitchInterpreter(ArtMethod* method)
David Srbecky9581e612018-10-30 14:29:43 +0000133 REQUIRES_SHARED(Locks::mutator_lock_);
David Srbecky960327b2018-10-25 10:11:59 +0000134
135// Throws exception if we are getting close to the end of the stack.
136NO_INLINE bool CheckStackOverflow(Thread* self, size_t frame_size)
137 REQUIRES_SHARED(Locks::mutator_lock_);
138
Alex Lightb7c640d2019-03-20 15:52:13 -0700139
140// Sends the normal method exit event.
141// Returns true if the events succeeded and false if there is a pending exception.
142template <typename T> bool SendMethodExitEvents(
143 Thread* self,
144 const instrumentation::Instrumentation* instrumentation,
145 ShadowFrame& frame,
Alex Lightb7c640d2019-03-20 15:52:13 -0700146 ArtMethod* method,
Alex Lightb7c640d2019-03-20 15:52:13 -0700147 T& result) REQUIRES_SHARED(Locks::mutator_lock_);
148
149static inline ALWAYS_INLINE WARN_UNUSED bool
150NeedsMethodExitEvent(const instrumentation::Instrumentation* ins)
151 REQUIRES_SHARED(Locks::mutator_lock_) {
152 return ins->HasMethodExitListeners() || ins->HasWatchedFramePopListeners();
153}
154
155// NO_INLINE so we won't bloat the interpreter with this very cold lock-release code.
156template <bool kMonitorCounting>
157static NO_INLINE void UnlockHeldMonitors(Thread* self, ShadowFrame* shadow_frame)
158 REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Marko0685b982021-03-25 11:59:22 +0000159 DCHECK(shadow_frame->GetForcePopFrame() ||
160 Runtime::Current()->IsTransactionAborted());
Alex Lightb7c640d2019-03-20 15:52:13 -0700161 // Unlock all monitors.
162 if (kMonitorCounting && shadow_frame->GetMethod()->MustCountLocks()) {
163 // Get the monitors from the shadow-frame monitor-count data.
164 shadow_frame->GetLockCountData().VisitMonitors(
165 [&](mirror::Object** obj) REQUIRES_SHARED(Locks::mutator_lock_) {
166 // Since we don't use the 'obj' pointer after the DoMonitorExit everything should be fine
167 // WRT suspension.
168 DoMonitorExit<kMonitorCounting>(self, shadow_frame, *obj);
169 });
170 } else {
171 std::vector<verifier::MethodVerifier::DexLockInfo> locks;
172 verifier::MethodVerifier::FindLocksAtDexPc(shadow_frame->GetMethod(),
173 shadow_frame->GetDexPC(),
174 &locks,
175 Runtime::Current()->GetTargetSdkVersion());
176 for (const auto& reg : locks) {
177 if (UNLIKELY(reg.dex_registers.empty())) {
178 LOG(ERROR) << "Unable to determine reference locked by "
179 << shadow_frame->GetMethod()->PrettyMethod() << " at pc "
180 << shadow_frame->GetDexPC();
181 } else {
182 DoMonitorExit<kMonitorCounting>(
183 self, shadow_frame, shadow_frame->GetVRegReference(*reg.dex_registers.begin()));
184 }
185 }
186 }
187}
188
189enum class MonitorState {
190 kNoMonitorsLocked,
191 kCountingMonitors,
192 kNormalMonitors,
193};
194
195template<MonitorState kMonitorState>
Vladimir Marko0685b982021-03-25 11:59:22 +0000196static inline ALWAYS_INLINE void PerformNonStandardReturn(
Alex Lightb7c640d2019-03-20 15:52:13 -0700197 Thread* self,
198 ShadowFrame& frame,
199 JValue& result,
200 const instrumentation::Instrumentation* instrumentation,
Mythri Alle18fba4c2021-10-27 10:00:55 +0000201 uint16_t num_dex_inst) REQUIRES_SHARED(Locks::mutator_lock_) {
Alex Lightb7c640d2019-03-20 15:52:13 -0700202 static constexpr bool kMonitorCounting = (kMonitorState == MonitorState::kCountingMonitors);
Vladimir Marko0685b982021-03-25 11:59:22 +0000203 ObjPtr<mirror::Object> thiz(frame.GetThisObject(num_dex_inst));
204 StackHandleScope<1u> hs(self);
Vladimir Marko0685b982021-03-25 11:59:22 +0000205 if (UNLIKELY(self->IsExceptionPending())) {
206 LOG(WARNING) << "Suppressing exception for non-standard method exit: "
207 << self->GetException()->Dump();
208 self->ClearException();
Alex Lightb7c640d2019-03-20 15:52:13 -0700209 }
Vladimir Marko0685b982021-03-25 11:59:22 +0000210 if (kMonitorState != MonitorState::kNoMonitorsLocked) {
211 UnlockHeldMonitors<kMonitorCounting>(self, &frame);
212 }
213 DoMonitorCheckOnExit<kMonitorCounting>(self, &frame);
214 result = JValue();
215 if (UNLIKELY(NeedsMethodExitEvent(instrumentation))) {
Mythri Alle18fba4c2021-10-27 10:00:55 +0000216 SendMethodExitEvents(self, instrumentation, frame, frame.GetMethod(), result);
Vladimir Marko0685b982021-03-25 11:59:22 +0000217 }
Alex Lightb7c640d2019-03-20 15:52:13 -0700218}
219
Narayan Kamath9823e782016-08-03 12:46:58 +0100220// Handles all invoke-XXX/range instructions except for invoke-polymorphic[/range].
Sebastien Hertzc6714852013-09-30 16:42:32 +0200221// Returns true on success, otherwise throws an exception and returns false.
David Srbeckydfe55442021-03-18 11:46:27 +0000222template<InvokeType type, bool is_range, bool do_access_check, bool is_mterp>
David Srbecky6849c062018-09-21 09:42:24 +0100223static ALWAYS_INLINE bool DoInvoke(Thread* self,
224 ShadowFrame& shadow_frame,
225 const Instruction* inst,
226 uint16_t inst_data,
227 JValue* result)
228 REQUIRES_SHARED(Locks::mutator_lock_) {
Alex Light848574c2017-09-25 16:59:39 -0700229 // Make sure to check for async exceptions before anything else.
Nicolas Geoffraye4f983c2021-07-12 15:53:27 +0100230 if (UNLIKELY(self->ObserveAsyncException())) {
Alex Light848574c2017-09-25 16:59:39 -0700231 return false;
232 }
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200233 const uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
234 const uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c();
David Srbeckyc853eed2018-09-13 14:33:22 +0100235 ArtMethod* sf_method = shadow_frame.GetMethod();
236
Nicolas Geoffray00391822019-12-10 10:17:23 +0000237 // Try to find the method in small thread-local cache first (only used when
238 // nterp is not used as mterp and nterp use the cache in an incompatible way).
David Srbeckyc853eed2018-09-13 14:33:22 +0100239 InterpreterCache* tls_cache = self->GetInterpreterCache();
240 size_t tls_value;
241 ArtMethod* resolved_method;
Hans Boehm3d2f1482022-01-17 01:32:55 +0000242 if (!IsNterpSupported() && LIKELY(tls_cache->Get(inst, &tls_value))) {
David Srbeckyc853eed2018-09-13 14:33:22 +0100243 resolved_method = reinterpret_cast<ArtMethod*>(tls_value);
244 } else {
245 ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
246 constexpr ClassLinker::ResolveMode resolve_mode =
247 do_access_check ? ClassLinker::ResolveMode::kCheckICCEAndIAE
248 : ClassLinker::ResolveMode::kNoChecks;
249 resolved_method = class_linker->ResolveMethod<resolve_mode>(self, method_idx, sf_method, type);
250 if (UNLIKELY(resolved_method == nullptr)) {
251 CHECK(self->IsExceptionPending());
252 result->SetJ(0);
253 return false;
254 }
Nicolas Geoffray00391822019-12-10 10:17:23 +0000255 if (!IsNterpSupported()) {
Hans Boehm3d2f1482022-01-17 01:32:55 +0000256 tls_cache->Set(inst, reinterpret_cast<size_t>(resolved_method));
Nicolas Geoffray00391822019-12-10 10:17:23 +0000257 }
David Srbeckyc853eed2018-09-13 14:33:22 +0100258 }
259
260 // Null pointer check and virtual method resolution.
Roland Levillain2ae376f2018-01-30 11:35:11 +0000261 ObjPtr<mirror::Object> receiver =
262 (type == kStatic) ? nullptr : shadow_frame.GetVRegReference(vregC);
David Srbecky08cb7382018-10-30 09:27:59 +0000263 ArtMethod* called_method;
David Srbeckydfe55442021-03-18 11:46:27 +0000264 called_method = FindMethodToCall<type, do_access_check>(
265 method_idx, resolved_method, &receiver, sf_method, self);
Ian Rogerse94652f2014-12-02 11:13:19 -0800266 if (UNLIKELY(called_method == nullptr)) {
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200267 CHECK(self->IsExceptionPending());
268 result->SetJ(0);
269 return false;
David Srbecky1f5ab4e2018-10-15 11:46:46 +0100270 }
271 if (UNLIKELY(!called_method->IsInvokable())) {
Alex Light9139e002015-10-09 15:59:48 -0700272 called_method->ThrowInvocationTimeError();
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200273 result->SetJ(0);
274 return false;
David Srbecky1f5ab4e2018-10-15 11:46:46 +0100275 }
276
277 jit::Jit* jit = Runtime::Current()->GetJit();
David Srbecky1f5ab4e2018-10-15 11:46:46 +0100278 if (is_mterp && !is_range && called_method->IsIntrinsic()) {
David Srbecky6c444482018-10-17 15:15:19 +0100279 if (MterpHandleIntrinsic(&shadow_frame, called_method, inst, inst_data,
280 shadow_frame.GetResultRegister())) {
281 if (jit != nullptr && sf_method != nullptr) {
282 jit->NotifyInterpreterToCompiledCodeTransition(self, sf_method);
David Srbecky6849c062018-09-21 09:42:24 +0100283 }
David Srbecky6c444482018-10-17 15:15:19 +0100284 return !self->IsExceptionPending();
Nicolas Geoffray5550ca82015-08-21 18:38:30 +0100285 }
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200286 }
David Srbecky1f5ab4e2018-10-15 11:46:46 +0100287
288 return DoCall<is_range, do_access_check>(called_method, self, shadow_frame, inst, inst_data,
289 result);
Sebastien Hertzc61124b2013-09-10 11:44:19 +0200290}
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200291
Vladimir Markoaf940202017-12-08 15:01:18 +0000292static inline ObjPtr<mirror::MethodHandle> ResolveMethodHandle(Thread* self,
293 uint32_t method_handle_index,
294 ArtMethod* referrer)
Orion Hodson2e599942017-09-22 16:17:41 +0100295 REQUIRES_SHARED(Locks::mutator_lock_) {
296 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Orion Hodsone7732be2017-10-11 14:35:20 +0100297 return class_linker->ResolveMethodHandle(self, method_handle_index, referrer);
Orion Hodson2e599942017-09-22 16:17:41 +0100298}
299
Vladimir Markoaf940202017-12-08 15:01:18 +0000300static inline ObjPtr<mirror::MethodType> ResolveMethodType(Thread* self,
Orion Hodson06d10a72018-05-14 08:53:38 +0100301 dex::ProtoIndex method_type_index,
Vladimir Markoaf940202017-12-08 15:01:18 +0000302 ArtMethod* referrer)
Orion Hodson2e599942017-09-22 16:17:41 +0100303 REQUIRES_SHARED(Locks::mutator_lock_) {
304 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Orion Hodsone7732be2017-10-11 14:35:20 +0100305 return class_linker->ResolveMethodType(self, method_type_index, referrer);
Orion Hodson2e599942017-09-22 16:17:41 +0100306}
307
Orion Hodson43f0cdb2017-10-10 14:47:32 +0100308#define DECLARE_SIGNATURE_POLYMORPHIC_HANDLER(Name, ...) \
309bool Do ## Name(Thread* self, \
310 ShadowFrame& shadow_frame, \
311 const Instruction* inst, \
312 uint16_t inst_data, \
313 JValue* result) REQUIRES_SHARED(Locks::mutator_lock_);
314#include "intrinsics_list.h"
315INTRINSICS_LIST(DECLARE_SIGNATURE_POLYMORPHIC_HANDLER)
316#undef INTRINSICS_LIST
317#undef DECLARE_SIGNATURE_POLYMORPHIC_HANDLER
318
319// Performs a invoke-polymorphic or invoke-polymorphic-range.
Orion Hodsonc069a302017-01-18 09:23:12 +0000320template<bool is_range>
Orion Hodson811bd5f2016-12-07 11:35:37 +0000321bool DoInvokePolymorphic(Thread* self,
322 ShadowFrame& shadow_frame,
323 const Instruction* inst,
324 uint16_t inst_data,
Orion Hodson4c8e12e2018-05-18 08:33:20 +0100325 JValue* result)
326 REQUIRES_SHARED(Locks::mutator_lock_);
327
328bool DoInvokeCustom(Thread* self,
329 ShadowFrame& shadow_frame,
330 uint32_t call_site_idx,
331 const InstructionOperands* operands,
332 JValue* result)
333 REQUIRES_SHARED(Locks::mutator_lock_);
Narayan Kamath9823e782016-08-03 12:46:58 +0100334
Orion Hodsonc069a302017-01-18 09:23:12 +0000335// Performs a custom invoke (invoke-custom/invoke-custom-range).
336template<bool is_range>
337bool DoInvokeCustom(Thread* self,
338 ShadowFrame& shadow_frame,
339 const Instruction* inst,
340 uint16_t inst_data,
Orion Hodson4c8e12e2018-05-18 08:33:20 +0100341 JValue* result)
342 REQUIRES_SHARED(Locks::mutator_lock_) {
343 const uint32_t call_site_idx = is_range ? inst->VRegB_3rc() : inst->VRegB_35c();
344 if (is_range) {
345 RangeInstructionOperands operands(inst->VRegC_3rc(), inst->VRegA_3rc());
346 return DoInvokeCustom(self, shadow_frame, call_site_idx, &operands, result);
347 } else {
348 uint32_t args[Instruction::kMaxVarArgRegs];
349 inst->GetVarArgs(args, inst_data);
350 VarArgsInstructionOperands operands(args, inst->VRegA_35c());
351 return DoInvokeCustom(self, shadow_frame, call_site_idx, &operands, result);
352 }
353}
Orion Hodsonc069a302017-01-18 09:23:12 +0000354
David Srbeckyf56393c2019-08-02 15:49:27 +0100355template<Primitive::Type field_type>
356ALWAYS_INLINE static JValue GetFieldValue(const ShadowFrame& shadow_frame, uint32_t vreg)
357 REQUIRES_SHARED(Locks::mutator_lock_) {
358 JValue field_value;
359 switch (field_type) {
360 case Primitive::kPrimBoolean:
361 field_value.SetZ(static_cast<uint8_t>(shadow_frame.GetVReg(vreg)));
362 break;
363 case Primitive::kPrimByte:
364 field_value.SetB(static_cast<int8_t>(shadow_frame.GetVReg(vreg)));
365 break;
366 case Primitive::kPrimChar:
367 field_value.SetC(static_cast<uint16_t>(shadow_frame.GetVReg(vreg)));
368 break;
369 case Primitive::kPrimShort:
370 field_value.SetS(static_cast<int16_t>(shadow_frame.GetVReg(vreg)));
371 break;
372 case Primitive::kPrimInt:
373 field_value.SetI(shadow_frame.GetVReg(vreg));
374 break;
375 case Primitive::kPrimLong:
376 field_value.SetJ(shadow_frame.GetVRegLong(vreg));
377 break;
378 case Primitive::kPrimNot:
379 field_value.SetL(shadow_frame.GetVRegReference(vreg));
380 break;
381 default:
382 LOG(FATAL) << "Unreachable: " << field_type;
383 UNREACHABLE();
384 }
385 return field_value;
386}
387
Sebastien Hertzc6714852013-09-30 16:42:32 +0200388// Handles iget-XXX and sget-XXX instructions.
389// Returns true on success, otherwise throws an exception and returns false.
Chang Xingbd208d82017-07-12 14:53:17 -0700390template<FindFieldType find_type, Primitive::Type field_type, bool do_access_check,
391 bool transaction_active = false>
David Srbeckyf56393c2019-08-02 15:49:27 +0100392ALWAYS_INLINE bool DoFieldGet(Thread* self, ShadowFrame& shadow_frame, const Instruction* inst,
393 uint16_t inst_data) REQUIRES_SHARED(Locks::mutator_lock_) {
394 const bool is_static = (find_type == StaticObjectRead) || (find_type == StaticPrimitiveRead);
395 const uint32_t field_idx = is_static ? inst->VRegB_21c() : inst->VRegC_22c();
396 ArtField* f =
397 FindFieldFromCode<find_type, do_access_check>(field_idx, shadow_frame.GetMethod(), self,
398 Primitive::ComponentSize(field_type));
399 if (UNLIKELY(f == nullptr)) {
400 CHECK(self->IsExceptionPending());
401 return false;
402 }
403 ObjPtr<mirror::Object> obj;
404 if (is_static) {
405 obj = f->GetDeclaringClass();
406 if (transaction_active) {
Vladimir Marko24c080f2021-07-06 14:04:30 +0100407 if (Runtime::Current()->GetTransaction()->ReadConstraint(obj)) {
David Srbeckyf56393c2019-08-02 15:49:27 +0100408 Runtime::Current()->AbortTransactionAndThrowAbortError(self, "Can't read static fields of "
409 + obj->PrettyTypeOf() + " since it does not belong to clinit's class.");
410 return false;
411 }
412 }
413 } else {
414 obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
415 if (UNLIKELY(obj == nullptr)) {
416 ThrowNullPointerExceptionForFieldAccess(f, true);
417 return false;
418 }
419 }
420
421 JValue result;
422 if (UNLIKELY(!DoFieldGetCommon<field_type>(self, shadow_frame, obj, f, &result))) {
423 // Instrumentation threw an error!
424 CHECK(self->IsExceptionPending());
425 return false;
426 }
427 uint32_t vregA = is_static ? inst->VRegA_21c(inst_data) : inst->VRegA_22c(inst_data);
428 switch (field_type) {
429 case Primitive::kPrimBoolean:
430 shadow_frame.SetVReg(vregA, result.GetZ());
431 break;
432 case Primitive::kPrimByte:
433 shadow_frame.SetVReg(vregA, result.GetB());
434 break;
435 case Primitive::kPrimChar:
436 shadow_frame.SetVReg(vregA, result.GetC());
437 break;
438 case Primitive::kPrimShort:
439 shadow_frame.SetVReg(vregA, result.GetS());
440 break;
441 case Primitive::kPrimInt:
442 shadow_frame.SetVReg(vregA, result.GetI());
443 break;
444 case Primitive::kPrimLong:
445 shadow_frame.SetVRegLong(vregA, result.GetJ());
446 break;
447 case Primitive::kPrimNot:
448 shadow_frame.SetVRegReference(vregA, result.GetL());
449 break;
450 default:
451 LOG(FATAL) << "Unreachable: " << field_type;
452 UNREACHABLE();
453 }
454 return true;
455}
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200456
Vladimir Marko4d7b6892020-01-16 17:06:35 +0000457static inline bool CheckWriteConstraint(Thread* self, ObjPtr<mirror::Object> obj)
458 REQUIRES_SHARED(Locks::mutator_lock_) {
459 Runtime* runtime = Runtime::Current();
Vladimir Marko24c080f2021-07-06 14:04:30 +0100460 if (runtime->GetTransaction()->WriteConstraint(obj)) {
Vladimir Marko4d7b6892020-01-16 17:06:35 +0000461 DCHECK(runtime->GetHeap()->ObjectIsInBootImageSpace(obj) || obj->IsClass());
462 const char* base_msg = runtime->GetHeap()->ObjectIsInBootImageSpace(obj)
463 ? "Can't set fields of boot image "
464 : "Can't set fields of ";
465 runtime->AbortTransactionAndThrowAbortError(self, base_msg + obj->PrettyTypeOf());
466 return false;
467 }
468 return true;
469}
470
Vladimir Marko149cdda2019-11-12 15:02:51 +0000471static inline bool CheckWriteValueConstraint(Thread* self, ObjPtr<mirror::Object> value)
472 REQUIRES_SHARED(Locks::mutator_lock_) {
473 Runtime* runtime = Runtime::Current();
Vladimir Marko24c080f2021-07-06 14:04:30 +0100474 if (runtime->GetTransaction()->WriteValueConstraint(value)) {
Vladimir Marko149cdda2019-11-12 15:02:51 +0000475 DCHECK(value != nullptr);
476 std::string msg = value->IsClass()
477 ? "Can't store reference to class " + value->AsClass()->PrettyDescriptor()
478 : "Can't store reference to instance of " + value->GetClass()->PrettyDescriptor();
479 runtime->AbortTransactionAndThrowAbortError(self, msg);
480 return false;
481 }
482 return true;
483}
484
Sebastien Hertzc6714852013-09-30 16:42:32 +0200485// Handles iput-XXX and sput-XXX instructions.
486// Returns true on success, otherwise throws an exception and returns false.
Ian Rogers54874942014-06-10 16:31:03 -0700487template<FindFieldType find_type, Primitive::Type field_type, bool do_access_check,
488 bool transaction_active>
David Srbeckyf56393c2019-08-02 15:49:27 +0100489ALWAYS_INLINE bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame,
490 const Instruction* inst, uint16_t inst_data)
491 REQUIRES_SHARED(Locks::mutator_lock_) {
492 const bool do_assignability_check = do_access_check;
493 bool is_static = (find_type == StaticObjectWrite) || (find_type == StaticPrimitiveWrite);
494 uint32_t field_idx = is_static ? inst->VRegB_21c() : inst->VRegC_22c();
495 ArtField* f =
496 FindFieldFromCode<find_type, do_access_check>(field_idx, shadow_frame.GetMethod(), self,
497 Primitive::ComponentSize(field_type));
498 if (UNLIKELY(f == nullptr)) {
499 CHECK(self->IsExceptionPending());
500 return false;
501 }
502 ObjPtr<mirror::Object> obj;
503 if (is_static) {
504 obj = f->GetDeclaringClass();
505 } else {
506 obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
507 if (UNLIKELY(obj == nullptr)) {
508 ThrowNullPointerExceptionForFieldAccess(f, false);
509 return false;
510 }
511 }
Vladimir Marko4d7b6892020-01-16 17:06:35 +0000512 if (transaction_active && !CheckWriteConstraint(self, obj)) {
513 return false;
David Srbeckyf56393c2019-08-02 15:49:27 +0100514 }
515
516 uint32_t vregA = is_static ? inst->VRegA_21c(inst_data) : inst->VRegA_22c(inst_data);
517 JValue value = GetFieldValue<field_type>(shadow_frame, vregA);
Vladimir Marko149cdda2019-11-12 15:02:51 +0000518
519 if (transaction_active &&
520 field_type == Primitive::kPrimNot &&
521 !CheckWriteValueConstraint(self, value.GetL())) {
522 return false;
523 }
524
David Srbeckyf56393c2019-08-02 15:49:27 +0100525 return DoFieldPutCommon<field_type, do_assignability_check, transaction_active>(self,
526 shadow_frame,
527 obj,
528 f,
529 value);
530}
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200531
Sebastien Hertzc6714852013-09-30 16:42:32 +0200532// Handles string resolution for const-string and const-string-jumbo instructions. Also ensures the
533// java.lang.String class is initialized.
Mathieu Chartieref41db72016-10-25 15:08:01 -0700534static inline ObjPtr<mirror::String> ResolveString(Thread* self,
535 ShadowFrame& shadow_frame,
Andreas Gampe8a0128a2016-11-28 07:38:35 -0800536 dex::StringIndex string_idx)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700537 REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Markoacb906d2018-05-30 10:23:49 +0100538 ObjPtr<mirror::Class> java_lang_string_class = GetClassRoot<mirror::String>();
Vladimir Markobaa81b52019-08-02 10:14:04 +0100539 if (UNLIKELY(!java_lang_string_class->IsVisiblyInitialized())) {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700540 StackHandleScope<1> hs(self);
541 Handle<mirror::Class> h_class(hs.NewHandle(java_lang_string_class));
Vladimir Markobaa81b52019-08-02 10:14:04 +0100542 if (UNLIKELY(!Runtime::Current()->GetClassLinker()->EnsureInitialized(
543 self, h_class, /*can_init_fields=*/ true, /*can_init_parents=*/ true))) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200544 DCHECK(self->IsExceptionPending());
Mathieu Chartierc528dba2013-11-26 12:00:11 -0800545 return nullptr;
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200546 }
Vladimir Markobaa81b52019-08-02 10:14:04 +0100547 DCHECK(h_class->IsInitializing());
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200548 }
Mathieu Chartiere401d142015-04-22 13:56:20 -0700549 ArtMethod* method = shadow_frame.GetMethod();
Vladimir Marko18090d12018-06-01 16:53:12 +0100550 ObjPtr<mirror::String> string_ptr =
551 Runtime::Current()->GetClassLinker()->ResolveString(string_idx, method);
Christina Wadsworthbf44e0e2016-08-18 10:37:42 -0700552 return string_ptr;
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200553}
554
Sebastien Hertzc6714852013-09-30 16:42:32 +0200555// Handles div-int, div-int/2addr, div-int/li16 and div-int/lit8 instructions.
556// Returns true on success, otherwise throws a java.lang.ArithmeticException and return false.
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200557static inline bool DoIntDivide(ShadowFrame& shadow_frame, size_t result_reg,
558 int32_t dividend, int32_t divisor)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700559 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersf72a11d2014-10-30 15:41:08 -0700560 constexpr int32_t kMinInt = std::numeric_limits<int32_t>::min();
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200561 if (UNLIKELY(divisor == 0)) {
562 ThrowArithmeticExceptionDivideByZero();
563 return false;
564 }
565 if (UNLIKELY(dividend == kMinInt && divisor == -1)) {
566 shadow_frame.SetVReg(result_reg, kMinInt);
567 } else {
568 shadow_frame.SetVReg(result_reg, dividend / divisor);
569 }
570 return true;
571}
572
Sebastien Hertzc6714852013-09-30 16:42:32 +0200573// Handles rem-int, rem-int/2addr, rem-int/li16 and rem-int/lit8 instructions.
574// Returns true on success, otherwise throws a java.lang.ArithmeticException and return false.
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200575static inline bool DoIntRemainder(ShadowFrame& shadow_frame, size_t result_reg,
576 int32_t dividend, int32_t divisor)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700577 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogersf72a11d2014-10-30 15:41:08 -0700578 constexpr int32_t kMinInt = std::numeric_limits<int32_t>::min();
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200579 if (UNLIKELY(divisor == 0)) {
580 ThrowArithmeticExceptionDivideByZero();
581 return false;
582 }
583 if (UNLIKELY(dividend == kMinInt && divisor == -1)) {
584 shadow_frame.SetVReg(result_reg, 0);
585 } else {
586 shadow_frame.SetVReg(result_reg, dividend % divisor);
587 }
588 return true;
589}
590
Sebastien Hertzc6714852013-09-30 16:42:32 +0200591// Handles div-long and div-long-2addr instructions.
592// Returns true on success, otherwise throws a java.lang.ArithmeticException and return false.
Mathieu Chartieref41db72016-10-25 15:08:01 -0700593static inline bool DoLongDivide(ShadowFrame& shadow_frame,
594 size_t result_reg,
595 int64_t dividend,
596 int64_t divisor)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700597 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers2e2deeb2013-09-23 11:58:57 -0700598 const int64_t kMinLong = std::numeric_limits<int64_t>::min();
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200599 if (UNLIKELY(divisor == 0)) {
600 ThrowArithmeticExceptionDivideByZero();
601 return false;
602 }
603 if (UNLIKELY(dividend == kMinLong && divisor == -1)) {
604 shadow_frame.SetVRegLong(result_reg, kMinLong);
605 } else {
606 shadow_frame.SetVRegLong(result_reg, dividend / divisor);
607 }
608 return true;
609}
610
Sebastien Hertzc6714852013-09-30 16:42:32 +0200611// Handles rem-long and rem-long-2addr instructions.
612// Returns true on success, otherwise throws a java.lang.ArithmeticException and return false.
Mathieu Chartieref41db72016-10-25 15:08:01 -0700613static inline bool DoLongRemainder(ShadowFrame& shadow_frame,
614 size_t result_reg,
615 int64_t dividend,
616 int64_t divisor)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700617 REQUIRES_SHARED(Locks::mutator_lock_) {
Ian Rogers2e2deeb2013-09-23 11:58:57 -0700618 const int64_t kMinLong = std::numeric_limits<int64_t>::min();
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200619 if (UNLIKELY(divisor == 0)) {
620 ThrowArithmeticExceptionDivideByZero();
621 return false;
622 }
623 if (UNLIKELY(dividend == kMinLong && divisor == -1)) {
624 shadow_frame.SetVRegLong(result_reg, 0);
625 } else {
626 shadow_frame.SetVRegLong(result_reg, dividend % divisor);
627 }
628 return true;
629}
630
Sebastien Hertzc6714852013-09-30 16:42:32 +0200631// Handles filled-new-array and filled-new-array-range instructions.
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200632// Returns true on success, otherwise throws an exception and returns false.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100633template <bool is_range, bool do_access_check, bool transaction_active>
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200634bool DoFilledNewArray(const Instruction* inst, const ShadowFrame& shadow_frame,
Sebastien Hertzc6714852013-09-30 16:42:32 +0200635 Thread* self, JValue* result);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200636
Sebastien Hertzc6714852013-09-30 16:42:32 +0200637// Handles packed-switch instruction.
638// Returns the branch offset to the next instruction to execute.
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200639static inline int32_t DoPackedSwitch(const Instruction* inst, const ShadowFrame& shadow_frame,
640 uint16_t inst_data)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700641 REQUIRES_SHARED(Locks::mutator_lock_) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200642 DCHECK(inst->Opcode() == Instruction::PACKED_SWITCH);
643 const uint16_t* switch_data = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200644 int32_t test_val = shadow_frame.GetVReg(inst->VRegA_31t(inst_data));
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200645 DCHECK_EQ(switch_data[0], static_cast<uint16_t>(Instruction::kPackedSwitchSignature));
646 uint16_t size = switch_data[1];
David Brazdil2ef645b2015-06-17 18:20:52 +0100647 if (size == 0) {
648 // Empty packed switch, move forward by 3 (size of PACKED_SWITCH).
649 return 3;
650 }
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200651 const int32_t* keys = reinterpret_cast<const int32_t*>(&switch_data[2]);
Roland Levillain14d90572015-07-16 10:52:26 +0100652 DCHECK_ALIGNED(keys, 4);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200653 int32_t first_key = keys[0];
654 const int32_t* targets = reinterpret_cast<const int32_t*>(&switch_data[4]);
Roland Levillain14d90572015-07-16 10:52:26 +0100655 DCHECK_ALIGNED(targets, 4);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200656 int32_t index = test_val - first_key;
657 if (index >= 0 && index < size) {
658 return targets[index];
659 } else {
660 // No corresponding value: move forward by 3 (size of PACKED_SWITCH).
661 return 3;
662 }
663}
664
Sebastien Hertzc6714852013-09-30 16:42:32 +0200665// Handles sparse-switch instruction.
666// Returns the branch offset to the next instruction to execute.
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200667static inline int32_t DoSparseSwitch(const Instruction* inst, const ShadowFrame& shadow_frame,
668 uint16_t inst_data)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700669 REQUIRES_SHARED(Locks::mutator_lock_) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200670 DCHECK(inst->Opcode() == Instruction::SPARSE_SWITCH);
671 const uint16_t* switch_data = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
Sebastien Hertz3b588e02013-09-11 14:33:18 +0200672 int32_t test_val = shadow_frame.GetVReg(inst->VRegA_31t(inst_data));
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200673 DCHECK_EQ(switch_data[0], static_cast<uint16_t>(Instruction::kSparseSwitchSignature));
674 uint16_t size = switch_data[1];
Jeff Hao935e01a2015-03-20 19:44:35 -0700675 // Return length of SPARSE_SWITCH if size is 0.
676 if (size == 0) {
677 return 3;
678 }
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200679 const int32_t* keys = reinterpret_cast<const int32_t*>(&switch_data[2]);
Roland Levillain14d90572015-07-16 10:52:26 +0100680 DCHECK_ALIGNED(keys, 4);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200681 const int32_t* entries = keys + size;
Roland Levillain14d90572015-07-16 10:52:26 +0100682 DCHECK_ALIGNED(entries, 4);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200683 int lo = 0;
684 int hi = size - 1;
685 while (lo <= hi) {
686 int mid = (lo + hi) / 2;
687 int32_t foundVal = keys[mid];
688 if (test_val < foundVal) {
689 hi = mid - 1;
690 } else if (test_val > foundVal) {
691 lo = mid + 1;
692 } else {
693 return entries[mid];
694 }
695 }
696 // No corresponding value: move forward by 3 (size of SPARSE_SWITCH).
697 return 3;
698}
699
Alex Light9fb1ab12017-09-05 09:32:49 -0700700// We execute any instrumentation events triggered by throwing and/or handing the pending exception
701// and change the shadow_frames dex_pc to the appropriate exception handler if the current method
702// has one. If the exception has been handled and the shadow_frame is now pointing to a catch clause
703// we return true. If the current method is unable to handle the exception we return false.
704// This function accepts a null Instrumentation* as a way to cause instrumentation events not to be
705// reported.
706// TODO We might wish to reconsider how we cause some events to be ignored.
707bool MoveToExceptionHandler(Thread* self,
708 ShadowFrame& shadow_frame,
709 const instrumentation::Instrumentation* instrumentation)
710 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200711
Andreas Gampe794ad762015-02-23 08:12:24 -0800712NO_RETURN void UnexpectedOpcode(const Instruction* inst, const ShadowFrame& shadow_frame)
713 __attribute__((cold))
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700714 REQUIRES_SHARED(Locks::mutator_lock_);
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200715
Bill Buzbeed47fd902016-07-07 14:42:43 +0000716// Set true if you want TraceExecution invocation before each bytecode execution.
717constexpr bool kTraceExecutionEnabled = false;
Serguei Katkov9fb0ac72016-02-20 12:55:24 +0600718
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200719static inline void TraceExecution(const ShadowFrame& shadow_frame, const Instruction* inst,
Ian Rogerse94652f2014-12-02 11:13:19 -0800720 const uint32_t dex_pc)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700721 REQUIRES_SHARED(Locks::mutator_lock_) {
Bill Buzbeed47fd902016-07-07 14:42:43 +0000722 if (kTraceExecutionEnabled) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200723#define TRACE_LOG std::cerr
Mathieu Chartiere861ebd2013-10-09 15:01:21 -0700724 std::ostringstream oss;
David Sehr709b0702016-10-13 09:12:37 -0700725 oss << shadow_frame.GetMethod()->PrettyMethod()
Andreas Gampe46ee31b2016-12-14 10:11:49 -0800726 << android::base::StringPrintf("\n0x%x: ", dex_pc)
Ian Rogerse94652f2014-12-02 11:13:19 -0800727 << inst->DumpString(shadow_frame.GetMethod()->GetDexFile()) << "\n";
Ian Rogersef7d42f2014-01-06 12:55:46 -0800728 for (uint32_t i = 0; i < shadow_frame.NumberOfVRegs(); ++i) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200729 uint32_t raw_value = shadow_frame.GetVReg(i);
Mathieu Chartieref41db72016-10-25 15:08:01 -0700730 ObjPtr<mirror::Object> ref_value = shadow_frame.GetVRegReference(i);
Andreas Gampe46ee31b2016-12-14 10:11:49 -0800731 oss << android::base::StringPrintf(" vreg%u=0x%08X", i, raw_value);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700732 if (ref_value != nullptr) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200733 if (ref_value->GetClass()->IsStringClass() &&
jessicahandojo3aaa37b2016-07-29 14:46:37 -0700734 !ref_value->AsString()->IsValueNull()) {
Mathieu Chartiere861ebd2013-10-09 15:01:21 -0700735 oss << "/java.lang.String \"" << ref_value->AsString()->ToModifiedUtf8() << "\"";
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200736 } else {
David Sehr709b0702016-10-13 09:12:37 -0700737 oss << "/" << ref_value->PrettyTypeOf();
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200738 }
739 }
740 }
Mathieu Chartiere861ebd2013-10-09 15:01:21 -0700741 TRACE_LOG << oss.str() << "\n";
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200742#undef TRACE_LOG
743 }
744}
745
Sebastien Hertz1eda2262013-09-09 16:53:14 +0200746static inline bool IsBackwardBranch(int32_t branch_offset) {
747 return branch_offset <= 0;
748}
749
Jeff Hao5ea84132017-05-05 16:59:29 -0700750// The arg_offset is the offset to the first input register in the frame.
Nicolas Geoffray71cd50f2016-04-14 15:00:33 +0100751void ArtInterpreterToCompiledCodeBridge(Thread* self,
752 ArtMethod* caller,
Nicolas Geoffray71cd50f2016-04-14 15:00:33 +0100753 ShadowFrame* shadow_frame,
Jeff Hao5ea84132017-05-05 16:59:29 -0700754 uint16_t arg_offset,
Nicolas Geoffray71cd50f2016-04-14 15:00:33 +0100755 JValue* result);
Siva Chandra05d24152016-01-05 17:43:17 -0800756
Mingyao Yang2ee17902017-08-30 11:37:08 -0700757static inline bool IsStringInit(const DexFile* dex_file, uint32_t method_idx)
758 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe3f1dcd32018-12-28 09:39:56 -0800759 const dex::MethodId& method_id = dex_file->GetMethodId(method_idx);
Mingyao Yang2ee17902017-08-30 11:37:08 -0700760 const char* class_name = dex_file->StringByTypeIdx(method_id.class_idx_);
761 const char* method_name = dex_file->GetMethodName(method_id);
762 // Instead of calling ResolveMethod() which has suspend point and can trigger
763 // GC, look up the method symbolically.
764 // Compare method's class name and method name against string init.
765 // It's ok since it's not allowed to create your own java/lang/String.
766 // TODO: verify that assumption.
767 if ((strcmp(class_name, "Ljava/lang/String;") == 0) &&
768 (strcmp(method_name, "<init>") == 0)) {
769 return true;
770 }
771 return false;
772}
773
774static inline bool IsStringInit(const Instruction* instr, ArtMethod* caller)
775 REQUIRES_SHARED(Locks::mutator_lock_) {
776 if (instr->Opcode() == Instruction::INVOKE_DIRECT ||
777 instr->Opcode() == Instruction::INVOKE_DIRECT_RANGE) {
778 uint16_t callee_method_idx = (instr->Opcode() == Instruction::INVOKE_DIRECT_RANGE) ?
779 instr->VRegB_3rc() : instr->VRegB_35c();
780 return IsStringInit(caller->GetDexFile(), callee_method_idx);
781 }
782 return false;
783}
784
Mingyao Yangffedec52016-05-19 10:48:40 -0700785// Set string value created from StringFactory.newStringFromXXX() into all aliases of
786// StringFactory.newEmptyString().
787void SetStringInitValueToAllAliases(ShadowFrame* shadow_frame,
788 uint16_t this_obj_vreg,
789 JValue result);
790
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200791} // namespace interpreter
792} // namespace art
793
794#endif // ART_RUNTIME_INTERPRETER_INTERPRETER_COMMON_H_