blob: 56b84a0601d2a763c52f6f046bc13aca7bb4a86f [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
David Srbecky2ee09ff2018-10-24 13:24:22 +010017#ifndef ART_RUNTIME_INTERPRETER_INTERPRETER_SWITCH_IMPL_INL_H_
18#define ART_RUNTIME_INTERPRETER_INTERPRETER_SWITCH_IMPL_INL_H_
19
Andreas Gampe5e26eb12016-08-22 17:54:17 -070020#include "interpreter_switch_impl.h"
21
Andreas Gampe542451c2016-07-26 09:02:02 -070022#include "base/enums.h"
Alex Light49af7042019-05-29 18:30:33 -070023#include "base/globals.h"
Alex Light6f22e062018-10-05 15:05:12 -070024#include "base/memory_tool.h"
David Sehrc431b9d2018-03-02 12:01:51 -080025#include "base/quasi_atomic.h"
David Sehr9e734c72018-01-04 17:56:19 -080026#include "dex/dex_file_types.h"
David Srbecky6da82472018-10-23 14:03:08 +010027#include "dex/dex_instruction_list.h"
Alex Lighteb7c1442015-08-31 13:17:42 -070028#include "experimental_flags.h"
Alex Light49af7042019-05-29 18:30:33 -070029#include "handle_scope.h"
Sebastien Hertz8ece0502013-08-07 11:26:41 +020030#include "interpreter_common.h"
Alex Light49af7042019-05-29 18:30:33 -070031#include "interpreter/shadow_frame.h"
David Srbeckye3fc2d12018-11-30 13:41:14 +000032#include "jit/jit-inl.h"
Mathieu Chartier28bd2e42016-10-04 13:54:57 -070033#include "jvalue-inl.h"
Andreas Gampefd63bbf2018-10-29 12:55:35 -070034#include "mirror/string-alloc-inl.h"
Alex Light49af7042019-05-29 18:30:33 -070035#include "mirror/throwable.h"
Alex Lightb7c640d2019-03-20 15:52:13 -070036#include "monitor.h"
Alex Light0aa7a5a2018-10-10 15:58:14 +000037#include "nth_caller_visitor.h"
Ian Rogersf72a11d2014-10-30 15:41:08 -070038#include "safe_math.h"
Vladimir Marko6ec2a1b2018-05-22 15:33:48 +010039#include "shadow_frame-inl.h"
Alex Light0aa7a5a2018-10-10 15:58:14 +000040#include "thread.h"
Alex Light49af7042019-05-29 18:30:33 -070041#include "verifier/method_verifier.h"
Sebastien Hertz8ece0502013-08-07 11:26:41 +020042
43namespace art {
44namespace interpreter {
45
David Srbecky6da82472018-10-23 14:03:08 +010046// Short-lived helper class which executes single DEX bytecode. It is inlined by compiler.
David Srbecky8d335b62019-06-06 14:25:42 +010047// Any relevant execution information is stored in the fields - it should be kept to minimum.
48// All instance functions must be inlined so that the fields can be stored in registers.
David Srbecky6da82472018-10-23 14:03:08 +010049//
50// The function names must match the names from dex_instruction_list.h and have no arguments.
David Srbecky8d335b62019-06-06 14:25:42 +010051// Return value: The handlers must return false if the instruction throws or returns (exits).
David Srbecky47ad3762018-10-31 12:43:40 +000052//
David Srbecky436f6c12019-05-22 13:28:42 +010053template<bool do_access_check, bool transaction_active, Instruction::Format kFormat>
David Srbecky6da82472018-10-23 14:03:08 +010054class InstructionHandler {
55 public:
David Srbecky47ad3762018-10-31 12:43:40 +000056 ALWAYS_INLINE WARN_UNUSED bool CheckForceReturn()
57 REQUIRES_SHARED(Locks::mutator_lock_) {
Alex Lightb7c640d2019-03-20 15:52:13 -070058 if (PerformNonStandardReturn<kMonitorState>(self,
59 shadow_frame,
60 ctx->result,
61 instrumentation,
62 Accessor().InsSize(),
63 inst->GetDexPc(Insns()))) {
David Srbecky47ad3762018-10-31 12:43:40 +000064 exit_interpreter_loop = true;
65 return false;
66 }
67 return true;
68 }
69
David Srbecky8d335b62019-06-06 14:25:42 +010070 ALWAYS_INLINE WARN_UNUSED bool HandlePendingException()
David Srbecky47ad3762018-10-31 12:43:40 +000071 REQUIRES_SHARED(Locks::mutator_lock_) {
72 DCHECK(self->IsExceptionPending());
73 self->AllowThreadSuspension();
74 if (!CheckForceReturn()) {
75 return false;
76 }
David Srbecky8d335b62019-06-06 14:25:42 +010077 bool skip_event = shadow_frame.GetSkipNextExceptionEvent();
78 shadow_frame.SetSkipNextExceptionEvent(false);
79 if (!MoveToExceptionHandler(self, shadow_frame, skip_event ? nullptr : instrumentation)) {
David Srbecky47ad3762018-10-31 12:43:40 +000080 /* Structured locking is to be enforced for abnormal termination, too. */
81 DoMonitorCheckOnExit<do_assignability_check>(self, &shadow_frame);
David Srbecky47ad3762018-10-31 12:43:40 +000082 ctx->result = JValue(); /* Handled in caller. */
83 exit_interpreter_loop = true;
84 return false; // Return to caller.
85 }
86 if (!CheckForceReturn()) {
87 return false;
88 }
89 int32_t displacement =
90 static_cast<int32_t>(shadow_frame.GetDexPC()) - static_cast<int32_t>(dex_pc);
David Srbecky8867f3b2019-05-31 20:01:46 +010091 SetNextInstruction(inst->RelativeAt(displacement));
David Srbecky8d335b62019-06-06 14:25:42 +010092 return true;
David Srbecky47ad3762018-10-31 12:43:40 +000093 }
94
David Srbecky8d335b62019-06-06 14:25:42 +010095 ALWAYS_INLINE WARN_UNUSED bool PossiblyHandlePendingExceptionOnInvoke(bool is_exception_pending)
David Srbecky47ad3762018-10-31 12:43:40 +000096 REQUIRES_SHARED(Locks::mutator_lock_) {
97 if (UNLIKELY(shadow_frame.GetForceRetryInstruction())) {
98 /* Don't need to do anything except clear the flag and exception. We leave the */
99 /* instruction the same so it will be re-executed on the next go-around. */
100 DCHECK(inst->IsInvoke());
101 shadow_frame.SetForceRetryInstruction(false);
102 if (UNLIKELY(is_exception_pending)) {
103 DCHECK(self->IsExceptionPending());
104 if (kIsDebugBuild) {
105 LOG(WARNING) << "Suppressing exception for instruction-retry: "
106 << self->GetException()->Dump();
107 }
108 self->ClearException();
109 }
David Srbecky8867f3b2019-05-31 20:01:46 +0100110 SetNextInstruction(inst);
David Srbecky47ad3762018-10-31 12:43:40 +0000111 } else if (UNLIKELY(is_exception_pending)) {
112 /* Should have succeeded. */
113 DCHECK(!shadow_frame.GetForceRetryInstruction());
David Srbecky8d335b62019-06-06 14:25:42 +0100114 return false; // Pending exception.
David Srbecky47ad3762018-10-31 12:43:40 +0000115 }
116 return true;
117 }
118
119 ALWAYS_INLINE WARN_UNUSED bool HandleMonitorChecks()
120 REQUIRES_SHARED(Locks::mutator_lock_) {
121 if (!DoMonitorCheckOnExit<do_assignability_check>(self, &shadow_frame)) {
David Srbecky8d335b62019-06-06 14:25:42 +0100122 return false; // Pending exception.
David Srbecky47ad3762018-10-31 12:43:40 +0000123 }
124 return true;
125 }
126
127 // Code to run before each dex instruction.
David Srbeckya4a96af2018-10-31 16:34:58 +0000128 ALWAYS_INLINE WARN_UNUSED bool Preamble()
David Srbecky47ad3762018-10-31 12:43:40 +0000129 REQUIRES_SHARED(Locks::mutator_lock_) {
130 /* We need to put this before & after the instrumentation to avoid having to put in a */
131 /* post-script macro. */
132 if (!CheckForceReturn()) {
133 return false;
134 }
135 if (UNLIKELY(instrumentation->HasDexPcListeners())) {
David Srbeckya4a96af2018-10-31 16:34:58 +0000136 uint8_t opcode = inst->Opcode(inst_data);
137 bool is_move_result_object = (opcode == Instruction::MOVE_RESULT_OBJECT);
138 JValue* save_ref = is_move_result_object ? &ctx->result_register : nullptr;
David Srbecky47ad3762018-10-31 12:43:40 +0000139 if (UNLIKELY(!DoDexPcMoveEvent(self,
140 Accessor(),
141 shadow_frame,
142 dex_pc,
143 instrumentation,
144 save_ref))) {
David Srbecky8d335b62019-06-06 14:25:42 +0100145 DCHECK(self->IsExceptionPending());
146 // Do not raise exception event if it is caused by other instrumentation event.
147 shadow_frame.SetSkipNextExceptionEvent(true);
148 return false; // Pending exception.
David Srbecky47ad3762018-10-31 12:43:40 +0000149 }
150 if (!CheckForceReturn()) {
151 return false;
152 }
153 }
154 return true;
155 }
156
157 ALWAYS_INLINE WARN_UNUSED bool BranchInstrumentation(int32_t offset)
158 REQUIRES_SHARED(Locks::mutator_lock_) {
159 if (UNLIKELY(instrumentation->HasBranchListeners())) {
160 instrumentation->Branch(self, shadow_frame.GetMethod(), dex_pc, offset);
161 }
162 JValue result;
163 if (jit::Jit::MaybeDoOnStackReplacement(self,
164 shadow_frame.GetMethod(),
165 dex_pc,
166 offset,
167 &result)) {
David Srbecky47ad3762018-10-31 12:43:40 +0000168 ctx->result = result;
169 exit_interpreter_loop = true;
170 return false;
171 }
172 return true;
173 }
174
175 ALWAYS_INLINE void HotnessUpdate()
176 REQUIRES_SHARED(Locks::mutator_lock_) {
177 jit::Jit* jit = Runtime::Current()->GetJit();
178 if (jit != nullptr) {
179 jit->AddSamples(self, shadow_frame.GetMethod(), 1, /*with_backedges=*/ true);
180 }
181 }
182
183 ALWAYS_INLINE WARN_UNUSED bool HandleAsyncException()
184 REQUIRES_SHARED(Locks::mutator_lock_) {
185 if (UNLIKELY(self->ObserveAsyncException())) {
David Srbecky8d335b62019-06-06 14:25:42 +0100186 return false; // Pending exception.
David Srbecky47ad3762018-10-31 12:43:40 +0000187 }
188 return true;
189 }
190
191 ALWAYS_INLINE void HandleBackwardBranch(int32_t offset)
192 REQUIRES_SHARED(Locks::mutator_lock_) {
193 if (IsBackwardBranch(offset)) {
194 HotnessUpdate();
195 /* Record new dex pc early to have consistent suspend point at loop header. */
David Srbeckyc56a23e2019-06-05 17:45:49 +0100196 shadow_frame.SetDexPC(next->GetDexPc(Insns()));
David Srbecky47ad3762018-10-31 12:43:40 +0000197 self->AllowThreadSuspension();
198 }
199 }
200
201 // Unlike most other events the DexPcMovedEvent can be sent when there is a pending exception (if
202 // the next instruction is MOVE_EXCEPTION). This means it needs to be handled carefully to be able
203 // to detect exceptions thrown by the DexPcMovedEvent itself. These exceptions could be thrown by
204 // jvmti-agents while handling breakpoint or single step events. We had to move this into its own
205 // function because it was making ExecuteSwitchImpl have too large a stack.
206 NO_INLINE static bool DoDexPcMoveEvent(Thread* self,
207 const CodeItemDataAccessor& accessor,
208 const ShadowFrame& shadow_frame,
209 uint32_t dex_pc,
210 const instrumentation::Instrumentation* instrumentation,
211 JValue* save_ref)
212 REQUIRES_SHARED(Locks::mutator_lock_) {
213 DCHECK(instrumentation->HasDexPcListeners());
214 StackHandleScope<2> hs(self);
215 Handle<mirror::Throwable> thr(hs.NewHandle(self->GetException()));
216 mirror::Object* null_obj = nullptr;
217 HandleWrapper<mirror::Object> h(
218 hs.NewHandleWrapper(LIKELY(save_ref == nullptr) ? &null_obj : save_ref->GetGCRoot()));
219 self->ClearException();
220 instrumentation->DexPcMovedEvent(self,
221 shadow_frame.GetThisObject(accessor.InsSize()),
222 shadow_frame.GetMethod(),
223 dex_pc);
224 if (UNLIKELY(self->IsExceptionPending())) {
225 // We got a new exception in the dex-pc-moved event.
226 // We just let this exception replace the old one.
227 // TODO It would be good to add the old exception to the
228 // suppressed exceptions of the new one if possible.
David Srbecky8d335b62019-06-06 14:25:42 +0100229 return false; // Pending exception.
David Srbecky47ad3762018-10-31 12:43:40 +0000230 } else {
231 if (UNLIKELY(!thr.IsNull())) {
232 self->SetException(thr.Get());
233 }
234 return true;
235 }
236 }
237
David Srbeckyee12e3a2019-06-03 15:18:57 +0100238 ALWAYS_INLINE WARN_UNUSED bool HandleReturn(JValue result) REQUIRES_SHARED(Locks::mutator_lock_) {
239 self->AllowThreadSuspension();
240 if (!HandleMonitorChecks()) {
241 return false;
242 }
243 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
244 !SendMethodExitEvents(self,
245 instrumentation,
246 shadow_frame,
247 shadow_frame.GetThisObject(Accessor().InsSize()),
248 shadow_frame.GetMethod(),
249 inst->GetDexPc(Insns()),
250 result))) {
David Srbecky8d335b62019-06-06 14:25:42 +0100251 DCHECK(self->IsExceptionPending());
252 // Do not raise exception event if it is caused by other instrumentation event.
253 shadow_frame.SetSkipNextExceptionEvent(true);
254 return false; // Pending exception.
David Srbeckyee12e3a2019-06-03 15:18:57 +0100255 }
256 ctx->result = result;
257 exit_interpreter_loop = true;
David Srbecky8d335b62019-06-06 14:25:42 +0100258 return false;
David Srbeckyee12e3a2019-06-03 15:18:57 +0100259 }
260
261 ALWAYS_INLINE WARN_UNUSED bool HandleGoto(int32_t offset) REQUIRES_SHARED(Locks::mutator_lock_) {
262 if (!HandleAsyncException()) {
263 return false;
264 }
David Srbecky8d335b62019-06-06 14:25:42 +0100265 if (!BranchInstrumentation(offset)) {
266 return false;
267 }
David Srbecky8867f3b2019-05-31 20:01:46 +0100268 SetNextInstruction(inst->RelativeAt(offset));
David Srbeckyee12e3a2019-06-03 15:18:57 +0100269 HandleBackwardBranch(offset);
270 return true;
271 }
272
273#pragma clang diagnostic push
274#pragma clang diagnostic ignored "-Wfloat-equal"
275
276 template<typename T>
277 ALWAYS_INLINE WARN_UNUSED bool HandleCmpl(T val1, T val2) REQUIRES_SHARED(Locks::mutator_lock_) {
278 int32_t result;
279 if (val1 > val2) {
280 result = 1;
281 } else if (val1 == val2) {
282 result = 0;
283 } else {
284 result = -1;
285 }
286 SetVReg(A(), result);
David Srbeckyee12e3a2019-06-03 15:18:57 +0100287 return true;
288 }
289
290 // Returns the same result as the function above. It only differs for NaN values.
291 template<typename T>
292 ALWAYS_INLINE WARN_UNUSED bool HandleCmpg(T val1, T val2) REQUIRES_SHARED(Locks::mutator_lock_) {
293 int32_t result;
294 if (val1 < val2) {
295 result = -1;
296 } else if (val1 == val2) {
297 result = 0;
298 } else {
299 result = 1;
300 }
301 SetVReg(A(), result);
David Srbeckyee12e3a2019-06-03 15:18:57 +0100302 return true;
303 }
304
305#pragma clang diagnostic pop
306
307 ALWAYS_INLINE WARN_UNUSED bool HandleIf(bool cond, int32_t offset)
308 REQUIRES_SHARED(Locks::mutator_lock_) {
309 if (cond) {
David Srbecky8d335b62019-06-06 14:25:42 +0100310 if (!BranchInstrumentation(offset)) {
311 return false;
312 }
David Srbecky8867f3b2019-05-31 20:01:46 +0100313 SetNextInstruction(inst->RelativeAt(offset));
David Srbeckyee12e3a2019-06-03 15:18:57 +0100314 HandleBackwardBranch(offset);
315 } else {
David Srbecky8d335b62019-06-06 14:25:42 +0100316 if (!BranchInstrumentation(2)) {
317 return false;
318 }
David Srbeckyee12e3a2019-06-03 15:18:57 +0100319 }
320 return true;
321 }
322
David Srbecky1332c262019-06-04 13:13:37 +0100323 template<typename ArrayType, typename SetVRegFn>
324 ALWAYS_INLINE bool HandleAGet(SetVRegFn setVReg) REQUIRES_SHARED(Locks::mutator_lock_) {
325 ObjPtr<mirror::Object> a = GetVRegReference(B());
326 if (UNLIKELY(a == nullptr)) {
327 ThrowNullPointerExceptionFromInterpreter();
David Srbecky8d335b62019-06-06 14:25:42 +0100328 return false; // Pending exception.
David Srbecky1332c262019-06-04 13:13:37 +0100329 }
330 int32_t index = GetVReg(C());
331 ObjPtr<ArrayType> array = ObjPtr<ArrayType>::DownCast(a);
332 if (UNLIKELY(!array->CheckIsValidIndex(index))) {
David Srbecky8d335b62019-06-06 14:25:42 +0100333 return false; // Pending exception.
David Srbecky1332c262019-06-04 13:13:37 +0100334 } else {
335 (this->*setVReg)(A(), array->GetWithoutChecks(index));
David Srbecky1332c262019-06-04 13:13:37 +0100336 }
337 return true;
338 }
339
340 template<typename ArrayType, typename T>
341 ALWAYS_INLINE bool HandleAPut(T value) REQUIRES_SHARED(Locks::mutator_lock_) {
342 ObjPtr<mirror::Object> a = GetVRegReference(B());
343 if (UNLIKELY(a == nullptr)) {
344 ThrowNullPointerExceptionFromInterpreter();
David Srbecky8d335b62019-06-06 14:25:42 +0100345 return false; // Pending exception.
David Srbecky1332c262019-06-04 13:13:37 +0100346 }
347 int32_t index = GetVReg(C());
348 ObjPtr<ArrayType> array = ObjPtr<ArrayType>::DownCast(a);
349 if (UNLIKELY(!array->CheckIsValidIndex(index))) {
David Srbecky8d335b62019-06-06 14:25:42 +0100350 return false; // Pending exception.
David Srbecky1332c262019-06-04 13:13:37 +0100351 } else {
352 array->template SetWithoutChecks<transaction_active>(index, value);
David Srbecky1332c262019-06-04 13:13:37 +0100353 }
354 return true;
355 }
356
David Srbeckyee12e3a2019-06-03 15:18:57 +0100357 template<FindFieldType find_type, Primitive::Type field_type>
358 ALWAYS_INLINE WARN_UNUSED bool HandleGet() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky8d335b62019-06-06 14:25:42 +0100359 return DoFieldGet<find_type, field_type, do_access_check, transaction_active>(
David Srbeckyee12e3a2019-06-03 15:18:57 +0100360 self, shadow_frame, inst, inst_data);
David Srbeckyee12e3a2019-06-03 15:18:57 +0100361 }
362
363 template<Primitive::Type field_type>
364 ALWAYS_INLINE WARN_UNUSED bool HandleGetQuick() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky8d335b62019-06-06 14:25:42 +0100365 return DoIGetQuick<field_type>(shadow_frame, inst, inst_data);
David Srbeckyee12e3a2019-06-03 15:18:57 +0100366 }
367
368 template<FindFieldType find_type, Primitive::Type field_type>
369 ALWAYS_INLINE WARN_UNUSED bool HandlePut() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky8d335b62019-06-06 14:25:42 +0100370 return DoFieldPut<find_type, field_type, do_access_check, transaction_active>(
David Srbeckyee12e3a2019-06-03 15:18:57 +0100371 self, shadow_frame, inst, inst_data);
David Srbeckyee12e3a2019-06-03 15:18:57 +0100372 }
373
374 template<Primitive::Type field_type>
375 ALWAYS_INLINE WARN_UNUSED bool HandlePutQuick() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky8d335b62019-06-06 14:25:42 +0100376 return DoIPutQuick<field_type, transaction_active>(
David Srbeckyee12e3a2019-06-03 15:18:57 +0100377 shadow_frame, inst, inst_data);
David Srbeckyee12e3a2019-06-03 15:18:57 +0100378 }
379
380 template<InvokeType type, bool is_range, bool is_quick = false>
381 ALWAYS_INLINE WARN_UNUSED bool HandleInvoke() REQUIRES_SHARED(Locks::mutator_lock_) {
382 bool success = DoInvoke<type, is_range, do_access_check, /*is_mterp=*/ false, is_quick>(
383 self, shadow_frame, inst, inst_data, ResultRegister());
David Srbecky8d335b62019-06-06 14:25:42 +0100384 return PossiblyHandlePendingExceptionOnInvoke(!success);
David Srbeckyee12e3a2019-06-03 15:18:57 +0100385 }
386
387 ALWAYS_INLINE WARN_UNUSED bool HandleUnused() REQUIRES_SHARED(Locks::mutator_lock_) {
388 UnexpectedOpcode(inst, shadow_frame);
389 return true;
390 }
391
David Srbeckybd613ec2019-05-30 15:39:38 +0100392 ALWAYS_INLINE bool NOP() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckybd613ec2019-05-30 15:39:38 +0100393 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100394 }
395
David Srbeckybd613ec2019-05-30 15:39:38 +0100396 ALWAYS_INLINE bool MOVE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100397 SetVReg(A(), GetVReg(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +0100398 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100399 }
400
David Srbeckybd613ec2019-05-30 15:39:38 +0100401 ALWAYS_INLINE bool MOVE_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100402 SetVReg(A(), GetVReg(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +0100403 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100404 }
405
David Srbeckybd613ec2019-05-30 15:39:38 +0100406 ALWAYS_INLINE bool MOVE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100407 SetVReg(A(), GetVReg(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +0100408 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100409 }
410
David Srbeckybd613ec2019-05-30 15:39:38 +0100411 ALWAYS_INLINE bool MOVE_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100412 SetVRegLong(A(), GetVRegLong(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +0100413 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100414 }
415
David Srbeckybd613ec2019-05-30 15:39:38 +0100416 ALWAYS_INLINE bool MOVE_WIDE_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100417 SetVRegLong(A(), GetVRegLong(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +0100418 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100419 }
420
David Srbeckybd613ec2019-05-30 15:39:38 +0100421 ALWAYS_INLINE bool MOVE_WIDE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100422 SetVRegLong(A(), GetVRegLong(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +0100423 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100424 }
425
David Srbeckybd613ec2019-05-30 15:39:38 +0100426 ALWAYS_INLINE bool MOVE_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100427 SetVRegReference(A(), GetVRegReference(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +0100428 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100429 }
430
David Srbeckybd613ec2019-05-30 15:39:38 +0100431 ALWAYS_INLINE bool MOVE_OBJECT_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100432 SetVRegReference(A(), GetVRegReference(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +0100433 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100434 }
435
David Srbeckybd613ec2019-05-30 15:39:38 +0100436 ALWAYS_INLINE bool MOVE_OBJECT_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100437 SetVRegReference(A(), GetVRegReference(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +0100438 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100439 }
440
David Srbeckybd613ec2019-05-30 15:39:38 +0100441 ALWAYS_INLINE bool MOVE_RESULT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100442 SetVReg(A(), ResultRegister()->GetI());
David Srbeckybd613ec2019-05-30 15:39:38 +0100443 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100444 }
445
David Srbeckybd613ec2019-05-30 15:39:38 +0100446 ALWAYS_INLINE bool MOVE_RESULT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100447 SetVRegLong(A(), ResultRegister()->GetJ());
David Srbeckybd613ec2019-05-30 15:39:38 +0100448 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100449 }
450
David Srbeckybd613ec2019-05-30 15:39:38 +0100451 ALWAYS_INLINE bool MOVE_RESULT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100452 SetVRegReference(A(), ResultRegister()->GetL());
David Srbeckybd613ec2019-05-30 15:39:38 +0100453 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100454 }
455
David Srbeckybd613ec2019-05-30 15:39:38 +0100456 ALWAYS_INLINE bool MOVE_EXCEPTION() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100457 ObjPtr<mirror::Throwable> exception = self->GetException();
458 DCHECK(exception != nullptr) << "No pending exception on MOVE_EXCEPTION instruction";
David Srbecky6baf6442019-05-30 14:57:43 +0100459 SetVRegReference(A(), exception);
David Srbecky6da82472018-10-23 14:03:08 +0100460 self->ClearException();
David Srbeckybd613ec2019-05-30 15:39:38 +0100461 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100462 }
463
David Srbeckybd613ec2019-05-30 15:39:38 +0100464 ALWAYS_INLINE bool RETURN_VOID_NO_BARRIER() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100465 JValue result;
David Srbeckyee12e3a2019-06-03 15:18:57 +0100466 return HandleReturn(result);
David Srbecky6da82472018-10-23 14:03:08 +0100467 }
468
David Srbeckybd613ec2019-05-30 15:39:38 +0100469 ALWAYS_INLINE bool RETURN_VOID() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100470 QuasiAtomic::ThreadFenceForConstructor();
471 JValue result;
David Srbeckyee12e3a2019-06-03 15:18:57 +0100472 return HandleReturn(result);
David Srbecky6da82472018-10-23 14:03:08 +0100473 }
474
David Srbeckybd613ec2019-05-30 15:39:38 +0100475 ALWAYS_INLINE bool RETURN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100476 JValue result;
477 result.SetJ(0);
David Srbecky6baf6442019-05-30 14:57:43 +0100478 result.SetI(GetVReg(A()));
David Srbeckyee12e3a2019-06-03 15:18:57 +0100479 return HandleReturn(result);
David Srbecky6da82472018-10-23 14:03:08 +0100480 }
481
David Srbeckybd613ec2019-05-30 15:39:38 +0100482 ALWAYS_INLINE bool RETURN_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100483 JValue result;
David Srbecky6baf6442019-05-30 14:57:43 +0100484 result.SetJ(GetVRegLong(A()));
David Srbeckyee12e3a2019-06-03 15:18:57 +0100485 return HandleReturn(result);
David Srbecky6da82472018-10-23 14:03:08 +0100486 }
487
David Srbeckybd613ec2019-05-30 15:39:38 +0100488 ALWAYS_INLINE bool RETURN_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100489 JValue result;
490 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000491 if (!HandleMonitorChecks()) {
David Srbeckybd613ec2019-05-30 15:39:38 +0100492 return false;
David Srbecky47ad3762018-10-31 12:43:40 +0000493 }
David Srbeckyd6f579c2019-05-29 18:09:30 +0100494 const size_t ref_idx = A();
David Srbecky6baf6442019-05-30 14:57:43 +0100495 ObjPtr<mirror::Object> obj_result = GetVRegReference(ref_idx);
David Srbecky6da82472018-10-23 14:03:08 +0100496 if (do_assignability_check && obj_result != nullptr) {
497 ObjPtr<mirror::Class> return_type = shadow_frame.GetMethod()->ResolveReturnType();
498 // Re-load since it might have moved.
David Srbecky6baf6442019-05-30 14:57:43 +0100499 obj_result = GetVRegReference(ref_idx);
David Srbecky6da82472018-10-23 14:03:08 +0100500 if (return_type == nullptr) {
501 // Return the pending exception.
David Srbecky8d335b62019-06-06 14:25:42 +0100502 return false; // Pending exception.
David Srbecky6da82472018-10-23 14:03:08 +0100503 }
504 if (!obj_result->VerifierInstanceOf(return_type)) {
Andreas Gampebc919af2019-07-10 14:09:51 -0700505 CHECK_LE(Runtime::Current()->GetTargetSdkVersion(), 29u);
David Srbecky6da82472018-10-23 14:03:08 +0100506 // This should never happen.
507 std::string temp1, temp2;
508 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
509 "Returning '%s' that is not instance of return type '%s'",
510 obj_result->GetClass()->GetDescriptor(&temp1),
511 return_type->GetDescriptor(&temp2));
David Srbecky8d335b62019-06-06 14:25:42 +0100512 return false; // Pending exception.
David Srbecky6da82472018-10-23 14:03:08 +0100513 }
514 }
Alex Lightb7c640d2019-03-20 15:52:13 -0700515 StackHandleScope<1> hs(self);
516 MutableHandle<mirror::Object> h_result(hs.NewHandle(obj_result));
David Srbecky6da82472018-10-23 14:03:08 +0100517 result.SetL(obj_result);
518 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
519 !SendMethodExitEvents(self,
520 instrumentation,
521 shadow_frame,
522 shadow_frame.GetThisObject(Accessor().InsSize()),
523 shadow_frame.GetMethod(),
524 inst->GetDexPc(Insns()),
Alex Lightb7c640d2019-03-20 15:52:13 -0700525 h_result))) {
David Srbecky8d335b62019-06-06 14:25:42 +0100526 DCHECK(self->IsExceptionPending());
527 // Do not raise exception event if it is caused by other instrumentation event.
528 shadow_frame.SetSkipNextExceptionEvent(true);
529 return false; // Pending exception.
David Srbecky6da82472018-10-23 14:03:08 +0100530 }
Alex Lightb7c640d2019-03-20 15:52:13 -0700531 // Re-load since it might have moved or been replaced during the MethodExitEvent.
532 result.SetL(h_result.Get());
David Srbecky6da82472018-10-23 14:03:08 +0100533 ctx->result = result;
534 exit_interpreter_loop = true;
David Srbecky8d335b62019-06-06 14:25:42 +0100535 return false;
David Srbecky6da82472018-10-23 14:03:08 +0100536 }
537
David Srbeckybd613ec2019-05-30 15:39:38 +0100538 ALWAYS_INLINE bool CONST_4() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100539 uint4_t dst = inst->VRegA_11n(inst_data);
540 int4_t val = inst->VRegB_11n(inst_data);
David Srbecky6baf6442019-05-30 14:57:43 +0100541 SetVReg(dst, val);
David Srbecky6da82472018-10-23 14:03:08 +0100542 if (val == 0) {
David Srbecky6baf6442019-05-30 14:57:43 +0100543 SetVRegReference(dst, nullptr);
David Srbecky6da82472018-10-23 14:03:08 +0100544 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100545 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100546 }
547
David Srbeckybd613ec2019-05-30 15:39:38 +0100548 ALWAYS_INLINE bool CONST_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100549 uint8_t dst = A();
550 int16_t val = B();
David Srbecky6baf6442019-05-30 14:57:43 +0100551 SetVReg(dst, val);
David Srbecky6da82472018-10-23 14:03:08 +0100552 if (val == 0) {
David Srbecky6baf6442019-05-30 14:57:43 +0100553 SetVRegReference(dst, nullptr);
David Srbecky6da82472018-10-23 14:03:08 +0100554 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100555 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100556 }
557
David Srbeckybd613ec2019-05-30 15:39:38 +0100558 ALWAYS_INLINE bool CONST() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100559 uint8_t dst = A();
560 int32_t val = B();
David Srbecky6baf6442019-05-30 14:57:43 +0100561 SetVReg(dst, val);
David Srbecky6da82472018-10-23 14:03:08 +0100562 if (val == 0) {
David Srbecky6baf6442019-05-30 14:57:43 +0100563 SetVRegReference(dst, nullptr);
David Srbecky6da82472018-10-23 14:03:08 +0100564 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100565 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100566 }
567
David Srbeckybd613ec2019-05-30 15:39:38 +0100568 ALWAYS_INLINE bool CONST_HIGH16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100569 uint8_t dst = A();
570 int32_t val = static_cast<int32_t>(B() << 16);
David Srbecky6baf6442019-05-30 14:57:43 +0100571 SetVReg(dst, val);
David Srbecky6da82472018-10-23 14:03:08 +0100572 if (val == 0) {
David Srbecky6baf6442019-05-30 14:57:43 +0100573 SetVRegReference(dst, nullptr);
David Srbecky6da82472018-10-23 14:03:08 +0100574 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100575 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100576 }
577
David Srbeckybd613ec2019-05-30 15:39:38 +0100578 ALWAYS_INLINE bool CONST_WIDE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100579 SetVRegLong(A(), B());
David Srbeckybd613ec2019-05-30 15:39:38 +0100580 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100581 }
582
David Srbeckybd613ec2019-05-30 15:39:38 +0100583 ALWAYS_INLINE bool CONST_WIDE_32() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100584 SetVRegLong(A(), B());
David Srbeckybd613ec2019-05-30 15:39:38 +0100585 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100586 }
587
David Srbeckybd613ec2019-05-30 15:39:38 +0100588 ALWAYS_INLINE bool CONST_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100589 SetVRegLong(A(), inst->WideVRegB());
David Srbeckybd613ec2019-05-30 15:39:38 +0100590 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100591 }
592
David Srbeckybd613ec2019-05-30 15:39:38 +0100593 ALWAYS_INLINE bool CONST_WIDE_HIGH16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100594 SetVRegLong(A(), static_cast<uint64_t>(B()) << 48);
David Srbeckybd613ec2019-05-30 15:39:38 +0100595 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100596 }
597
David Srbeckybd613ec2019-05-30 15:39:38 +0100598 ALWAYS_INLINE bool CONST_STRING() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100599 ObjPtr<mirror::String> s = ResolveString(self, shadow_frame, dex::StringIndex(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100600 if (UNLIKELY(s == nullptr)) {
David Srbecky8d335b62019-06-06 14:25:42 +0100601 return false; // Pending exception.
David Srbecky6da82472018-10-23 14:03:08 +0100602 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100603 SetVRegReference(A(), s);
David Srbecky6da82472018-10-23 14:03:08 +0100604 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100605 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100606 }
607
David Srbeckybd613ec2019-05-30 15:39:38 +0100608 ALWAYS_INLINE bool CONST_STRING_JUMBO() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100609 ObjPtr<mirror::String> s = ResolveString(self, shadow_frame, dex::StringIndex(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100610 if (UNLIKELY(s == nullptr)) {
David Srbecky8d335b62019-06-06 14:25:42 +0100611 return false; // Pending exception.
David Srbecky6da82472018-10-23 14:03:08 +0100612 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100613 SetVRegReference(A(), s);
David Srbecky6da82472018-10-23 14:03:08 +0100614 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100615 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100616 }
617
David Srbeckybd613ec2019-05-30 15:39:38 +0100618 ALWAYS_INLINE bool CONST_CLASS() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100619 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(B()),
David Srbecky6da82472018-10-23 14:03:08 +0100620 shadow_frame.GetMethod(),
621 self,
622 false,
623 do_access_check);
624 if (UNLIKELY(c == nullptr)) {
David Srbecky8d335b62019-06-06 14:25:42 +0100625 return false; // Pending exception.
David Srbecky6da82472018-10-23 14:03:08 +0100626 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100627 SetVRegReference(A(), c);
David Srbecky6da82472018-10-23 14:03:08 +0100628 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100629 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100630 }
631
David Srbeckybd613ec2019-05-30 15:39:38 +0100632 ALWAYS_INLINE bool CONST_METHOD_HANDLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100633 ClassLinker* cl = Runtime::Current()->GetClassLinker();
634 ObjPtr<mirror::MethodHandle> mh = cl->ResolveMethodHandle(self,
David Srbeckyd6f579c2019-05-29 18:09:30 +0100635 B(),
David Srbecky6da82472018-10-23 14:03:08 +0100636 shadow_frame.GetMethod());
637 if (UNLIKELY(mh == nullptr)) {
David Srbecky8d335b62019-06-06 14:25:42 +0100638 return false; // Pending exception.
David Srbecky6da82472018-10-23 14:03:08 +0100639 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100640 SetVRegReference(A(), mh);
David Srbecky6da82472018-10-23 14:03:08 +0100641 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100642 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100643 }
644
David Srbeckybd613ec2019-05-30 15:39:38 +0100645 ALWAYS_INLINE bool CONST_METHOD_TYPE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100646 ClassLinker* cl = Runtime::Current()->GetClassLinker();
647 ObjPtr<mirror::MethodType> mt = cl->ResolveMethodType(self,
David Srbeckyd6f579c2019-05-29 18:09:30 +0100648 dex::ProtoIndex(B()),
David Srbecky6da82472018-10-23 14:03:08 +0100649 shadow_frame.GetMethod());
650 if (UNLIKELY(mt == nullptr)) {
David Srbecky8d335b62019-06-06 14:25:42 +0100651 return false; // Pending exception.
David Srbecky6da82472018-10-23 14:03:08 +0100652 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100653 SetVRegReference(A(), mt);
David Srbecky6da82472018-10-23 14:03:08 +0100654 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100655 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100656 }
657
David Srbeckybd613ec2019-05-30 15:39:38 +0100658 ALWAYS_INLINE bool MONITOR_ENTER() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000659 if (!HandleAsyncException()) {
David Srbeckybd613ec2019-05-30 15:39:38 +0100660 return false;
David Srbecky47ad3762018-10-31 12:43:40 +0000661 }
David Srbecky6baf6442019-05-30 14:57:43 +0100662 ObjPtr<mirror::Object> obj = GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +0100663 if (UNLIKELY(obj == nullptr)) {
664 ThrowNullPointerExceptionFromInterpreter();
David Srbecky8d335b62019-06-06 14:25:42 +0100665 return false; // Pending exception.
David Srbecky6da82472018-10-23 14:03:08 +0100666 } else {
667 DoMonitorEnter<do_assignability_check>(self, &shadow_frame, obj);
David Srbecky8d335b62019-06-06 14:25:42 +0100668 return !self->IsExceptionPending();
David Srbecky6da82472018-10-23 14:03:08 +0100669 }
670 }
671
David Srbeckybd613ec2019-05-30 15:39:38 +0100672 ALWAYS_INLINE bool MONITOR_EXIT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000673 if (!HandleAsyncException()) {
David Srbeckybd613ec2019-05-30 15:39:38 +0100674 return false;
David Srbecky47ad3762018-10-31 12:43:40 +0000675 }
David Srbecky6baf6442019-05-30 14:57:43 +0100676 ObjPtr<mirror::Object> obj = GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +0100677 if (UNLIKELY(obj == nullptr)) {
678 ThrowNullPointerExceptionFromInterpreter();
David Srbecky8d335b62019-06-06 14:25:42 +0100679 return false; // Pending exception.
David Srbecky6da82472018-10-23 14:03:08 +0100680 } else {
681 DoMonitorExit<do_assignability_check>(self, &shadow_frame, obj);
David Srbecky8d335b62019-06-06 14:25:42 +0100682 return !self->IsExceptionPending();
David Srbecky6da82472018-10-23 14:03:08 +0100683 }
684 }
685
David Srbeckybd613ec2019-05-30 15:39:38 +0100686 ALWAYS_INLINE bool CHECK_CAST() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100687 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(B()),
David Srbecky6da82472018-10-23 14:03:08 +0100688 shadow_frame.GetMethod(),
689 self,
690 false,
691 do_access_check);
692 if (UNLIKELY(c == nullptr)) {
David Srbecky8d335b62019-06-06 14:25:42 +0100693 return false; // Pending exception.
David Srbecky6da82472018-10-23 14:03:08 +0100694 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100695 ObjPtr<mirror::Object> obj = GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +0100696 if (UNLIKELY(obj != nullptr && !obj->InstanceOf(c))) {
697 ThrowClassCastException(c, obj->GetClass());
David Srbecky8d335b62019-06-06 14:25:42 +0100698 return false; // Pending exception.
David Srbecky6da82472018-10-23 14:03:08 +0100699 }
700 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100701 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100702 }
703
David Srbeckybd613ec2019-05-30 15:39:38 +0100704 ALWAYS_INLINE bool INSTANCE_OF() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100705 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(C()),
David Srbecky6da82472018-10-23 14:03:08 +0100706 shadow_frame.GetMethod(),
707 self,
708 false,
709 do_access_check);
710 if (UNLIKELY(c == nullptr)) {
David Srbecky8d335b62019-06-06 14:25:42 +0100711 return false; // Pending exception.
David Srbecky6da82472018-10-23 14:03:08 +0100712 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100713 ObjPtr<mirror::Object> obj = GetVRegReference(B());
714 SetVReg(A(), (obj != nullptr && obj->InstanceOf(c)) ? 1 : 0);
David Srbecky6da82472018-10-23 14:03:08 +0100715 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100716 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100717 }
718
David Srbeckybd613ec2019-05-30 15:39:38 +0100719 ALWAYS_INLINE bool ARRAY_LENGTH() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100720 ObjPtr<mirror::Object> array = GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +0100721 if (UNLIKELY(array == nullptr)) {
722 ThrowNullPointerExceptionFromInterpreter();
David Srbecky8d335b62019-06-06 14:25:42 +0100723 return false; // Pending exception.
David Srbecky6da82472018-10-23 14:03:08 +0100724 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100725 SetVReg(A(), array->AsArray()->GetLength());
David Srbecky6da82472018-10-23 14:03:08 +0100726 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100727 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100728 }
729
David Srbeckybd613ec2019-05-30 15:39:38 +0100730 ALWAYS_INLINE bool NEW_INSTANCE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100731 ObjPtr<mirror::Object> obj = nullptr;
David Srbeckyd6f579c2019-05-29 18:09:30 +0100732 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(B()),
David Srbecky6da82472018-10-23 14:03:08 +0100733 shadow_frame.GetMethod(),
734 self,
735 false,
736 do_access_check);
737 if (LIKELY(c != nullptr)) {
Vladimir Marko64b56032019-06-20 15:52:39 +0100738 // Don't allow finalizable objects to be allocated during a transaction since these can't
739 // be finalized without a started runtime.
740 if (transaction_active && c->IsFinalizable()) {
741 AbortTransactionF(self,
742 "Allocating finalizable object in transaction: %s",
743 c->PrettyDescriptor().c_str());
David Srbecky8d335b62019-06-06 14:25:42 +0100744 return false; // Pending exception.
Vladimir Marko64b56032019-06-20 15:52:39 +0100745 }
Vladimir Marko9b81ac32019-05-16 16:47:08 +0100746 gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
David Srbecky6da82472018-10-23 14:03:08 +0100747 if (UNLIKELY(c->IsStringClass())) {
Vladimir Marko9b81ac32019-05-16 16:47:08 +0100748 obj = mirror::String::AllocEmptyString(self, allocator_type);
David Srbecky6da82472018-10-23 14:03:08 +0100749 } else {
Vladimir Marko9b81ac32019-05-16 16:47:08 +0100750 obj = AllocObjectFromCode(c, self, allocator_type);
David Srbecky6da82472018-10-23 14:03:08 +0100751 }
752 }
753 if (UNLIKELY(obj == nullptr)) {
David Srbecky8d335b62019-06-06 14:25:42 +0100754 return false; // Pending exception.
David Srbecky6da82472018-10-23 14:03:08 +0100755 } else {
756 obj->GetClass()->AssertInitializedOrInitializingInThread(self);
David Srbecky6baf6442019-05-30 14:57:43 +0100757 SetVRegReference(A(), obj);
David Srbecky6da82472018-10-23 14:03:08 +0100758 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100759 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100760 }
761
David Srbeckybd613ec2019-05-30 15:39:38 +0100762 ALWAYS_INLINE bool NEW_ARRAY() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100763 int32_t length = GetVReg(B());
Vladimir Marko9b81ac32019-05-16 16:47:08 +0100764 ObjPtr<mirror::Object> obj = AllocArrayFromCode<do_access_check>(
David Srbeckyd6f579c2019-05-29 18:09:30 +0100765 dex::TypeIndex(C()),
David Srbecky6da82472018-10-23 14:03:08 +0100766 length,
767 shadow_frame.GetMethod(),
768 self,
769 Runtime::Current()->GetHeap()->GetCurrentAllocator());
770 if (UNLIKELY(obj == nullptr)) {
David Srbecky8d335b62019-06-06 14:25:42 +0100771 return false; // Pending exception.
David Srbecky6da82472018-10-23 14:03:08 +0100772 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100773 SetVRegReference(A(), obj);
David Srbecky6da82472018-10-23 14:03:08 +0100774 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100775 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100776 }
777
David Srbeckybd613ec2019-05-30 15:39:38 +0100778 ALWAYS_INLINE bool FILLED_NEW_ARRAY() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky8d335b62019-06-06 14:25:42 +0100779 return DoFilledNewArray<false, do_access_check, transaction_active>(
780 inst, shadow_frame, self, ResultRegister());
David Srbecky6da82472018-10-23 14:03:08 +0100781 }
782
David Srbeckybd613ec2019-05-30 15:39:38 +0100783 ALWAYS_INLINE bool FILLED_NEW_ARRAY_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky8d335b62019-06-06 14:25:42 +0100784 return DoFilledNewArray<true, do_access_check, transaction_active>(
785 inst, shadow_frame, self, ResultRegister());
David Srbecky6da82472018-10-23 14:03:08 +0100786 }
787
David Srbeckybd613ec2019-05-30 15:39:38 +0100788 ALWAYS_INLINE bool FILL_ARRAY_DATA() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100789 const uint16_t* payload_addr = reinterpret_cast<const uint16_t*>(inst) + B();
David Srbecky6da82472018-10-23 14:03:08 +0100790 const Instruction::ArrayDataPayload* payload =
791 reinterpret_cast<const Instruction::ArrayDataPayload*>(payload_addr);
David Srbecky6baf6442019-05-30 14:57:43 +0100792 ObjPtr<mirror::Object> obj = GetVRegReference(A());
David Srbecky8d335b62019-06-06 14:25:42 +0100793 if (!FillArrayData(obj, payload)) {
794 return false; // Pending exception.
David Srbecky6da82472018-10-23 14:03:08 +0100795 }
796 if (transaction_active) {
797 RecordArrayElementsInTransaction(obj->AsArray(), payload->element_count);
798 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100799 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100800 }
801
David Srbeckybd613ec2019-05-30 15:39:38 +0100802 ALWAYS_INLINE bool THROW() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000803 if (!HandleAsyncException()) {
David Srbeckybd613ec2019-05-30 15:39:38 +0100804 return false;
David Srbecky47ad3762018-10-31 12:43:40 +0000805 }
David Srbecky6baf6442019-05-30 14:57:43 +0100806 ObjPtr<mirror::Object> exception = GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +0100807 if (UNLIKELY(exception == nullptr)) {
808 ThrowNullPointerException("throw with null exception");
809 } else if (do_assignability_check && !exception->GetClass()->IsThrowableClass()) {
810 // This should never happen.
811 std::string temp;
812 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
813 "Throwing '%s' that is not instance of Throwable",
814 exception->GetClass()->GetDescriptor(&temp));
815 } else {
816 self->SetException(exception->AsThrowable());
817 }
David Srbecky8d335b62019-06-06 14:25:42 +0100818 return false; // Pending exception.
David Srbecky6da82472018-10-23 14:03:08 +0100819 }
820
David Srbeckybd613ec2019-05-30 15:39:38 +0100821 ALWAYS_INLINE bool GOTO() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100822 return HandleGoto(A());
David Srbecky6da82472018-10-23 14:03:08 +0100823 }
824
David Srbeckybd613ec2019-05-30 15:39:38 +0100825 ALWAYS_INLINE bool GOTO_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100826 return HandleGoto(A());
David Srbecky6da82472018-10-23 14:03:08 +0100827 }
828
David Srbeckybd613ec2019-05-30 15:39:38 +0100829 ALWAYS_INLINE bool GOTO_32() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100830 return HandleGoto(A());
David Srbecky6da82472018-10-23 14:03:08 +0100831 }
832
David Srbeckybd613ec2019-05-30 15:39:38 +0100833 ALWAYS_INLINE bool PACKED_SWITCH() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100834 int32_t offset = DoPackedSwitch(inst, shadow_frame, inst_data);
David Srbecky8d335b62019-06-06 14:25:42 +0100835 if (!BranchInstrumentation(offset)) {
836 return false;
837 }
David Srbecky8867f3b2019-05-31 20:01:46 +0100838 SetNextInstruction(inst->RelativeAt(offset));
David Srbecky47ad3762018-10-31 12:43:40 +0000839 HandleBackwardBranch(offset);
David Srbeckybd613ec2019-05-30 15:39:38 +0100840 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100841 }
842
David Srbeckybd613ec2019-05-30 15:39:38 +0100843 ALWAYS_INLINE bool SPARSE_SWITCH() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100844 int32_t offset = DoSparseSwitch(inst, shadow_frame, inst_data);
David Srbecky8d335b62019-06-06 14:25:42 +0100845 if (!BranchInstrumentation(offset)) {
846 return false;
847 }
David Srbecky8867f3b2019-05-31 20:01:46 +0100848 SetNextInstruction(inst->RelativeAt(offset));
David Srbecky47ad3762018-10-31 12:43:40 +0000849 HandleBackwardBranch(offset);
David Srbeckybd613ec2019-05-30 15:39:38 +0100850 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100851 }
852
David Srbeckybd613ec2019-05-30 15:39:38 +0100853 ALWAYS_INLINE bool CMPL_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100854 return HandleCmpl<float>(GetVRegFloat(B()), GetVRegFloat(C()));
David Srbecky6da82472018-10-23 14:03:08 +0100855 }
856
David Srbeckybd613ec2019-05-30 15:39:38 +0100857 ALWAYS_INLINE bool CMPG_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100858 return HandleCmpg<float>(GetVRegFloat(B()), GetVRegFloat(C()));
David Srbecky6da82472018-10-23 14:03:08 +0100859 }
860
David Srbeckybd613ec2019-05-30 15:39:38 +0100861 ALWAYS_INLINE bool CMPL_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100862 return HandleCmpl<double>(GetVRegDouble(B()), GetVRegDouble(C()));
David Srbecky6da82472018-10-23 14:03:08 +0100863 }
864
David Srbeckybd613ec2019-05-30 15:39:38 +0100865 ALWAYS_INLINE bool CMPG_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100866 return HandleCmpg<double>(GetVRegDouble(B()), GetVRegDouble(C()));
David Srbecky6da82472018-10-23 14:03:08 +0100867 }
868
David Srbeckybd613ec2019-05-30 15:39:38 +0100869 ALWAYS_INLINE bool CMP_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100870 return HandleCmpl<int64_t>(GetVRegLong(B()), GetVRegLong(C()));
David Srbecky6da82472018-10-23 14:03:08 +0100871 }
872
David Srbeckybd613ec2019-05-30 15:39:38 +0100873 ALWAYS_INLINE bool IF_EQ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100874 return HandleIf(GetVReg(A()) == GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +0100875 }
876
David Srbeckybd613ec2019-05-30 15:39:38 +0100877 ALWAYS_INLINE bool IF_NE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100878 return HandleIf(GetVReg(A()) != GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +0100879 }
880
David Srbeckybd613ec2019-05-30 15:39:38 +0100881 ALWAYS_INLINE bool IF_LT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100882 return HandleIf(GetVReg(A()) < GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +0100883 }
884
David Srbeckybd613ec2019-05-30 15:39:38 +0100885 ALWAYS_INLINE bool IF_GE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100886 return HandleIf(GetVReg(A()) >= GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +0100887 }
888
David Srbeckybd613ec2019-05-30 15:39:38 +0100889 ALWAYS_INLINE bool IF_GT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100890 return HandleIf(GetVReg(A()) > GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +0100891 }
892
David Srbeckybd613ec2019-05-30 15:39:38 +0100893 ALWAYS_INLINE bool IF_LE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100894 return HandleIf(GetVReg(A()) <= GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +0100895 }
896
David Srbeckybd613ec2019-05-30 15:39:38 +0100897 ALWAYS_INLINE bool IF_EQZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100898 return HandleIf(GetVReg(A()) == 0, B());
David Srbecky6da82472018-10-23 14:03:08 +0100899 }
900
David Srbeckybd613ec2019-05-30 15:39:38 +0100901 ALWAYS_INLINE bool IF_NEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100902 return HandleIf(GetVReg(A()) != 0, B());
David Srbecky6da82472018-10-23 14:03:08 +0100903 }
904
David Srbeckybd613ec2019-05-30 15:39:38 +0100905 ALWAYS_INLINE bool IF_LTZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100906 return HandleIf(GetVReg(A()) < 0, B());
David Srbecky6da82472018-10-23 14:03:08 +0100907 }
908
David Srbeckybd613ec2019-05-30 15:39:38 +0100909 ALWAYS_INLINE bool IF_GEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100910 return HandleIf(GetVReg(A()) >= 0, B());
David Srbecky6da82472018-10-23 14:03:08 +0100911 }
912
David Srbeckybd613ec2019-05-30 15:39:38 +0100913 ALWAYS_INLINE bool IF_GTZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100914 return HandleIf(GetVReg(A()) > 0, B());
David Srbecky6da82472018-10-23 14:03:08 +0100915 }
916
David Srbeckybd613ec2019-05-30 15:39:38 +0100917 ALWAYS_INLINE bool IF_LEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100918 return HandleIf(GetVReg(A()) <= 0, B());
David Srbecky6da82472018-10-23 14:03:08 +0100919 }
920
David Srbeckybd613ec2019-05-30 15:39:38 +0100921 ALWAYS_INLINE bool AGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +0100922 return HandleAGet<mirror::BooleanArray>(&InstructionHandler::SetVReg);
David Srbecky6da82472018-10-23 14:03:08 +0100923 }
924
David Srbeckybd613ec2019-05-30 15:39:38 +0100925 ALWAYS_INLINE bool AGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +0100926 return HandleAGet<mirror::ByteArray>(&InstructionHandler::SetVReg);
David Srbecky6da82472018-10-23 14:03:08 +0100927 }
928
David Srbeckybd613ec2019-05-30 15:39:38 +0100929 ALWAYS_INLINE bool AGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +0100930 return HandleAGet<mirror::CharArray>(&InstructionHandler::SetVReg);
David Srbecky6da82472018-10-23 14:03:08 +0100931 }
932
David Srbeckybd613ec2019-05-30 15:39:38 +0100933 ALWAYS_INLINE bool AGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +0100934 return HandleAGet<mirror::ShortArray>(&InstructionHandler::SetVReg);
David Srbecky6da82472018-10-23 14:03:08 +0100935 }
936
David Srbeckybd613ec2019-05-30 15:39:38 +0100937 ALWAYS_INLINE bool AGET() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +0100938 return HandleAGet<mirror::IntArray>(&InstructionHandler::SetVReg);
David Srbecky6da82472018-10-23 14:03:08 +0100939 }
940
David Srbeckybd613ec2019-05-30 15:39:38 +0100941 ALWAYS_INLINE bool AGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +0100942 return HandleAGet<mirror::LongArray>(&InstructionHandler::SetVRegLong);
David Srbecky6da82472018-10-23 14:03:08 +0100943 }
944
David Srbeckybd613ec2019-05-30 15:39:38 +0100945 ALWAYS_INLINE bool AGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +0100946 return HandleAGet<mirror::ObjectArray<mirror::Object>>(&InstructionHandler::SetVRegReference);
David Srbecky6da82472018-10-23 14:03:08 +0100947 }
948
David Srbeckybd613ec2019-05-30 15:39:38 +0100949 ALWAYS_INLINE bool APUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +0100950 return HandleAPut<mirror::BooleanArray>(GetVReg(A()));
David Srbecky6da82472018-10-23 14:03:08 +0100951 }
952
David Srbeckybd613ec2019-05-30 15:39:38 +0100953 ALWAYS_INLINE bool APUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +0100954 return HandleAPut<mirror::ByteArray>(GetVReg(A()));
David Srbecky6da82472018-10-23 14:03:08 +0100955 }
956
David Srbeckybd613ec2019-05-30 15:39:38 +0100957 ALWAYS_INLINE bool APUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +0100958 return HandleAPut<mirror::CharArray>(GetVReg(A()));
David Srbecky6da82472018-10-23 14:03:08 +0100959 }
960
David Srbeckybd613ec2019-05-30 15:39:38 +0100961 ALWAYS_INLINE bool APUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +0100962 return HandleAPut<mirror::ShortArray>(GetVReg(A()));
David Srbecky6da82472018-10-23 14:03:08 +0100963 }
964
David Srbeckybd613ec2019-05-30 15:39:38 +0100965 ALWAYS_INLINE bool APUT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +0100966 return HandleAPut<mirror::IntArray>(GetVReg(A()));
David Srbecky6da82472018-10-23 14:03:08 +0100967 }
968
David Srbeckybd613ec2019-05-30 15:39:38 +0100969 ALWAYS_INLINE bool APUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +0100970 return HandleAPut<mirror::LongArray>(GetVRegLong(A()));
David Srbecky6da82472018-10-23 14:03:08 +0100971 }
972
David Srbeckybd613ec2019-05-30 15:39:38 +0100973 ALWAYS_INLINE bool APUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100974 ObjPtr<mirror::Object> a = GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +0100975 if (UNLIKELY(a == nullptr)) {
976 ThrowNullPointerExceptionFromInterpreter();
David Srbecky8d335b62019-06-06 14:25:42 +0100977 return false; // Pending exception.
David Srbecky6da82472018-10-23 14:03:08 +0100978 }
David Srbecky6baf6442019-05-30 14:57:43 +0100979 int32_t index = GetVReg(C());
980 ObjPtr<mirror::Object> val = GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +0100981 ObjPtr<mirror::ObjectArray<mirror::Object>> array = a->AsObjectArray<mirror::Object>();
982 if (array->CheckIsValidIndex(index) && array->CheckAssignable(val)) {
983 array->SetWithoutChecks<transaction_active>(index, val);
David Srbecky6da82472018-10-23 14:03:08 +0100984 } else {
David Srbecky8d335b62019-06-06 14:25:42 +0100985 return false; // Pending exception.
David Srbecky6da82472018-10-23 14:03:08 +0100986 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100987 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100988 }
989
David Srbeckybd613ec2019-05-30 15:39:38 +0100990 ALWAYS_INLINE bool IGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100991 return HandleGet<InstancePrimitiveRead, Primitive::kPrimBoolean>();
David Srbecky6da82472018-10-23 14:03:08 +0100992 }
993
David Srbeckybd613ec2019-05-30 15:39:38 +0100994 ALWAYS_INLINE bool IGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100995 return HandleGet<InstancePrimitiveRead, Primitive::kPrimByte>();
David Srbecky6da82472018-10-23 14:03:08 +0100996 }
997
David Srbeckybd613ec2019-05-30 15:39:38 +0100998 ALWAYS_INLINE bool IGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100999 return HandleGet<InstancePrimitiveRead, Primitive::kPrimChar>();
David Srbecky6da82472018-10-23 14:03:08 +01001000 }
1001
David Srbeckybd613ec2019-05-30 15:39:38 +01001002 ALWAYS_INLINE bool IGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001003 return HandleGet<InstancePrimitiveRead, Primitive::kPrimShort>();
David Srbecky6da82472018-10-23 14:03:08 +01001004 }
1005
David Srbeckybd613ec2019-05-30 15:39:38 +01001006 ALWAYS_INLINE bool IGET() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001007 return HandleGet<InstancePrimitiveRead, Primitive::kPrimInt>();
David Srbecky6da82472018-10-23 14:03:08 +01001008 }
1009
David Srbeckybd613ec2019-05-30 15:39:38 +01001010 ALWAYS_INLINE bool IGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001011 return HandleGet<InstancePrimitiveRead, Primitive::kPrimLong>();
David Srbecky6da82472018-10-23 14:03:08 +01001012 }
1013
David Srbeckybd613ec2019-05-30 15:39:38 +01001014 ALWAYS_INLINE bool IGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001015 return HandleGet<InstanceObjectRead, Primitive::kPrimNot>();
David Srbecky6da82472018-10-23 14:03:08 +01001016 }
1017
David Srbeckybd613ec2019-05-30 15:39:38 +01001018 ALWAYS_INLINE bool IGET_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001019 return HandleGetQuick<Primitive::kPrimInt>();
David Srbecky6da82472018-10-23 14:03:08 +01001020 }
1021
David Srbeckybd613ec2019-05-30 15:39:38 +01001022 ALWAYS_INLINE bool IGET_WIDE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001023 return HandleGetQuick<Primitive::kPrimLong>();
David Srbecky6da82472018-10-23 14:03:08 +01001024 }
1025
David Srbeckybd613ec2019-05-30 15:39:38 +01001026 ALWAYS_INLINE bool IGET_OBJECT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001027 return HandleGetQuick<Primitive::kPrimNot>();
David Srbecky6da82472018-10-23 14:03:08 +01001028 }
1029
David Srbeckybd613ec2019-05-30 15:39:38 +01001030 ALWAYS_INLINE bool IGET_BOOLEAN_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001031 return HandleGetQuick<Primitive::kPrimBoolean>();
David Srbecky6da82472018-10-23 14:03:08 +01001032 }
1033
David Srbeckybd613ec2019-05-30 15:39:38 +01001034 ALWAYS_INLINE bool IGET_BYTE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001035 return HandleGetQuick<Primitive::kPrimByte>();
David Srbecky6da82472018-10-23 14:03:08 +01001036 }
1037
David Srbeckybd613ec2019-05-30 15:39:38 +01001038 ALWAYS_INLINE bool IGET_CHAR_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001039 return HandleGetQuick<Primitive::kPrimChar>();
David Srbecky6da82472018-10-23 14:03:08 +01001040 }
1041
David Srbeckybd613ec2019-05-30 15:39:38 +01001042 ALWAYS_INLINE bool IGET_SHORT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001043 return HandleGetQuick<Primitive::kPrimShort>();
David Srbecky6da82472018-10-23 14:03:08 +01001044 }
1045
David Srbeckybd613ec2019-05-30 15:39:38 +01001046 ALWAYS_INLINE bool SGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001047 return HandleGet<StaticPrimitiveRead, Primitive::kPrimBoolean>();
David Srbecky6da82472018-10-23 14:03:08 +01001048 }
1049
David Srbeckybd613ec2019-05-30 15:39:38 +01001050 ALWAYS_INLINE bool SGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001051 return HandleGet<StaticPrimitiveRead, Primitive::kPrimByte>();
David Srbecky6da82472018-10-23 14:03:08 +01001052 }
1053
David Srbeckybd613ec2019-05-30 15:39:38 +01001054 ALWAYS_INLINE bool SGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001055 return HandleGet<StaticPrimitiveRead, Primitive::kPrimChar>();
David Srbecky6da82472018-10-23 14:03:08 +01001056 }
1057
David Srbeckybd613ec2019-05-30 15:39:38 +01001058 ALWAYS_INLINE bool SGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001059 return HandleGet<StaticPrimitiveRead, Primitive::kPrimShort>();
David Srbecky6da82472018-10-23 14:03:08 +01001060 }
1061
David Srbeckybd613ec2019-05-30 15:39:38 +01001062 ALWAYS_INLINE bool SGET() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001063 return HandleGet<StaticPrimitiveRead, Primitive::kPrimInt>();
David Srbecky6da82472018-10-23 14:03:08 +01001064 }
1065
David Srbeckybd613ec2019-05-30 15:39:38 +01001066 ALWAYS_INLINE bool SGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001067 return HandleGet<StaticPrimitiveRead, Primitive::kPrimLong>();
David Srbecky6da82472018-10-23 14:03:08 +01001068 }
1069
David Srbeckybd613ec2019-05-30 15:39:38 +01001070 ALWAYS_INLINE bool SGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001071 return HandleGet<StaticObjectRead, Primitive::kPrimNot>();
David Srbecky6da82472018-10-23 14:03:08 +01001072 }
1073
David Srbeckybd613ec2019-05-30 15:39:38 +01001074 ALWAYS_INLINE bool IPUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001075 return HandlePut<InstancePrimitiveWrite, Primitive::kPrimBoolean>();
David Srbecky6da82472018-10-23 14:03:08 +01001076 }
1077
David Srbeckybd613ec2019-05-30 15:39:38 +01001078 ALWAYS_INLINE bool IPUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001079 return HandlePut<InstancePrimitiveWrite, Primitive::kPrimByte>();
David Srbecky6da82472018-10-23 14:03:08 +01001080 }
1081
David Srbeckybd613ec2019-05-30 15:39:38 +01001082 ALWAYS_INLINE bool IPUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001083 return HandlePut<InstancePrimitiveWrite, Primitive::kPrimChar>();
David Srbecky6da82472018-10-23 14:03:08 +01001084 }
1085
David Srbeckybd613ec2019-05-30 15:39:38 +01001086 ALWAYS_INLINE bool IPUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001087 return HandlePut<InstancePrimitiveWrite, Primitive::kPrimShort>();
David Srbecky6da82472018-10-23 14:03:08 +01001088 }
1089
David Srbeckybd613ec2019-05-30 15:39:38 +01001090 ALWAYS_INLINE bool IPUT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001091 return HandlePut<InstancePrimitiveWrite, Primitive::kPrimInt>();
David Srbecky6da82472018-10-23 14:03:08 +01001092 }
1093
David Srbeckybd613ec2019-05-30 15:39:38 +01001094 ALWAYS_INLINE bool IPUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001095 return HandlePut<InstancePrimitiveWrite, Primitive::kPrimLong>();
David Srbecky6da82472018-10-23 14:03:08 +01001096 }
1097
David Srbeckybd613ec2019-05-30 15:39:38 +01001098 ALWAYS_INLINE bool IPUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001099 return HandlePut<InstanceObjectWrite, Primitive::kPrimNot>();
David Srbecky6da82472018-10-23 14:03:08 +01001100 }
1101
David Srbeckybd613ec2019-05-30 15:39:38 +01001102 ALWAYS_INLINE bool IPUT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001103 return HandlePutQuick<Primitive::kPrimInt>();
David Srbecky6da82472018-10-23 14:03:08 +01001104 }
1105
David Srbeckybd613ec2019-05-30 15:39:38 +01001106 ALWAYS_INLINE bool IPUT_BOOLEAN_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001107 return HandlePutQuick<Primitive::kPrimBoolean>();
David Srbecky6da82472018-10-23 14:03:08 +01001108 }
1109
David Srbeckybd613ec2019-05-30 15:39:38 +01001110 ALWAYS_INLINE bool IPUT_BYTE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001111 return HandlePutQuick<Primitive::kPrimByte>();
David Srbecky6da82472018-10-23 14:03:08 +01001112 }
1113
David Srbeckybd613ec2019-05-30 15:39:38 +01001114 ALWAYS_INLINE bool IPUT_CHAR_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001115 return HandlePutQuick<Primitive::kPrimChar>();
David Srbecky6da82472018-10-23 14:03:08 +01001116 }
1117
David Srbeckybd613ec2019-05-30 15:39:38 +01001118 ALWAYS_INLINE bool IPUT_SHORT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001119 return HandlePutQuick<Primitive::kPrimShort>();
David Srbecky6da82472018-10-23 14:03:08 +01001120 }
1121
David Srbeckybd613ec2019-05-30 15:39:38 +01001122 ALWAYS_INLINE bool IPUT_WIDE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001123 return HandlePutQuick<Primitive::kPrimLong>();
David Srbecky6da82472018-10-23 14:03:08 +01001124 }
1125
David Srbeckybd613ec2019-05-30 15:39:38 +01001126 ALWAYS_INLINE bool IPUT_OBJECT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001127 return HandlePutQuick<Primitive::kPrimNot>();
David Srbecky6da82472018-10-23 14:03:08 +01001128 }
1129
David Srbeckybd613ec2019-05-30 15:39:38 +01001130 ALWAYS_INLINE bool SPUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001131 return HandlePut<StaticPrimitiveWrite, Primitive::kPrimBoolean>();
David Srbecky6da82472018-10-23 14:03:08 +01001132 }
1133
David Srbeckybd613ec2019-05-30 15:39:38 +01001134 ALWAYS_INLINE bool SPUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001135 return HandlePut<StaticPrimitiveWrite, Primitive::kPrimByte>();
David Srbecky6da82472018-10-23 14:03:08 +01001136 }
1137
David Srbeckybd613ec2019-05-30 15:39:38 +01001138 ALWAYS_INLINE bool SPUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001139 return HandlePut<StaticPrimitiveWrite, Primitive::kPrimChar>();
David Srbecky6da82472018-10-23 14:03:08 +01001140 }
1141
David Srbeckybd613ec2019-05-30 15:39:38 +01001142 ALWAYS_INLINE bool SPUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001143 return HandlePut<StaticPrimitiveWrite, Primitive::kPrimShort>();
David Srbecky6da82472018-10-23 14:03:08 +01001144 }
1145
David Srbeckybd613ec2019-05-30 15:39:38 +01001146 ALWAYS_INLINE bool SPUT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001147 return HandlePut<StaticPrimitiveWrite, Primitive::kPrimInt>();
David Srbecky6da82472018-10-23 14:03:08 +01001148 }
1149
David Srbeckybd613ec2019-05-30 15:39:38 +01001150 ALWAYS_INLINE bool SPUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001151 return HandlePut<StaticPrimitiveWrite, Primitive::kPrimLong>();
David Srbecky6da82472018-10-23 14:03:08 +01001152 }
1153
David Srbeckybd613ec2019-05-30 15:39:38 +01001154 ALWAYS_INLINE bool SPUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001155 return HandlePut<StaticObjectWrite, Primitive::kPrimNot>();
David Srbecky6da82472018-10-23 14:03:08 +01001156 }
1157
David Srbeckybd613ec2019-05-30 15:39:38 +01001158 ALWAYS_INLINE bool INVOKE_VIRTUAL() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001159 return HandleInvoke<kVirtual, /*is_range=*/ false>();
David Srbecky6da82472018-10-23 14:03:08 +01001160 }
1161
David Srbeckybd613ec2019-05-30 15:39:38 +01001162 ALWAYS_INLINE bool INVOKE_VIRTUAL_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001163 return HandleInvoke<kVirtual, /*is_range=*/ true>();
David Srbecky6da82472018-10-23 14:03:08 +01001164 }
1165
David Srbeckybd613ec2019-05-30 15:39:38 +01001166 ALWAYS_INLINE bool INVOKE_SUPER() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001167 return HandleInvoke<kSuper, /*is_range=*/ false>();
David Srbecky6da82472018-10-23 14:03:08 +01001168 }
1169
David Srbeckybd613ec2019-05-30 15:39:38 +01001170 ALWAYS_INLINE bool INVOKE_SUPER_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001171 return HandleInvoke<kSuper, /*is_range=*/ true>();
David Srbecky6da82472018-10-23 14:03:08 +01001172 }
1173
David Srbeckybd613ec2019-05-30 15:39:38 +01001174 ALWAYS_INLINE bool INVOKE_DIRECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001175 return HandleInvoke<kDirect, /*is_range=*/ false>();
David Srbecky6da82472018-10-23 14:03:08 +01001176 }
1177
David Srbeckybd613ec2019-05-30 15:39:38 +01001178 ALWAYS_INLINE bool INVOKE_DIRECT_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001179 return HandleInvoke<kDirect, /*is_range=*/ true>();
David Srbecky6da82472018-10-23 14:03:08 +01001180 }
1181
David Srbeckybd613ec2019-05-30 15:39:38 +01001182 ALWAYS_INLINE bool INVOKE_INTERFACE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001183 return HandleInvoke<kInterface, /*is_range=*/ false>();
David Srbecky6da82472018-10-23 14:03:08 +01001184 }
1185
David Srbeckybd613ec2019-05-30 15:39:38 +01001186 ALWAYS_INLINE bool INVOKE_INTERFACE_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001187 return HandleInvoke<kInterface, /*is_range=*/ true>();
David Srbecky6da82472018-10-23 14:03:08 +01001188 }
1189
David Srbeckybd613ec2019-05-30 15:39:38 +01001190 ALWAYS_INLINE bool INVOKE_STATIC() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001191 return HandleInvoke<kStatic, /*is_range=*/ false>();
David Srbecky6da82472018-10-23 14:03:08 +01001192 }
1193
David Srbeckybd613ec2019-05-30 15:39:38 +01001194 ALWAYS_INLINE bool INVOKE_STATIC_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001195 return HandleInvoke<kStatic, /*is_range=*/ true>();
David Srbecky6da82472018-10-23 14:03:08 +01001196 }
1197
David Srbeckybd613ec2019-05-30 15:39:38 +01001198 ALWAYS_INLINE bool INVOKE_VIRTUAL_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001199 return HandleInvoke<kVirtual, /*is_range=*/ false, /*is_quick=*/ true>();
David Srbecky6da82472018-10-23 14:03:08 +01001200 }
1201
David Srbeckybd613ec2019-05-30 15:39:38 +01001202 ALWAYS_INLINE bool INVOKE_VIRTUAL_RANGE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001203 return HandleInvoke<kVirtual, /*is_range=*/ true, /*is_quick=*/ true>();
David Srbecky6da82472018-10-23 14:03:08 +01001204 }
1205
David Srbeckybd613ec2019-05-30 15:39:38 +01001206 ALWAYS_INLINE bool INVOKE_POLYMORPHIC() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001207 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1208 bool success = DoInvokePolymorphic</* is_range= */ false>(
1209 self, shadow_frame, inst, inst_data, ResultRegister());
David Srbecky8d335b62019-06-06 14:25:42 +01001210 return PossiblyHandlePendingExceptionOnInvoke(!success);
David Srbecky6da82472018-10-23 14:03:08 +01001211 }
1212
David Srbeckybd613ec2019-05-30 15:39:38 +01001213 ALWAYS_INLINE bool INVOKE_POLYMORPHIC_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001214 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1215 bool success = DoInvokePolymorphic</* is_range= */ true>(
1216 self, shadow_frame, inst, inst_data, ResultRegister());
David Srbecky8d335b62019-06-06 14:25:42 +01001217 return PossiblyHandlePendingExceptionOnInvoke(!success);
David Srbecky6da82472018-10-23 14:03:08 +01001218 }
1219
David Srbeckybd613ec2019-05-30 15:39:38 +01001220 ALWAYS_INLINE bool INVOKE_CUSTOM() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001221 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1222 bool success = DoInvokeCustom</* is_range= */ false>(
1223 self, shadow_frame, inst, inst_data, ResultRegister());
David Srbecky8d335b62019-06-06 14:25:42 +01001224 return PossiblyHandlePendingExceptionOnInvoke(!success);
David Srbecky6da82472018-10-23 14:03:08 +01001225 }
1226
David Srbeckybd613ec2019-05-30 15:39:38 +01001227 ALWAYS_INLINE bool INVOKE_CUSTOM_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001228 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1229 bool success = DoInvokeCustom</* is_range= */ true>(
1230 self, shadow_frame, inst, inst_data, ResultRegister());
David Srbecky8d335b62019-06-06 14:25:42 +01001231 return PossiblyHandlePendingExceptionOnInvoke(!success);
David Srbecky6da82472018-10-23 14:03:08 +01001232 }
1233
David Srbeckybd613ec2019-05-30 15:39:38 +01001234 ALWAYS_INLINE bool NEG_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001235 SetVReg(A(), -GetVReg(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001236 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001237 }
1238
David Srbeckybd613ec2019-05-30 15:39:38 +01001239 ALWAYS_INLINE bool NOT_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001240 SetVReg(A(), ~GetVReg(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001241 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001242 }
1243
David Srbeckybd613ec2019-05-30 15:39:38 +01001244 ALWAYS_INLINE bool NEG_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001245 SetVRegLong(A(), -GetVRegLong(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001246 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001247 }
1248
David Srbeckybd613ec2019-05-30 15:39:38 +01001249 ALWAYS_INLINE bool NOT_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001250 SetVRegLong(A(), ~GetVRegLong(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001251 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001252 }
1253
David Srbeckybd613ec2019-05-30 15:39:38 +01001254 ALWAYS_INLINE bool NEG_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001255 SetVRegFloat(A(), -GetVRegFloat(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001256 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001257 }
1258
David Srbeckybd613ec2019-05-30 15:39:38 +01001259 ALWAYS_INLINE bool NEG_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001260 SetVRegDouble(A(), -GetVRegDouble(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001261 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001262 }
1263
David Srbeckybd613ec2019-05-30 15:39:38 +01001264 ALWAYS_INLINE bool INT_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001265 SetVRegLong(A(), GetVReg(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001266 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001267 }
1268
David Srbeckybd613ec2019-05-30 15:39:38 +01001269 ALWAYS_INLINE bool INT_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001270 SetVRegFloat(A(), GetVReg(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001271 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001272 }
1273
David Srbeckybd613ec2019-05-30 15:39:38 +01001274 ALWAYS_INLINE bool INT_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001275 SetVRegDouble(A(), GetVReg(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001276 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001277 }
1278
David Srbeckybd613ec2019-05-30 15:39:38 +01001279 ALWAYS_INLINE bool LONG_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001280 SetVReg(A(), GetVRegLong(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001281 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001282 }
1283
David Srbeckybd613ec2019-05-30 15:39:38 +01001284 ALWAYS_INLINE bool LONG_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001285 SetVRegFloat(A(), GetVRegLong(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001286 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001287 }
1288
David Srbeckybd613ec2019-05-30 15:39:38 +01001289 ALWAYS_INLINE bool LONG_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001290 SetVRegDouble(A(), GetVRegLong(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001291 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001292 }
1293
David Srbeckybd613ec2019-05-30 15:39:38 +01001294 ALWAYS_INLINE bool FLOAT_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001295 float val = GetVRegFloat(B());
David Srbecky6da82472018-10-23 14:03:08 +01001296 int32_t result = art_float_to_integral<int32_t, float>(val);
David Srbecky6baf6442019-05-30 14:57:43 +01001297 SetVReg(A(), result);
David Srbeckybd613ec2019-05-30 15:39:38 +01001298 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001299 }
1300
David Srbeckybd613ec2019-05-30 15:39:38 +01001301 ALWAYS_INLINE bool FLOAT_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001302 float val = GetVRegFloat(B());
David Srbecky6da82472018-10-23 14:03:08 +01001303 int64_t result = art_float_to_integral<int64_t, float>(val);
David Srbecky6baf6442019-05-30 14:57:43 +01001304 SetVRegLong(A(), result);
David Srbeckybd613ec2019-05-30 15:39:38 +01001305 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001306 }
1307
David Srbeckybd613ec2019-05-30 15:39:38 +01001308 ALWAYS_INLINE bool FLOAT_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001309 SetVRegDouble(A(), GetVRegFloat(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001310 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001311 }
1312
David Srbeckybd613ec2019-05-30 15:39:38 +01001313 ALWAYS_INLINE bool DOUBLE_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001314 double val = GetVRegDouble(B());
David Srbecky6da82472018-10-23 14:03:08 +01001315 int32_t result = art_float_to_integral<int32_t, double>(val);
David Srbecky6baf6442019-05-30 14:57:43 +01001316 SetVReg(A(), result);
David Srbeckybd613ec2019-05-30 15:39:38 +01001317 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001318 }
1319
David Srbeckybd613ec2019-05-30 15:39:38 +01001320 ALWAYS_INLINE bool DOUBLE_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001321 double val = GetVRegDouble(B());
David Srbecky6da82472018-10-23 14:03:08 +01001322 int64_t result = art_float_to_integral<int64_t, double>(val);
David Srbecky6baf6442019-05-30 14:57:43 +01001323 SetVRegLong(A(), result);
David Srbeckybd613ec2019-05-30 15:39:38 +01001324 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001325 }
1326
David Srbeckybd613ec2019-05-30 15:39:38 +01001327 ALWAYS_INLINE bool DOUBLE_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001328 SetVRegFloat(A(), GetVRegDouble(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001329 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001330 }
1331
David Srbeckybd613ec2019-05-30 15:39:38 +01001332 ALWAYS_INLINE bool INT_TO_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001333 SetVReg(A(), static_cast<int8_t>(GetVReg(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001334 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001335 }
1336
David Srbeckybd613ec2019-05-30 15:39:38 +01001337 ALWAYS_INLINE bool INT_TO_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001338 SetVReg(A(), static_cast<uint16_t>(GetVReg(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001339 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001340 }
1341
David Srbeckybd613ec2019-05-30 15:39:38 +01001342 ALWAYS_INLINE bool INT_TO_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001343 SetVReg(A(), static_cast<int16_t>(GetVReg(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001344 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001345 }
1346
David Srbeckybd613ec2019-05-30 15:39:38 +01001347 ALWAYS_INLINE bool ADD_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001348 SetVReg(A(), SafeAdd(GetVReg(B()), GetVReg(C())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001349 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001350 }
1351
David Srbeckybd613ec2019-05-30 15:39:38 +01001352 ALWAYS_INLINE bool SUB_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001353 SetVReg(A(), SafeSub(GetVReg(B()), GetVReg(C())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001354 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001355 }
1356
David Srbeckybd613ec2019-05-30 15:39:38 +01001357 ALWAYS_INLINE bool MUL_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001358 SetVReg(A(), SafeMul(GetVReg(B()), GetVReg(C())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001359 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001360 }
1361
David Srbeckybd613ec2019-05-30 15:39:38 +01001362 ALWAYS_INLINE bool DIV_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky8d335b62019-06-06 14:25:42 +01001363 return DoIntDivide(shadow_frame, A(), GetVReg(B()), GetVReg(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001364 }
1365
David Srbeckybd613ec2019-05-30 15:39:38 +01001366 ALWAYS_INLINE bool REM_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky8d335b62019-06-06 14:25:42 +01001367 return DoIntRemainder(shadow_frame, A(), GetVReg(B()), GetVReg(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001368 }
1369
David Srbeckybd613ec2019-05-30 15:39:38 +01001370 ALWAYS_INLINE bool SHL_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001371 SetVReg(A(), GetVReg(B()) << (GetVReg(C()) & 0x1f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001372 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001373 }
1374
David Srbeckybd613ec2019-05-30 15:39:38 +01001375 ALWAYS_INLINE bool SHR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001376 SetVReg(A(), GetVReg(B()) >> (GetVReg(C()) & 0x1f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001377 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001378 }
1379
David Srbeckybd613ec2019-05-30 15:39:38 +01001380 ALWAYS_INLINE bool USHR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001381 SetVReg(A(), static_cast<uint32_t>(GetVReg(B())) >> (GetVReg(C()) & 0x1f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001382 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001383 }
1384
David Srbeckybd613ec2019-05-30 15:39:38 +01001385 ALWAYS_INLINE bool AND_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001386 SetVReg(A(), GetVReg(B()) & GetVReg(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001387 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001388 }
1389
David Srbeckybd613ec2019-05-30 15:39:38 +01001390 ALWAYS_INLINE bool OR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001391 SetVReg(A(), GetVReg(B()) | GetVReg(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001392 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001393 }
1394
David Srbeckybd613ec2019-05-30 15:39:38 +01001395 ALWAYS_INLINE bool XOR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001396 SetVReg(A(), GetVReg(B()) ^ GetVReg(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001397 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001398 }
1399
David Srbeckybd613ec2019-05-30 15:39:38 +01001400 ALWAYS_INLINE bool ADD_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001401 SetVRegLong(A(), SafeAdd(GetVRegLong(B()), GetVRegLong(C())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001402 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001403 }
1404
David Srbeckybd613ec2019-05-30 15:39:38 +01001405 ALWAYS_INLINE bool SUB_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001406 SetVRegLong(A(), SafeSub(GetVRegLong(B()), GetVRegLong(C())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001407 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001408 }
1409
David Srbeckybd613ec2019-05-30 15:39:38 +01001410 ALWAYS_INLINE bool MUL_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001411 SetVRegLong(A(), SafeMul(GetVRegLong(B()), GetVRegLong(C())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001412 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001413 }
1414
David Srbeckybd613ec2019-05-30 15:39:38 +01001415 ALWAYS_INLINE bool DIV_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky8d335b62019-06-06 14:25:42 +01001416 return DoLongDivide(shadow_frame, A(), GetVRegLong(B()), GetVRegLong(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001417 }
1418
David Srbeckybd613ec2019-05-30 15:39:38 +01001419 ALWAYS_INLINE bool REM_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky8d335b62019-06-06 14:25:42 +01001420 return DoLongRemainder(shadow_frame, A(), GetVRegLong(B()), GetVRegLong(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001421 }
1422
David Srbeckybd613ec2019-05-30 15:39:38 +01001423 ALWAYS_INLINE bool AND_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001424 SetVRegLong(A(), GetVRegLong(B()) & GetVRegLong(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001425 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001426 }
1427
David Srbeckybd613ec2019-05-30 15:39:38 +01001428 ALWAYS_INLINE bool OR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001429 SetVRegLong(A(), GetVRegLong(B()) | GetVRegLong(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001430 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001431 }
1432
David Srbeckybd613ec2019-05-30 15:39:38 +01001433 ALWAYS_INLINE bool XOR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001434 SetVRegLong(A(), GetVRegLong(B()) ^ GetVRegLong(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001435 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001436 }
1437
David Srbeckybd613ec2019-05-30 15:39:38 +01001438 ALWAYS_INLINE bool SHL_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001439 SetVRegLong(A(), GetVRegLong(B()) << (GetVReg(C()) & 0x3f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001440 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001441 }
1442
David Srbeckybd613ec2019-05-30 15:39:38 +01001443 ALWAYS_INLINE bool SHR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001444 SetVRegLong(A(), GetVRegLong(B()) >> (GetVReg(C()) & 0x3f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001445 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001446 }
1447
David Srbeckybd613ec2019-05-30 15:39:38 +01001448 ALWAYS_INLINE bool USHR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001449 SetVRegLong(A(), static_cast<uint64_t>(GetVRegLong(B())) >> (GetVReg(C()) & 0x3f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001450 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001451 }
1452
David Srbeckybd613ec2019-05-30 15:39:38 +01001453 ALWAYS_INLINE bool ADD_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001454 SetVRegFloat(A(), GetVRegFloat(B()) + GetVRegFloat(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001455 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001456 }
1457
David Srbeckybd613ec2019-05-30 15:39:38 +01001458 ALWAYS_INLINE bool SUB_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001459 SetVRegFloat(A(), GetVRegFloat(B()) - GetVRegFloat(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001460 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001461 }
1462
David Srbeckybd613ec2019-05-30 15:39:38 +01001463 ALWAYS_INLINE bool MUL_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001464 SetVRegFloat(A(), GetVRegFloat(B()) * GetVRegFloat(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001465 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001466 }
1467
David Srbeckybd613ec2019-05-30 15:39:38 +01001468 ALWAYS_INLINE bool DIV_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001469 SetVRegFloat(A(), GetVRegFloat(B()) / GetVRegFloat(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001470 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001471 }
1472
David Srbeckybd613ec2019-05-30 15:39:38 +01001473 ALWAYS_INLINE bool REM_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001474 SetVRegFloat(A(), fmodf(GetVRegFloat(B()), GetVRegFloat(C())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001475 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001476 }
1477
David Srbeckybd613ec2019-05-30 15:39:38 +01001478 ALWAYS_INLINE bool ADD_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001479 SetVRegDouble(A(), GetVRegDouble(B()) + GetVRegDouble(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001480 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001481 }
1482
David Srbeckybd613ec2019-05-30 15:39:38 +01001483 ALWAYS_INLINE bool SUB_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001484 SetVRegDouble(A(), GetVRegDouble(B()) - GetVRegDouble(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001485 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001486 }
1487
David Srbeckybd613ec2019-05-30 15:39:38 +01001488 ALWAYS_INLINE bool MUL_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001489 SetVRegDouble(A(), GetVRegDouble(B()) * GetVRegDouble(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001490 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001491 }
1492
David Srbeckybd613ec2019-05-30 15:39:38 +01001493 ALWAYS_INLINE bool DIV_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001494 SetVRegDouble(A(), GetVRegDouble(B()) / GetVRegDouble(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001495 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001496 }
1497
David Srbeckybd613ec2019-05-30 15:39:38 +01001498 ALWAYS_INLINE bool REM_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001499 SetVRegDouble(A(), fmod(GetVRegDouble(B()), GetVRegDouble(C())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001500 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001501 }
1502
David Srbeckybd613ec2019-05-30 15:39:38 +01001503 ALWAYS_INLINE bool ADD_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001504 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001505 SetVReg(vregA, SafeAdd(GetVReg(vregA), GetVReg(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001506 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001507 }
1508
David Srbeckybd613ec2019-05-30 15:39:38 +01001509 ALWAYS_INLINE bool SUB_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001510 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001511 SetVReg(vregA, SafeSub(GetVReg(vregA), GetVReg(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001512 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001513 }
1514
David Srbeckybd613ec2019-05-30 15:39:38 +01001515 ALWAYS_INLINE bool MUL_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001516 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001517 SetVReg(vregA, SafeMul(GetVReg(vregA), GetVReg(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001518 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001519 }
1520
David Srbeckybd613ec2019-05-30 15:39:38 +01001521 ALWAYS_INLINE bool DIV_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001522 uint4_t vregA = A();
David Srbecky8d335b62019-06-06 14:25:42 +01001523 return DoIntDivide(shadow_frame, vregA, GetVReg(vregA), GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001524 }
1525
David Srbeckybd613ec2019-05-30 15:39:38 +01001526 ALWAYS_INLINE bool REM_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001527 uint4_t vregA = A();
David Srbecky8d335b62019-06-06 14:25:42 +01001528 return DoIntRemainder(shadow_frame, vregA, GetVReg(vregA), GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001529 }
1530
David Srbeckybd613ec2019-05-30 15:39:38 +01001531 ALWAYS_INLINE bool SHL_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001532 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001533 SetVReg(vregA, GetVReg(vregA) << (GetVReg(B()) & 0x1f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001534 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001535 }
1536
David Srbeckybd613ec2019-05-30 15:39:38 +01001537 ALWAYS_INLINE bool SHR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001538 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001539 SetVReg(vregA, GetVReg(vregA) >> (GetVReg(B()) & 0x1f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001540 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001541 }
1542
David Srbeckybd613ec2019-05-30 15:39:38 +01001543 ALWAYS_INLINE bool USHR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001544 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001545 SetVReg(vregA, static_cast<uint32_t>(GetVReg(vregA)) >> (GetVReg(B()) & 0x1f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001546 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001547 }
1548
David Srbeckybd613ec2019-05-30 15:39:38 +01001549 ALWAYS_INLINE bool AND_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001550 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001551 SetVReg(vregA, GetVReg(vregA) & GetVReg(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001552 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001553 }
1554
David Srbeckybd613ec2019-05-30 15:39:38 +01001555 ALWAYS_INLINE bool OR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001556 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001557 SetVReg(vregA, GetVReg(vregA) | GetVReg(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001558 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001559 }
1560
David Srbeckybd613ec2019-05-30 15:39:38 +01001561 ALWAYS_INLINE bool XOR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001562 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001563 SetVReg(vregA, GetVReg(vregA) ^ GetVReg(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001564 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001565 }
1566
David Srbeckybd613ec2019-05-30 15:39:38 +01001567 ALWAYS_INLINE bool ADD_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001568 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001569 SetVRegLong(vregA, SafeAdd(GetVRegLong(vregA), GetVRegLong(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001570 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001571 }
1572
David Srbeckybd613ec2019-05-30 15:39:38 +01001573 ALWAYS_INLINE bool SUB_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001574 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001575 SetVRegLong(vregA, SafeSub(GetVRegLong(vregA), GetVRegLong(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001576 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001577 }
1578
David Srbeckybd613ec2019-05-30 15:39:38 +01001579 ALWAYS_INLINE bool MUL_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001580 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001581 SetVRegLong(vregA, SafeMul(GetVRegLong(vregA), GetVRegLong(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001582 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001583 }
1584
David Srbeckybd613ec2019-05-30 15:39:38 +01001585 ALWAYS_INLINE bool DIV_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001586 uint4_t vregA = A();
David Srbecky8d335b62019-06-06 14:25:42 +01001587 return DoLongDivide(shadow_frame, vregA, GetVRegLong(vregA), GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001588 }
1589
David Srbeckybd613ec2019-05-30 15:39:38 +01001590 ALWAYS_INLINE bool REM_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001591 uint4_t vregA = A();
David Srbecky8d335b62019-06-06 14:25:42 +01001592 return DoLongRemainder(shadow_frame, vregA, GetVRegLong(vregA), GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001593 }
1594
David Srbeckybd613ec2019-05-30 15:39:38 +01001595 ALWAYS_INLINE bool AND_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001596 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001597 SetVRegLong(vregA, GetVRegLong(vregA) & GetVRegLong(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001598 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001599 }
1600
David Srbeckybd613ec2019-05-30 15:39:38 +01001601 ALWAYS_INLINE bool OR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001602 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001603 SetVRegLong(vregA, GetVRegLong(vregA) | GetVRegLong(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001604 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001605 }
1606
David Srbeckybd613ec2019-05-30 15:39:38 +01001607 ALWAYS_INLINE bool XOR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001608 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001609 SetVRegLong(vregA, GetVRegLong(vregA) ^ GetVRegLong(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001610 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001611 }
1612
David Srbeckybd613ec2019-05-30 15:39:38 +01001613 ALWAYS_INLINE bool SHL_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001614 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001615 SetVRegLong(vregA, GetVRegLong(vregA) << (GetVReg(B()) & 0x3f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001616 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001617 }
1618
David Srbeckybd613ec2019-05-30 15:39:38 +01001619 ALWAYS_INLINE bool SHR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001620 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001621 SetVRegLong(vregA, GetVRegLong(vregA) >> (GetVReg(B()) & 0x3f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001622 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001623 }
1624
David Srbeckybd613ec2019-05-30 15:39:38 +01001625 ALWAYS_INLINE bool USHR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001626 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001627 SetVRegLong(vregA, static_cast<uint64_t>(GetVRegLong(vregA)) >> (GetVReg(B()) & 0x3f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001628 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001629 }
1630
David Srbeckybd613ec2019-05-30 15:39:38 +01001631 ALWAYS_INLINE bool ADD_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001632 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001633 SetVRegFloat(vregA, GetVRegFloat(vregA) + GetVRegFloat(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001634 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001635 }
1636
David Srbeckybd613ec2019-05-30 15:39:38 +01001637 ALWAYS_INLINE bool SUB_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001638 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001639 SetVRegFloat(vregA, GetVRegFloat(vregA) - GetVRegFloat(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001640 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001641 }
1642
David Srbeckybd613ec2019-05-30 15:39:38 +01001643 ALWAYS_INLINE bool MUL_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001644 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001645 SetVRegFloat(vregA, GetVRegFloat(vregA) * GetVRegFloat(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001646 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001647 }
1648
David Srbeckybd613ec2019-05-30 15:39:38 +01001649 ALWAYS_INLINE bool DIV_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001650 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001651 SetVRegFloat(vregA, GetVRegFloat(vregA) / GetVRegFloat(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001652 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001653 }
1654
David Srbeckybd613ec2019-05-30 15:39:38 +01001655 ALWAYS_INLINE bool REM_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001656 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001657 SetVRegFloat(vregA, fmodf(GetVRegFloat(vregA), GetVRegFloat(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001658 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001659 }
1660
David Srbeckybd613ec2019-05-30 15:39:38 +01001661 ALWAYS_INLINE bool ADD_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001662 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001663 SetVRegDouble(vregA, GetVRegDouble(vregA) + GetVRegDouble(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001664 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001665 }
1666
David Srbeckybd613ec2019-05-30 15:39:38 +01001667 ALWAYS_INLINE bool SUB_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001668 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001669 SetVRegDouble(vregA, GetVRegDouble(vregA) - GetVRegDouble(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001670 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001671 }
1672
David Srbeckybd613ec2019-05-30 15:39:38 +01001673 ALWAYS_INLINE bool MUL_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001674 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001675 SetVRegDouble(vregA, GetVRegDouble(vregA) * GetVRegDouble(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001676 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001677 }
1678
David Srbeckybd613ec2019-05-30 15:39:38 +01001679 ALWAYS_INLINE bool DIV_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001680 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001681 SetVRegDouble(vregA, GetVRegDouble(vregA) / GetVRegDouble(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001682 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001683 }
1684
David Srbeckybd613ec2019-05-30 15:39:38 +01001685 ALWAYS_INLINE bool REM_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001686 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001687 SetVRegDouble(vregA, fmod(GetVRegDouble(vregA), GetVRegDouble(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001688 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001689 }
1690
David Srbeckybd613ec2019-05-30 15:39:38 +01001691 ALWAYS_INLINE bool ADD_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001692 SetVReg(A(), SafeAdd(GetVReg(B()), C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001693 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001694 }
1695
David Srbeckybd613ec2019-05-30 15:39:38 +01001696 ALWAYS_INLINE bool RSUB_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001697 SetVReg(A(), SafeSub(C(), GetVReg(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001698 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001699 }
1700
David Srbeckybd613ec2019-05-30 15:39:38 +01001701 ALWAYS_INLINE bool MUL_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001702 SetVReg(A(), SafeMul(GetVReg(B()), C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001703 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001704 }
1705
David Srbeckybd613ec2019-05-30 15:39:38 +01001706 ALWAYS_INLINE bool DIV_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky8d335b62019-06-06 14:25:42 +01001707 return DoIntDivide(shadow_frame, A(), GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +01001708 }
1709
David Srbeckybd613ec2019-05-30 15:39:38 +01001710 ALWAYS_INLINE bool REM_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky8d335b62019-06-06 14:25:42 +01001711 return DoIntRemainder(shadow_frame, A(), GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +01001712 }
1713
David Srbeckybd613ec2019-05-30 15:39:38 +01001714 ALWAYS_INLINE bool AND_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001715 SetVReg(A(), GetVReg(B()) & C());
David Srbeckybd613ec2019-05-30 15:39:38 +01001716 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001717 }
1718
David Srbeckybd613ec2019-05-30 15:39:38 +01001719 ALWAYS_INLINE bool OR_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001720 SetVReg(A(), GetVReg(B()) | C());
David Srbeckybd613ec2019-05-30 15:39:38 +01001721 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001722 }
1723
David Srbeckybd613ec2019-05-30 15:39:38 +01001724 ALWAYS_INLINE bool XOR_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001725 SetVReg(A(), GetVReg(B()) ^ C());
David Srbeckybd613ec2019-05-30 15:39:38 +01001726 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001727 }
1728
David Srbeckybd613ec2019-05-30 15:39:38 +01001729 ALWAYS_INLINE bool ADD_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001730 SetVReg(A(), SafeAdd(GetVReg(B()), C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001731 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001732 }
1733
David Srbeckybd613ec2019-05-30 15:39:38 +01001734 ALWAYS_INLINE bool RSUB_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001735 SetVReg(A(), SafeSub(C(), GetVReg(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001736 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001737 }
1738
David Srbeckybd613ec2019-05-30 15:39:38 +01001739 ALWAYS_INLINE bool MUL_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001740 SetVReg(A(), SafeMul(GetVReg(B()), C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001741 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001742 }
1743
David Srbeckybd613ec2019-05-30 15:39:38 +01001744 ALWAYS_INLINE bool DIV_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky8d335b62019-06-06 14:25:42 +01001745 return DoIntDivide(shadow_frame, A(), GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +01001746 }
1747
David Srbeckybd613ec2019-05-30 15:39:38 +01001748 ALWAYS_INLINE bool REM_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky8d335b62019-06-06 14:25:42 +01001749 return DoIntRemainder(shadow_frame, A(), GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +01001750 }
1751
David Srbeckybd613ec2019-05-30 15:39:38 +01001752 ALWAYS_INLINE bool AND_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001753 SetVReg(A(), GetVReg(B()) & C());
David Srbeckybd613ec2019-05-30 15:39:38 +01001754 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001755 }
1756
David Srbeckybd613ec2019-05-30 15:39:38 +01001757 ALWAYS_INLINE bool OR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001758 SetVReg(A(), GetVReg(B()) | C());
David Srbeckybd613ec2019-05-30 15:39:38 +01001759 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001760 }
1761
David Srbeckybd613ec2019-05-30 15:39:38 +01001762 ALWAYS_INLINE bool XOR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001763 SetVReg(A(), GetVReg(B()) ^ C());
David Srbeckybd613ec2019-05-30 15:39:38 +01001764 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001765 }
1766
David Srbeckybd613ec2019-05-30 15:39:38 +01001767 ALWAYS_INLINE bool SHL_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001768 SetVReg(A(), GetVReg(B()) << (C() & 0x1f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001769 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001770 }
1771
David Srbeckybd613ec2019-05-30 15:39:38 +01001772 ALWAYS_INLINE bool SHR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001773 SetVReg(A(), GetVReg(B()) >> (C() & 0x1f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001774 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001775 }
1776
David Srbeckybd613ec2019-05-30 15:39:38 +01001777 ALWAYS_INLINE bool USHR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001778 SetVReg(A(), static_cast<uint32_t>(GetVReg(B())) >> (C() & 0x1f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001779 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001780 }
1781
David Srbeckybd613ec2019-05-30 15:39:38 +01001782 ALWAYS_INLINE bool UNUSED_3E() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001783 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001784 }
1785
David Srbeckybd613ec2019-05-30 15:39:38 +01001786 ALWAYS_INLINE bool UNUSED_3F() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001787 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001788 }
1789
David Srbeckybd613ec2019-05-30 15:39:38 +01001790 ALWAYS_INLINE bool UNUSED_40() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001791 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001792 }
1793
David Srbeckybd613ec2019-05-30 15:39:38 +01001794 ALWAYS_INLINE bool UNUSED_41() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001795 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001796 }
1797
David Srbeckybd613ec2019-05-30 15:39:38 +01001798 ALWAYS_INLINE bool UNUSED_42() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001799 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001800 }
1801
David Srbeckybd613ec2019-05-30 15:39:38 +01001802 ALWAYS_INLINE bool UNUSED_43() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001803 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001804 }
1805
David Srbeckybd613ec2019-05-30 15:39:38 +01001806 ALWAYS_INLINE bool UNUSED_79() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001807 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001808 }
1809
David Srbeckybd613ec2019-05-30 15:39:38 +01001810 ALWAYS_INLINE bool UNUSED_7A() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001811 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001812 }
1813
David Srbeckybd613ec2019-05-30 15:39:38 +01001814 ALWAYS_INLINE bool UNUSED_F3() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001815 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001816 }
1817
David Srbeckybd613ec2019-05-30 15:39:38 +01001818 ALWAYS_INLINE bool UNUSED_F4() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001819 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001820 }
1821
David Srbeckybd613ec2019-05-30 15:39:38 +01001822 ALWAYS_INLINE bool UNUSED_F5() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001823 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001824 }
1825
David Srbeckybd613ec2019-05-30 15:39:38 +01001826 ALWAYS_INLINE bool UNUSED_F6() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001827 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001828 }
1829
David Srbeckybd613ec2019-05-30 15:39:38 +01001830 ALWAYS_INLINE bool UNUSED_F7() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001831 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001832 }
1833
David Srbeckybd613ec2019-05-30 15:39:38 +01001834 ALWAYS_INLINE bool UNUSED_F8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001835 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001836 }
1837
David Srbeckybd613ec2019-05-30 15:39:38 +01001838 ALWAYS_INLINE bool UNUSED_F9() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001839 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001840 }
1841
1842 ALWAYS_INLINE InstructionHandler(SwitchImplContext* ctx,
1843 const instrumentation::Instrumentation* instrumentation,
1844 Thread* self,
1845 ShadowFrame& shadow_frame,
1846 uint16_t dex_pc,
David Srbeckyc56a23e2019-06-05 17:45:49 +01001847 const Instruction* inst,
David Srbecky6da82472018-10-23 14:03:08 +01001848 uint16_t inst_data,
David Srbecky8867f3b2019-05-31 20:01:46 +01001849 const Instruction*& next,
David Srbecky6da82472018-10-23 14:03:08 +01001850 bool& exit_interpreter_loop)
1851 : ctx(ctx),
1852 instrumentation(instrumentation),
1853 self(self),
1854 shadow_frame(shadow_frame),
1855 dex_pc(dex_pc),
1856 inst(inst),
1857 inst_data(inst_data),
David Srbecky8867f3b2019-05-31 20:01:46 +01001858 next(next),
David Srbecky6da82472018-10-23 14:03:08 +01001859 exit_interpreter_loop(exit_interpreter_loop) {
1860 }
1861
1862 private:
1863 static constexpr bool do_assignability_check = do_access_check;
Alex Lightb7c640d2019-03-20 15:52:13 -07001864 static constexpr MonitorState kMonitorState =
1865 do_assignability_check ? MonitorState::kCountingMonitors : MonitorState::kNormalMonitors;
David Srbecky6da82472018-10-23 14:03:08 +01001866
1867 const CodeItemDataAccessor& Accessor() { return ctx->accessor; }
1868 const uint16_t* Insns() { return ctx->accessor.Insns(); }
1869 JValue* ResultRegister() { return &ctx->result_register; }
1870
David Srbecky436f6c12019-05-22 13:28:42 +01001871 ALWAYS_INLINE int32_t A() { return inst->VRegA(kFormat, inst_data); }
1872 ALWAYS_INLINE int32_t B() { return inst->VRegB(kFormat, inst_data); }
1873 ALWAYS_INLINE int32_t C() { return inst->VRegC(kFormat); }
1874
David Srbecky6baf6442019-05-30 14:57:43 +01001875 int32_t GetVReg(size_t i) const { return shadow_frame.GetVReg(i); }
1876 int64_t GetVRegLong(size_t i) const { return shadow_frame.GetVRegLong(i); }
1877 float GetVRegFloat(size_t i) const { return shadow_frame.GetVRegFloat(i); }
1878 double GetVRegDouble(size_t i) const { return shadow_frame.GetVRegDouble(i); }
1879 ObjPtr<mirror::Object> GetVRegReference(size_t i) const REQUIRES_SHARED(Locks::mutator_lock_) {
1880 return shadow_frame.GetVRegReference(i);
1881 }
1882
1883 void SetVReg(size_t i, int32_t val) { shadow_frame.SetVReg(i, val); }
1884 void SetVRegLong(size_t i, int64_t val) { shadow_frame.SetVRegLong(i, val); }
1885 void SetVRegFloat(size_t i, float val) { shadow_frame.SetVRegFloat(i, val); }
1886 void SetVRegDouble(size_t i, double val) { shadow_frame.SetVRegDouble(i, val); }
1887 void SetVRegReference(size_t i, ObjPtr<mirror::Object> val)
1888 REQUIRES_SHARED(Locks::mutator_lock_) {
1889 shadow_frame.SetVRegReference(i, val);
1890 }
1891
David Srbecky8867f3b2019-05-31 20:01:46 +01001892 // Set the next instruction to be executed. It is the 'fall-through' instruction by default.
1893 ALWAYS_INLINE void SetNextInstruction(const Instruction* next_inst) {
1894 DCHECK_LT(next_inst->GetDexPc(Insns()), Accessor().InsnsSizeInCodeUnits());
1895 next = next_inst;
1896 }
1897
David Srbecky6da82472018-10-23 14:03:08 +01001898 SwitchImplContext* const ctx;
1899 const instrumentation::Instrumentation* const instrumentation;
1900 Thread* const self;
1901 ShadowFrame& shadow_frame;
1902 uint32_t const dex_pc;
David Srbeckyc56a23e2019-06-05 17:45:49 +01001903 const Instruction* const inst;
David Srbecky6da82472018-10-23 14:03:08 +01001904 uint16_t const inst_data;
David Srbecky8867f3b2019-05-31 20:01:46 +01001905 const Instruction*& next;
1906
David Srbecky6da82472018-10-23 14:03:08 +01001907 bool& exit_interpreter_loop;
1908};
1909
Alex Light6f22e062018-10-05 15:05:12 -07001910// TODO On ASAN builds this function gets a huge stack frame. Since normally we run in the mterp
1911// this shouldn't cause any problems for stack overflow detection. Remove this once b/117341496 is
1912// fixed.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +01001913template<bool do_access_check, bool transaction_active>
Alex Light6f22e062018-10-05 15:05:12 -07001914ATTRIBUTE_NO_SANITIZE_ADDRESS void ExecuteSwitchImplCpp(SwitchImplContext* ctx) {
David Srbecky946bb092018-03-09 17:23:01 +00001915 Thread* self = ctx->self;
1916 const CodeItemDataAccessor& accessor = ctx->accessor;
1917 ShadowFrame& shadow_frame = ctx->shadow_frame;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02001918 self->VerifyStack();
Sebastien Hertz8ece0502013-08-07 11:26:41 +02001919
1920 uint32_t dex_pc = shadow_frame.GetDexPC();
Mathieu Chartier2cebb242015-04-21 16:50:40 -07001921 const auto* const instrumentation = Runtime::Current()->GetInstrumentation();
Mathieu Chartier808c7a52017-12-15 11:19:33 -08001922 const uint16_t* const insns = accessor.Insns();
David Srbeckyc56a23e2019-06-05 17:45:49 +01001923 const Instruction* next = Instruction::At(insns + dex_pc);
Igor Murashkin6918bf12015-09-27 19:19:06 -07001924
Alex Light0aa7a5a2018-10-10 15:58:14 +00001925 DCHECK(!shadow_frame.GetForceRetryInstruction())
1926 << "Entered interpreter from invoke without retry instruction being handled!";
1927
David Srbecky6da82472018-10-23 14:03:08 +01001928 bool const interpret_one_instruction = ctx->interpret_one_instruction;
1929 while (true) {
David Srbeckyc56a23e2019-06-05 17:45:49 +01001930 const Instruction* const inst = next;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02001931 dex_pc = inst->GetDexPc(insns);
1932 shadow_frame.SetDexPC(dex_pc);
Ian Rogerse94652f2014-12-02 11:13:19 -08001933 TraceExecution(shadow_frame, inst, dex_pc);
David Srbecky8d335b62019-06-06 14:25:42 +01001934 uint16_t inst_data = inst->Fetch16(0);
1935 bool exit = false;
1936 if (InstructionHandler<do_access_check, transaction_active, Instruction::kInvalidFormat>(
1937 ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, next, exit).
1938 Preamble()) {
1939 switch (inst->Opcode(inst_data)) {
David Srbecky8867f3b2019-05-31 20:01:46 +01001940#define OPCODE_CASE(OPCODE, OPCODE_NAME, NAME, FORMAT, i, a, e, v) \
David Srbecky8d335b62019-06-06 14:25:42 +01001941 case OPCODE: { \
1942 DCHECK_EQ(self->IsExceptionPending(), (OPCODE == Instruction::MOVE_EXCEPTION)); \
1943 next = inst->RelativeAt(Instruction::SizeInCodeUnits(Instruction::FORMAT)); \
1944 InstructionHandler<do_access_check, transaction_active, Instruction::FORMAT> handler( \
1945 ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, next, exit); \
1946 if (handler.OPCODE_NAME() && LIKELY(!interpret_one_instruction)) { \
1947 DCHECK(!exit) << NAME; \
1948 continue; \
1949 } \
1950 if (exit) { \
1951 shadow_frame.SetDexPC(dex::kDexNoIndex); \
1952 return; \
1953 } \
1954 break; \
1955 }
1956 DEX_INSTRUCTION_LIST(OPCODE_CASE)
David Srbecky6da82472018-10-23 14:03:08 +01001957#undef OPCODE_CASE
David Srbecky8d335b62019-06-06 14:25:42 +01001958 }
1959 } else {
1960 // Preamble returned false due to debugger event.
1961 if (exit) {
1962 shadow_frame.SetDexPC(dex::kDexNoIndex);
1963 return; // Return statement or debugger forced exit.
1964 }
Sebastien Hertz8ece0502013-08-07 11:26:41 +02001965 }
David Srbecky8d335b62019-06-06 14:25:42 +01001966 if (self->IsExceptionPending()) {
1967 if (!InstructionHandler<do_access_check, transaction_active, Instruction::kInvalidFormat>(
1968 ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, next, exit).
1969 HandlePendingException()) {
1970 shadow_frame.SetDexPC(dex::kDexNoIndex);
1971 return; // Locally unhandled exception - return to caller.
1972 }
1973 // Continue execution in the catch block.
1974 }
1975 if (interpret_one_instruction) {
1976 shadow_frame.SetDexPC(next->GetDexPc(insns)); // Record where we stopped.
1977 ctx->result = ctx->result_register;
1978 return;
David Srbecky6da82472018-10-23 14:03:08 +01001979 }
1980 }
Sebastien Hertz8ece0502013-08-07 11:26:41 +02001981} // NOLINT(readability/fn_size)
1982
Sebastien Hertz8ece0502013-08-07 11:26:41 +02001983} // namespace interpreter
1984} // namespace art
David Srbecky2ee09ff2018-10-24 13:24:22 +01001985
1986#endif // ART_RUNTIME_INTERPRETER_INTERPRETER_SWITCH_IMPL_INL_H_