blob: 7ab88642d73c4563a06bb3cab991dfb549cdca3d [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.
47//
48// The function names must match the names from dex_instruction_list.h and have no arguments.
49//
50// Any relevant execution information is stored in the fields - it should be kept to minimum.
51//
David Srbecky47ad3762018-10-31 12:43:40 +000052// Helper methods may return boolean value - in which case 'false' always means
53// "stop executing current opcode" (which does not necessarily exit the interpreter loop).
54//
David Srbecky436f6c12019-05-22 13:28:42 +010055template<bool do_access_check, bool transaction_active, Instruction::Format kFormat>
David Srbecky6da82472018-10-23 14:03:08 +010056class InstructionHandler {
57 public:
David Srbecky47ad3762018-10-31 12:43:40 +000058 ALWAYS_INLINE WARN_UNUSED bool CheckForceReturn()
59 REQUIRES_SHARED(Locks::mutator_lock_) {
Alex Lightb7c640d2019-03-20 15:52:13 -070060 if (PerformNonStandardReturn<kMonitorState>(self,
61 shadow_frame,
62 ctx->result,
63 instrumentation,
64 Accessor().InsSize(),
65 inst->GetDexPc(Insns()))) {
David Srbecky47ad3762018-10-31 12:43:40 +000066 exit_interpreter_loop = true;
67 return false;
68 }
69 return true;
70 }
71
David Srbecky5f250012018-11-08 14:16:38 +000072 NO_INLINE WARN_UNUSED bool HandlePendingExceptionWithInstrumentationImpl(
David Srbecky47ad3762018-10-31 12:43:40 +000073 const instrumentation::Instrumentation* instr)
74 REQUIRES_SHARED(Locks::mutator_lock_) {
75 DCHECK(self->IsExceptionPending());
76 self->AllowThreadSuspension();
77 if (!CheckForceReturn()) {
78 return false;
79 }
80 if (!MoveToExceptionHandler(self, shadow_frame, instr)) {
81 /* Structured locking is to be enforced for abnormal termination, too. */
82 DoMonitorCheckOnExit<do_assignability_check>(self, &shadow_frame);
83 if (ctx->interpret_one_instruction) {
84 /* Signal mterp to return to caller */
85 shadow_frame.SetDexPC(dex::kDexNoIndex);
86 }
87 ctx->result = JValue(); /* Handled in caller. */
88 exit_interpreter_loop = true;
89 return false; // Return to caller.
90 }
91 if (!CheckForceReturn()) {
92 return false;
93 }
94 int32_t displacement =
95 static_cast<int32_t>(shadow_frame.GetDexPC()) - static_cast<int32_t>(dex_pc);
David Srbecky8867f3b2019-05-31 20:01:46 +010096 SetNextInstruction(inst->RelativeAt(displacement));
David Srbecky47ad3762018-10-31 12:43:40 +000097 return false; // Stop executing this opcode and continue in the exception handler.
98 }
99
David Srbecky5f250012018-11-08 14:16:38 +0000100 // Forwards the call to the NO_INLINE HandlePendingExceptionWithInstrumentationImpl.
101 ALWAYS_INLINE WARN_UNUSED bool HandlePendingExceptionWithInstrumentation(
102 const instrumentation::Instrumentation* instr)
103 REQUIRES_SHARED(Locks::mutator_lock_) {
104 // We need to help the compiler a bit to make the NO_INLINE call efficient.
105 // * All handler fields should be in registers, so we do not want to take the object
106 // address (for 'this' argument). Make a copy of the handler just for the slow path.
107 // * The modifiable fields should also be in registers, so we don't want to store their
108 // address even in the handler copy. Make a copy of them just for the call as well.
David Srbeckyc56a23e2019-06-05 17:45:49 +0100109 const Instruction* next_copy = next;
110 bool exit_copy = exit_interpreter_loop;
David Srbecky436f6c12019-05-22 13:28:42 +0100111 InstructionHandler<do_access_check, transaction_active, kFormat> handler_copy(
David Srbeckyc56a23e2019-06-05 17:45:49 +0100112 ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, next_copy, exit_copy);
David Srbecky5f250012018-11-08 14:16:38 +0000113 bool result = handler_copy.HandlePendingExceptionWithInstrumentationImpl(instr);
David Srbeckyc56a23e2019-06-05 17:45:49 +0100114 next = next_copy;
115 exit_interpreter_loop = exit_copy;
David Srbecky5f250012018-11-08 14:16:38 +0000116 return result;
117 }
118
David Srbecky47ad3762018-10-31 12:43:40 +0000119 ALWAYS_INLINE WARN_UNUSED bool HandlePendingException()
120 REQUIRES_SHARED(Locks::mutator_lock_) {
121 return HandlePendingExceptionWithInstrumentation(instrumentation);
122 }
123
124 ALWAYS_INLINE WARN_UNUSED bool PossiblyHandlePendingExceptionOnInvokeImpl(
125 bool is_exception_pending,
126 const Instruction* next_inst)
127 REQUIRES_SHARED(Locks::mutator_lock_) {
128 if (UNLIKELY(shadow_frame.GetForceRetryInstruction())) {
129 /* Don't need to do anything except clear the flag and exception. We leave the */
130 /* instruction the same so it will be re-executed on the next go-around. */
131 DCHECK(inst->IsInvoke());
132 shadow_frame.SetForceRetryInstruction(false);
133 if (UNLIKELY(is_exception_pending)) {
134 DCHECK(self->IsExceptionPending());
135 if (kIsDebugBuild) {
136 LOG(WARNING) << "Suppressing exception for instruction-retry: "
137 << self->GetException()->Dump();
138 }
139 self->ClearException();
140 }
David Srbecky8867f3b2019-05-31 20:01:46 +0100141 SetNextInstruction(inst);
David Srbecky47ad3762018-10-31 12:43:40 +0000142 } else if (UNLIKELY(is_exception_pending)) {
143 /* Should have succeeded. */
144 DCHECK(!shadow_frame.GetForceRetryInstruction());
145 if (!HandlePendingException()) {
146 return false;
147 }
148 } else {
David Srbecky8867f3b2019-05-31 20:01:46 +0100149 SetNextInstruction(next_inst);
David Srbecky47ad3762018-10-31 12:43:40 +0000150 }
151 return true;
152 }
153
154 ALWAYS_INLINE WARN_UNUSED bool PossiblyHandlePendingException(
155 bool is_exception_pending,
156 const Instruction* next_inst)
157 REQUIRES_SHARED(Locks::mutator_lock_) {
158 /* Should only be on invoke instructions. */
159 DCHECK(!shadow_frame.GetForceRetryInstruction());
160 if (UNLIKELY(is_exception_pending)) {
161 if (!HandlePendingException()) {
162 return false;
163 }
164 } else {
David Srbecky8867f3b2019-05-31 20:01:46 +0100165 SetNextInstruction(next_inst);
David Srbecky47ad3762018-10-31 12:43:40 +0000166 }
167 return true;
168 }
169
170 ALWAYS_INLINE WARN_UNUSED bool HandleMonitorChecks()
171 REQUIRES_SHARED(Locks::mutator_lock_) {
172 if (!DoMonitorCheckOnExit<do_assignability_check>(self, &shadow_frame)) {
173 if (!HandlePendingException()) {
174 return false;
175 }
176 }
177 return true;
178 }
179
180 // Code to run before each dex instruction.
David Srbeckya4a96af2018-10-31 16:34:58 +0000181 ALWAYS_INLINE WARN_UNUSED bool Preamble()
David Srbecky47ad3762018-10-31 12:43:40 +0000182 REQUIRES_SHARED(Locks::mutator_lock_) {
183 /* We need to put this before & after the instrumentation to avoid having to put in a */
184 /* post-script macro. */
185 if (!CheckForceReturn()) {
186 return false;
187 }
188 if (UNLIKELY(instrumentation->HasDexPcListeners())) {
David Srbeckya4a96af2018-10-31 16:34:58 +0000189 uint8_t opcode = inst->Opcode(inst_data);
190 bool is_move_result_object = (opcode == Instruction::MOVE_RESULT_OBJECT);
191 JValue* save_ref = is_move_result_object ? &ctx->result_register : nullptr;
David Srbecky47ad3762018-10-31 12:43:40 +0000192 if (UNLIKELY(!DoDexPcMoveEvent(self,
193 Accessor(),
194 shadow_frame,
195 dex_pc,
196 instrumentation,
197 save_ref))) {
198 if (!HandlePendingException()) {
199 return false;
200 }
201 }
202 if (!CheckForceReturn()) {
203 return false;
204 }
205 }
206 return true;
207 }
208
209 ALWAYS_INLINE WARN_UNUSED bool BranchInstrumentation(int32_t offset)
210 REQUIRES_SHARED(Locks::mutator_lock_) {
211 if (UNLIKELY(instrumentation->HasBranchListeners())) {
212 instrumentation->Branch(self, shadow_frame.GetMethod(), dex_pc, offset);
213 }
214 JValue result;
215 if (jit::Jit::MaybeDoOnStackReplacement(self,
216 shadow_frame.GetMethod(),
217 dex_pc,
218 offset,
219 &result)) {
220 if (ctx->interpret_one_instruction) {
221 /* OSR has completed execution of the method. Signal mterp to return to caller */
222 shadow_frame.SetDexPC(dex::kDexNoIndex);
223 }
224 ctx->result = result;
225 exit_interpreter_loop = true;
226 return false;
227 }
228 return true;
229 }
230
231 ALWAYS_INLINE void HotnessUpdate()
232 REQUIRES_SHARED(Locks::mutator_lock_) {
233 jit::Jit* jit = Runtime::Current()->GetJit();
234 if (jit != nullptr) {
235 jit->AddSamples(self, shadow_frame.GetMethod(), 1, /*with_backedges=*/ true);
236 }
237 }
238
239 ALWAYS_INLINE WARN_UNUSED bool HandleAsyncException()
240 REQUIRES_SHARED(Locks::mutator_lock_) {
241 if (UNLIKELY(self->ObserveAsyncException())) {
242 if (!HandlePendingException()) {
243 return false;
244 }
245 }
246 return true;
247 }
248
249 ALWAYS_INLINE void HandleBackwardBranch(int32_t offset)
250 REQUIRES_SHARED(Locks::mutator_lock_) {
251 if (IsBackwardBranch(offset)) {
252 HotnessUpdate();
253 /* Record new dex pc early to have consistent suspend point at loop header. */
David Srbeckyc56a23e2019-06-05 17:45:49 +0100254 shadow_frame.SetDexPC(next->GetDexPc(Insns()));
David Srbecky47ad3762018-10-31 12:43:40 +0000255 self->AllowThreadSuspension();
256 }
257 }
258
259 // Unlike most other events the DexPcMovedEvent can be sent when there is a pending exception (if
260 // the next instruction is MOVE_EXCEPTION). This means it needs to be handled carefully to be able
261 // to detect exceptions thrown by the DexPcMovedEvent itself. These exceptions could be thrown by
262 // jvmti-agents while handling breakpoint or single step events. We had to move this into its own
263 // function because it was making ExecuteSwitchImpl have too large a stack.
264 NO_INLINE static bool DoDexPcMoveEvent(Thread* self,
265 const CodeItemDataAccessor& accessor,
266 const ShadowFrame& shadow_frame,
267 uint32_t dex_pc,
268 const instrumentation::Instrumentation* instrumentation,
269 JValue* save_ref)
270 REQUIRES_SHARED(Locks::mutator_lock_) {
271 DCHECK(instrumentation->HasDexPcListeners());
272 StackHandleScope<2> hs(self);
273 Handle<mirror::Throwable> thr(hs.NewHandle(self->GetException()));
274 mirror::Object* null_obj = nullptr;
275 HandleWrapper<mirror::Object> h(
276 hs.NewHandleWrapper(LIKELY(save_ref == nullptr) ? &null_obj : save_ref->GetGCRoot()));
277 self->ClearException();
278 instrumentation->DexPcMovedEvent(self,
279 shadow_frame.GetThisObject(accessor.InsSize()),
280 shadow_frame.GetMethod(),
281 dex_pc);
282 if (UNLIKELY(self->IsExceptionPending())) {
283 // We got a new exception in the dex-pc-moved event.
284 // We just let this exception replace the old one.
285 // TODO It would be good to add the old exception to the
286 // suppressed exceptions of the new one if possible.
287 return false;
288 } else {
289 if (UNLIKELY(!thr.IsNull())) {
290 self->SetException(thr.Get());
291 }
292 return true;
293 }
294 }
295
David Srbecky47ad3762018-10-31 12:43:40 +0000296#define BRANCH_INSTRUMENTATION(offset) \
297 if (!BranchInstrumentation(offset)) { \
David Srbeckybd613ec2019-05-30 15:39:38 +0100298 return false; \
David Srbecky47ad3762018-10-31 12:43:40 +0000299 }
300
301#define HANDLE_PENDING_EXCEPTION() \
302 if (!HandlePendingException()) { \
David Srbeckybd613ec2019-05-30 15:39:38 +0100303 return false; \
David Srbecky47ad3762018-10-31 12:43:40 +0000304 }
305
306#define POSSIBLY_HANDLE_PENDING_EXCEPTION(is_exception_pending, next_function) \
307 if (!PossiblyHandlePendingException(is_exception_pending, inst->next_function())) { \
David Srbeckybd613ec2019-05-30 15:39:38 +0100308 return false; \
David Srbecky47ad3762018-10-31 12:43:40 +0000309 }
310
311#define POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(is_exception_pending) \
312 if (!PossiblyHandlePendingExceptionOnInvokeImpl(is_exception_pending, inst->Next_4xx())) { \
David Srbeckybd613ec2019-05-30 15:39:38 +0100313 return false; \
David Srbecky47ad3762018-10-31 12:43:40 +0000314 }
315
316#define POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(is_exception_pending) \
317 if (!PossiblyHandlePendingExceptionOnInvokeImpl(is_exception_pending, inst->Next_3xx())) { \
David Srbeckybd613ec2019-05-30 15:39:38 +0100318 return false; \
David Srbecky47ad3762018-10-31 12:43:40 +0000319 }
320
David Srbeckyee12e3a2019-06-03 15:18:57 +0100321 ALWAYS_INLINE WARN_UNUSED bool HandleReturn(JValue result) REQUIRES_SHARED(Locks::mutator_lock_) {
322 self->AllowThreadSuspension();
323 if (!HandleMonitorChecks()) {
324 return false;
325 }
326 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
327 !SendMethodExitEvents(self,
328 instrumentation,
329 shadow_frame,
330 shadow_frame.GetThisObject(Accessor().InsSize()),
331 shadow_frame.GetMethod(),
332 inst->GetDexPc(Insns()),
333 result))) {
334 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
335 return false;
336 }
337 }
338 if (ctx->interpret_one_instruction) {
339 /* Signal mterp to return to caller */
340 shadow_frame.SetDexPC(dex::kDexNoIndex);
341 }
342 ctx->result = result;
343 exit_interpreter_loop = true;
344 return true;
345 }
346
347 ALWAYS_INLINE WARN_UNUSED bool HandleGoto(int32_t offset) REQUIRES_SHARED(Locks::mutator_lock_) {
348 if (!HandleAsyncException()) {
349 return false;
350 }
351 BRANCH_INSTRUMENTATION(offset);
David Srbecky8867f3b2019-05-31 20:01:46 +0100352 SetNextInstruction(inst->RelativeAt(offset));
David Srbeckyee12e3a2019-06-03 15:18:57 +0100353 HandleBackwardBranch(offset);
354 return true;
355 }
356
357#pragma clang diagnostic push
358#pragma clang diagnostic ignored "-Wfloat-equal"
359
360 template<typename T>
361 ALWAYS_INLINE WARN_UNUSED bool HandleCmpl(T val1, T val2) REQUIRES_SHARED(Locks::mutator_lock_) {
362 int32_t result;
363 if (val1 > val2) {
364 result = 1;
365 } else if (val1 == val2) {
366 result = 0;
367 } else {
368 result = -1;
369 }
370 SetVReg(A(), result);
David Srbeckyee12e3a2019-06-03 15:18:57 +0100371 return true;
372 }
373
374 // Returns the same result as the function above. It only differs for NaN values.
375 template<typename T>
376 ALWAYS_INLINE WARN_UNUSED bool HandleCmpg(T val1, T val2) REQUIRES_SHARED(Locks::mutator_lock_) {
377 int32_t result;
378 if (val1 < val2) {
379 result = -1;
380 } else if (val1 == val2) {
381 result = 0;
382 } else {
383 result = 1;
384 }
385 SetVReg(A(), result);
David Srbeckyee12e3a2019-06-03 15:18:57 +0100386 return true;
387 }
388
389#pragma clang diagnostic pop
390
391 ALWAYS_INLINE WARN_UNUSED bool HandleIf(bool cond, int32_t offset)
392 REQUIRES_SHARED(Locks::mutator_lock_) {
393 if (cond) {
394 BRANCH_INSTRUMENTATION(offset);
David Srbecky8867f3b2019-05-31 20:01:46 +0100395 SetNextInstruction(inst->RelativeAt(offset));
David Srbeckyee12e3a2019-06-03 15:18:57 +0100396 HandleBackwardBranch(offset);
397 } else {
398 BRANCH_INSTRUMENTATION(2);
David Srbeckyee12e3a2019-06-03 15:18:57 +0100399 }
400 return true;
401 }
402
David Srbecky1332c262019-06-04 13:13:37 +0100403 template<typename ArrayType, typename SetVRegFn>
404 ALWAYS_INLINE bool HandleAGet(SetVRegFn setVReg) REQUIRES_SHARED(Locks::mutator_lock_) {
405 ObjPtr<mirror::Object> a = GetVRegReference(B());
406 if (UNLIKELY(a == nullptr)) {
407 ThrowNullPointerExceptionFromInterpreter();
408 HANDLE_PENDING_EXCEPTION();
409 }
410 int32_t index = GetVReg(C());
411 ObjPtr<ArrayType> array = ObjPtr<ArrayType>::DownCast(a);
412 if (UNLIKELY(!array->CheckIsValidIndex(index))) {
413 HANDLE_PENDING_EXCEPTION();
414 } else {
415 (this->*setVReg)(A(), array->GetWithoutChecks(index));
David Srbecky1332c262019-06-04 13:13:37 +0100416 }
417 return true;
418 }
419
420 template<typename ArrayType, typename T>
421 ALWAYS_INLINE bool HandleAPut(T value) REQUIRES_SHARED(Locks::mutator_lock_) {
422 ObjPtr<mirror::Object> a = GetVRegReference(B());
423 if (UNLIKELY(a == nullptr)) {
424 ThrowNullPointerExceptionFromInterpreter();
425 HANDLE_PENDING_EXCEPTION();
426 }
427 int32_t index = GetVReg(C());
428 ObjPtr<ArrayType> array = ObjPtr<ArrayType>::DownCast(a);
429 if (UNLIKELY(!array->CheckIsValidIndex(index))) {
430 HANDLE_PENDING_EXCEPTION();
431 } else {
432 array->template SetWithoutChecks<transaction_active>(index, value);
David Srbecky1332c262019-06-04 13:13:37 +0100433 }
434 return true;
435 }
436
David Srbeckyee12e3a2019-06-03 15:18:57 +0100437 template<FindFieldType find_type, Primitive::Type field_type>
438 ALWAYS_INLINE WARN_UNUSED bool HandleGet() REQUIRES_SHARED(Locks::mutator_lock_) {
439 bool success = DoFieldGet<find_type, field_type, do_access_check, transaction_active>(
440 self, shadow_frame, inst, inst_data);
441 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
442 return true;
443 }
444
445 template<Primitive::Type field_type>
446 ALWAYS_INLINE WARN_UNUSED bool HandleGetQuick() REQUIRES_SHARED(Locks::mutator_lock_) {
447 bool success = DoIGetQuick<field_type>(shadow_frame, inst, inst_data);
448 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
449 return true;
450 }
451
452 template<FindFieldType find_type, Primitive::Type field_type>
453 ALWAYS_INLINE WARN_UNUSED bool HandlePut() REQUIRES_SHARED(Locks::mutator_lock_) {
454 bool success = DoFieldPut<find_type, field_type, do_access_check, transaction_active>(
455 self, shadow_frame, inst, inst_data);
456 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
457 return true;
458 }
459
460 template<Primitive::Type field_type>
461 ALWAYS_INLINE WARN_UNUSED bool HandlePutQuick() REQUIRES_SHARED(Locks::mutator_lock_) {
462 bool success = DoIPutQuick<field_type, transaction_active>(
463 shadow_frame, inst, inst_data);
464 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
465 return true;
466 }
467
468 template<InvokeType type, bool is_range, bool is_quick = false>
469 ALWAYS_INLINE WARN_UNUSED bool HandleInvoke() REQUIRES_SHARED(Locks::mutator_lock_) {
470 bool success = DoInvoke<type, is_range, do_access_check, /*is_mterp=*/ false, is_quick>(
471 self, shadow_frame, inst, inst_data, ResultRegister());
472 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
473 return true;
474 }
475
476 ALWAYS_INLINE WARN_UNUSED bool HandleUnused() REQUIRES_SHARED(Locks::mutator_lock_) {
477 UnexpectedOpcode(inst, shadow_frame);
478 return true;
479 }
480
David Srbeckybd613ec2019-05-30 15:39:38 +0100481 ALWAYS_INLINE bool NOP() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckybd613ec2019-05-30 15:39:38 +0100482 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100483 }
484
David Srbeckybd613ec2019-05-30 15:39:38 +0100485 ALWAYS_INLINE bool MOVE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100486 SetVReg(A(), GetVReg(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +0100487 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100488 }
489
David Srbeckybd613ec2019-05-30 15:39:38 +0100490 ALWAYS_INLINE bool MOVE_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100491 SetVReg(A(), GetVReg(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +0100492 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100493 }
494
David Srbeckybd613ec2019-05-30 15:39:38 +0100495 ALWAYS_INLINE bool MOVE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100496 SetVReg(A(), GetVReg(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +0100497 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100498 }
499
David Srbeckybd613ec2019-05-30 15:39:38 +0100500 ALWAYS_INLINE bool MOVE_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100501 SetVRegLong(A(), GetVRegLong(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +0100502 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100503 }
504
David Srbeckybd613ec2019-05-30 15:39:38 +0100505 ALWAYS_INLINE bool MOVE_WIDE_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100506 SetVRegLong(A(), GetVRegLong(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +0100507 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100508 }
509
David Srbeckybd613ec2019-05-30 15:39:38 +0100510 ALWAYS_INLINE bool MOVE_WIDE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100511 SetVRegLong(A(), GetVRegLong(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +0100512 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100513 }
514
David Srbeckybd613ec2019-05-30 15:39:38 +0100515 ALWAYS_INLINE bool MOVE_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100516 SetVRegReference(A(), GetVRegReference(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +0100517 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100518 }
519
David Srbeckybd613ec2019-05-30 15:39:38 +0100520 ALWAYS_INLINE bool MOVE_OBJECT_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100521 SetVRegReference(A(), GetVRegReference(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +0100522 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100523 }
524
David Srbeckybd613ec2019-05-30 15:39:38 +0100525 ALWAYS_INLINE bool MOVE_OBJECT_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100526 SetVRegReference(A(), GetVRegReference(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +0100527 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100528 }
529
David Srbeckybd613ec2019-05-30 15:39:38 +0100530 ALWAYS_INLINE bool MOVE_RESULT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100531 SetVReg(A(), ResultRegister()->GetI());
David Srbeckybd613ec2019-05-30 15:39:38 +0100532 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100533 }
534
David Srbeckybd613ec2019-05-30 15:39:38 +0100535 ALWAYS_INLINE bool MOVE_RESULT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100536 SetVRegLong(A(), ResultRegister()->GetJ());
David Srbeckybd613ec2019-05-30 15:39:38 +0100537 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100538 }
539
David Srbeckybd613ec2019-05-30 15:39:38 +0100540 ALWAYS_INLINE bool MOVE_RESULT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100541 SetVRegReference(A(), ResultRegister()->GetL());
David Srbeckybd613ec2019-05-30 15:39:38 +0100542 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100543 }
544
David Srbeckybd613ec2019-05-30 15:39:38 +0100545 ALWAYS_INLINE bool MOVE_EXCEPTION() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100546 ObjPtr<mirror::Throwable> exception = self->GetException();
547 DCHECK(exception != nullptr) << "No pending exception on MOVE_EXCEPTION instruction";
David Srbecky6baf6442019-05-30 14:57:43 +0100548 SetVRegReference(A(), exception);
David Srbecky6da82472018-10-23 14:03:08 +0100549 self->ClearException();
David Srbeckybd613ec2019-05-30 15:39:38 +0100550 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100551 }
552
David Srbeckybd613ec2019-05-30 15:39:38 +0100553 ALWAYS_INLINE bool RETURN_VOID_NO_BARRIER() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100554 JValue result;
David Srbeckyee12e3a2019-06-03 15:18:57 +0100555 return HandleReturn(result);
David Srbecky6da82472018-10-23 14:03:08 +0100556 }
557
David Srbeckybd613ec2019-05-30 15:39:38 +0100558 ALWAYS_INLINE bool RETURN_VOID() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100559 QuasiAtomic::ThreadFenceForConstructor();
560 JValue result;
David Srbeckyee12e3a2019-06-03 15:18:57 +0100561 return HandleReturn(result);
David Srbecky6da82472018-10-23 14:03:08 +0100562 }
563
David Srbeckybd613ec2019-05-30 15:39:38 +0100564 ALWAYS_INLINE bool RETURN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100565 JValue result;
566 result.SetJ(0);
David Srbecky6baf6442019-05-30 14:57:43 +0100567 result.SetI(GetVReg(A()));
David Srbeckyee12e3a2019-06-03 15:18:57 +0100568 return HandleReturn(result);
David Srbecky6da82472018-10-23 14:03:08 +0100569 }
570
David Srbeckybd613ec2019-05-30 15:39:38 +0100571 ALWAYS_INLINE bool RETURN_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100572 JValue result;
David Srbecky6baf6442019-05-30 14:57:43 +0100573 result.SetJ(GetVRegLong(A()));
David Srbeckyee12e3a2019-06-03 15:18:57 +0100574 return HandleReturn(result);
David Srbecky6da82472018-10-23 14:03:08 +0100575 }
576
David Srbeckybd613ec2019-05-30 15:39:38 +0100577 ALWAYS_INLINE bool RETURN_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100578 JValue result;
579 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000580 if (!HandleMonitorChecks()) {
David Srbeckybd613ec2019-05-30 15:39:38 +0100581 return false;
David Srbecky47ad3762018-10-31 12:43:40 +0000582 }
David Srbeckyd6f579c2019-05-29 18:09:30 +0100583 const size_t ref_idx = A();
David Srbecky6baf6442019-05-30 14:57:43 +0100584 ObjPtr<mirror::Object> obj_result = GetVRegReference(ref_idx);
David Srbecky6da82472018-10-23 14:03:08 +0100585 if (do_assignability_check && obj_result != nullptr) {
586 ObjPtr<mirror::Class> return_type = shadow_frame.GetMethod()->ResolveReturnType();
587 // Re-load since it might have moved.
David Srbecky6baf6442019-05-30 14:57:43 +0100588 obj_result = GetVRegReference(ref_idx);
David Srbecky6da82472018-10-23 14:03:08 +0100589 if (return_type == nullptr) {
590 // Return the pending exception.
591 HANDLE_PENDING_EXCEPTION();
592 }
593 if (!obj_result->VerifierInstanceOf(return_type)) {
594 // This should never happen.
595 std::string temp1, temp2;
596 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
597 "Returning '%s' that is not instance of return type '%s'",
598 obj_result->GetClass()->GetDescriptor(&temp1),
599 return_type->GetDescriptor(&temp2));
600 HANDLE_PENDING_EXCEPTION();
601 }
602 }
Alex Lightb7c640d2019-03-20 15:52:13 -0700603 StackHandleScope<1> hs(self);
604 MutableHandle<mirror::Object> h_result(hs.NewHandle(obj_result));
David Srbecky6da82472018-10-23 14:03:08 +0100605 result.SetL(obj_result);
606 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
607 !SendMethodExitEvents(self,
608 instrumentation,
609 shadow_frame,
610 shadow_frame.GetThisObject(Accessor().InsSize()),
611 shadow_frame.GetMethod(),
612 inst->GetDexPc(Insns()),
Alex Lightb7c640d2019-03-20 15:52:13 -0700613 h_result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000614 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
David Srbeckybd613ec2019-05-30 15:39:38 +0100615 return false;
David Srbecky47ad3762018-10-31 12:43:40 +0000616 }
David Srbecky6da82472018-10-23 14:03:08 +0100617 }
Alex Lightb7c640d2019-03-20 15:52:13 -0700618 // Re-load since it might have moved or been replaced during the MethodExitEvent.
619 result.SetL(h_result.Get());
David Srbecky6da82472018-10-23 14:03:08 +0100620 if (ctx->interpret_one_instruction) {
621 /* Signal mterp to return to caller */
622 shadow_frame.SetDexPC(dex::kDexNoIndex);
623 }
624 ctx->result = result;
625 exit_interpreter_loop = true;
David Srbeckybd613ec2019-05-30 15:39:38 +0100626 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100627 }
628
David Srbeckybd613ec2019-05-30 15:39:38 +0100629 ALWAYS_INLINE bool CONST_4() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100630 uint4_t dst = inst->VRegA_11n(inst_data);
631 int4_t val = inst->VRegB_11n(inst_data);
David Srbecky6baf6442019-05-30 14:57:43 +0100632 SetVReg(dst, val);
David Srbecky6da82472018-10-23 14:03:08 +0100633 if (val == 0) {
David Srbecky6baf6442019-05-30 14:57:43 +0100634 SetVRegReference(dst, nullptr);
David Srbecky6da82472018-10-23 14:03:08 +0100635 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100636 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100637 }
638
David Srbeckybd613ec2019-05-30 15:39:38 +0100639 ALWAYS_INLINE bool CONST_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100640 uint8_t dst = A();
641 int16_t val = B();
David Srbecky6baf6442019-05-30 14:57:43 +0100642 SetVReg(dst, val);
David Srbecky6da82472018-10-23 14:03:08 +0100643 if (val == 0) {
David Srbecky6baf6442019-05-30 14:57:43 +0100644 SetVRegReference(dst, nullptr);
David Srbecky6da82472018-10-23 14:03:08 +0100645 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100646 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100647 }
648
David Srbeckybd613ec2019-05-30 15:39:38 +0100649 ALWAYS_INLINE bool CONST() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100650 uint8_t dst = A();
651 int32_t val = B();
David Srbecky6baf6442019-05-30 14:57:43 +0100652 SetVReg(dst, val);
David Srbecky6da82472018-10-23 14:03:08 +0100653 if (val == 0) {
David Srbecky6baf6442019-05-30 14:57:43 +0100654 SetVRegReference(dst, nullptr);
David Srbecky6da82472018-10-23 14:03:08 +0100655 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100656 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100657 }
658
David Srbeckybd613ec2019-05-30 15:39:38 +0100659 ALWAYS_INLINE bool CONST_HIGH16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100660 uint8_t dst = A();
661 int32_t val = static_cast<int32_t>(B() << 16);
David Srbecky6baf6442019-05-30 14:57:43 +0100662 SetVReg(dst, val);
David Srbecky6da82472018-10-23 14:03:08 +0100663 if (val == 0) {
David Srbecky6baf6442019-05-30 14:57:43 +0100664 SetVRegReference(dst, nullptr);
David Srbecky6da82472018-10-23 14:03:08 +0100665 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100666 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100667 }
668
David Srbeckybd613ec2019-05-30 15:39:38 +0100669 ALWAYS_INLINE bool CONST_WIDE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100670 SetVRegLong(A(), B());
David Srbeckybd613ec2019-05-30 15:39:38 +0100671 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100672 }
673
David Srbeckybd613ec2019-05-30 15:39:38 +0100674 ALWAYS_INLINE bool CONST_WIDE_32() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100675 SetVRegLong(A(), B());
David Srbeckybd613ec2019-05-30 15:39:38 +0100676 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100677 }
678
David Srbeckybd613ec2019-05-30 15:39:38 +0100679 ALWAYS_INLINE bool CONST_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100680 SetVRegLong(A(), inst->WideVRegB());
David Srbeckybd613ec2019-05-30 15:39:38 +0100681 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100682 }
683
David Srbeckybd613ec2019-05-30 15:39:38 +0100684 ALWAYS_INLINE bool CONST_WIDE_HIGH16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100685 SetVRegLong(A(), static_cast<uint64_t>(B()) << 48);
David Srbeckybd613ec2019-05-30 15:39:38 +0100686 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100687 }
688
David Srbeckybd613ec2019-05-30 15:39:38 +0100689 ALWAYS_INLINE bool CONST_STRING() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100690 ObjPtr<mirror::String> s = ResolveString(self, shadow_frame, dex::StringIndex(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100691 if (UNLIKELY(s == nullptr)) {
692 HANDLE_PENDING_EXCEPTION();
693 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100694 SetVRegReference(A(), s);
David Srbecky6da82472018-10-23 14:03:08 +0100695 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100696 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100697 }
698
David Srbeckybd613ec2019-05-30 15:39:38 +0100699 ALWAYS_INLINE bool CONST_STRING_JUMBO() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100700 ObjPtr<mirror::String> s = ResolveString(self, shadow_frame, dex::StringIndex(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100701 if (UNLIKELY(s == nullptr)) {
702 HANDLE_PENDING_EXCEPTION();
703 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100704 SetVRegReference(A(), s);
David Srbecky6da82472018-10-23 14:03:08 +0100705 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100706 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100707 }
708
David Srbeckybd613ec2019-05-30 15:39:38 +0100709 ALWAYS_INLINE bool CONST_CLASS() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100710 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(B()),
David Srbecky6da82472018-10-23 14:03:08 +0100711 shadow_frame.GetMethod(),
712 self,
713 false,
714 do_access_check);
715 if (UNLIKELY(c == nullptr)) {
716 HANDLE_PENDING_EXCEPTION();
717 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100718 SetVRegReference(A(), c);
David Srbecky6da82472018-10-23 14:03:08 +0100719 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100720 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100721 }
722
David Srbeckybd613ec2019-05-30 15:39:38 +0100723 ALWAYS_INLINE bool CONST_METHOD_HANDLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100724 ClassLinker* cl = Runtime::Current()->GetClassLinker();
725 ObjPtr<mirror::MethodHandle> mh = cl->ResolveMethodHandle(self,
David Srbeckyd6f579c2019-05-29 18:09:30 +0100726 B(),
David Srbecky6da82472018-10-23 14:03:08 +0100727 shadow_frame.GetMethod());
728 if (UNLIKELY(mh == nullptr)) {
729 HANDLE_PENDING_EXCEPTION();
730 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100731 SetVRegReference(A(), mh);
David Srbecky6da82472018-10-23 14:03:08 +0100732 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100733 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100734 }
735
David Srbeckybd613ec2019-05-30 15:39:38 +0100736 ALWAYS_INLINE bool CONST_METHOD_TYPE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100737 ClassLinker* cl = Runtime::Current()->GetClassLinker();
738 ObjPtr<mirror::MethodType> mt = cl->ResolveMethodType(self,
David Srbeckyd6f579c2019-05-29 18:09:30 +0100739 dex::ProtoIndex(B()),
David Srbecky6da82472018-10-23 14:03:08 +0100740 shadow_frame.GetMethod());
741 if (UNLIKELY(mt == nullptr)) {
742 HANDLE_PENDING_EXCEPTION();
743 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100744 SetVRegReference(A(), mt);
David Srbecky6da82472018-10-23 14:03:08 +0100745 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100746 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100747 }
748
David Srbeckybd613ec2019-05-30 15:39:38 +0100749 ALWAYS_INLINE bool MONITOR_ENTER() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000750 if (!HandleAsyncException()) {
David Srbeckybd613ec2019-05-30 15:39:38 +0100751 return false;
David Srbecky47ad3762018-10-31 12:43:40 +0000752 }
David Srbecky6baf6442019-05-30 14:57:43 +0100753 ObjPtr<mirror::Object> obj = GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +0100754 if (UNLIKELY(obj == nullptr)) {
755 ThrowNullPointerExceptionFromInterpreter();
756 HANDLE_PENDING_EXCEPTION();
757 } else {
758 DoMonitorEnter<do_assignability_check>(self, &shadow_frame, obj);
759 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
760 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100761 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100762 }
763
David Srbeckybd613ec2019-05-30 15:39:38 +0100764 ALWAYS_INLINE bool MONITOR_EXIT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000765 if (!HandleAsyncException()) {
David Srbeckybd613ec2019-05-30 15:39:38 +0100766 return false;
David Srbecky47ad3762018-10-31 12:43:40 +0000767 }
David Srbecky6baf6442019-05-30 14:57:43 +0100768 ObjPtr<mirror::Object> obj = GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +0100769 if (UNLIKELY(obj == nullptr)) {
770 ThrowNullPointerExceptionFromInterpreter();
771 HANDLE_PENDING_EXCEPTION();
772 } else {
773 DoMonitorExit<do_assignability_check>(self, &shadow_frame, obj);
774 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
775 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100776 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100777 }
778
David Srbeckybd613ec2019-05-30 15:39:38 +0100779 ALWAYS_INLINE bool CHECK_CAST() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100780 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(B()),
David Srbecky6da82472018-10-23 14:03:08 +0100781 shadow_frame.GetMethod(),
782 self,
783 false,
784 do_access_check);
785 if (UNLIKELY(c == nullptr)) {
786 HANDLE_PENDING_EXCEPTION();
787 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100788 ObjPtr<mirror::Object> obj = GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +0100789 if (UNLIKELY(obj != nullptr && !obj->InstanceOf(c))) {
790 ThrowClassCastException(c, obj->GetClass());
791 HANDLE_PENDING_EXCEPTION();
David Srbecky6da82472018-10-23 14:03:08 +0100792 }
793 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100794 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100795 }
796
David Srbeckybd613ec2019-05-30 15:39:38 +0100797 ALWAYS_INLINE bool INSTANCE_OF() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100798 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(C()),
David Srbecky6da82472018-10-23 14:03:08 +0100799 shadow_frame.GetMethod(),
800 self,
801 false,
802 do_access_check);
803 if (UNLIKELY(c == nullptr)) {
804 HANDLE_PENDING_EXCEPTION();
805 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100806 ObjPtr<mirror::Object> obj = GetVRegReference(B());
807 SetVReg(A(), (obj != nullptr && obj->InstanceOf(c)) ? 1 : 0);
David Srbecky6da82472018-10-23 14:03:08 +0100808 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100809 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100810 }
811
David Srbeckybd613ec2019-05-30 15:39:38 +0100812 ALWAYS_INLINE bool ARRAY_LENGTH() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100813 ObjPtr<mirror::Object> array = GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +0100814 if (UNLIKELY(array == nullptr)) {
815 ThrowNullPointerExceptionFromInterpreter();
816 HANDLE_PENDING_EXCEPTION();
817 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100818 SetVReg(A(), array->AsArray()->GetLength());
David Srbecky6da82472018-10-23 14:03:08 +0100819 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100820 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100821 }
822
David Srbeckybd613ec2019-05-30 15:39:38 +0100823 ALWAYS_INLINE bool NEW_INSTANCE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100824 ObjPtr<mirror::Object> obj = nullptr;
David Srbeckyd6f579c2019-05-29 18:09:30 +0100825 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(B()),
David Srbecky6da82472018-10-23 14:03:08 +0100826 shadow_frame.GetMethod(),
827 self,
828 false,
829 do_access_check);
830 if (LIKELY(c != nullptr)) {
Vladimir Marko9b81ac32019-05-16 16:47:08 +0100831 gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
David Srbecky6da82472018-10-23 14:03:08 +0100832 if (UNLIKELY(c->IsStringClass())) {
Vladimir Marko9b81ac32019-05-16 16:47:08 +0100833 obj = mirror::String::AllocEmptyString(self, allocator_type);
David Srbecky6da82472018-10-23 14:03:08 +0100834 } else {
Vladimir Marko9b81ac32019-05-16 16:47:08 +0100835 obj = AllocObjectFromCode(c, self, allocator_type);
David Srbecky6da82472018-10-23 14:03:08 +0100836 }
837 }
838 if (UNLIKELY(obj == nullptr)) {
839 HANDLE_PENDING_EXCEPTION();
840 } else {
841 obj->GetClass()->AssertInitializedOrInitializingInThread(self);
842 // Don't allow finalizable objects to be allocated during a transaction since these can't
843 // be finalized without a started runtime.
844 if (transaction_active && obj->GetClass()->IsFinalizable()) {
845 AbortTransactionF(self, "Allocating finalizable object in transaction: %s",
846 obj->PrettyTypeOf().c_str());
847 HANDLE_PENDING_EXCEPTION();
848 }
David Srbecky6baf6442019-05-30 14:57:43 +0100849 SetVRegReference(A(), obj);
David Srbecky6da82472018-10-23 14:03:08 +0100850 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100851 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100852 }
853
David Srbeckybd613ec2019-05-30 15:39:38 +0100854 ALWAYS_INLINE bool NEW_ARRAY() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100855 int32_t length = GetVReg(B());
Vladimir Marko9b81ac32019-05-16 16:47:08 +0100856 ObjPtr<mirror::Object> obj = AllocArrayFromCode<do_access_check>(
David Srbeckyd6f579c2019-05-29 18:09:30 +0100857 dex::TypeIndex(C()),
David Srbecky6da82472018-10-23 14:03:08 +0100858 length,
859 shadow_frame.GetMethod(),
860 self,
861 Runtime::Current()->GetHeap()->GetCurrentAllocator());
862 if (UNLIKELY(obj == nullptr)) {
863 HANDLE_PENDING_EXCEPTION();
864 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100865 SetVRegReference(A(), obj);
David Srbecky6da82472018-10-23 14:03:08 +0100866 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100867 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100868 }
869
David Srbeckybd613ec2019-05-30 15:39:38 +0100870 ALWAYS_INLINE bool FILLED_NEW_ARRAY() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100871 bool success =
872 DoFilledNewArray<false, do_access_check, transaction_active>(inst, shadow_frame, self,
873 ResultRegister());
874 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
David Srbeckybd613ec2019-05-30 15:39:38 +0100875 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100876 }
877
David Srbeckybd613ec2019-05-30 15:39:38 +0100878 ALWAYS_INLINE bool FILLED_NEW_ARRAY_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100879 bool success =
880 DoFilledNewArray<true, do_access_check, transaction_active>(inst, shadow_frame,
881 self, ResultRegister());
882 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
David Srbeckybd613ec2019-05-30 15:39:38 +0100883 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100884 }
885
David Srbeckybd613ec2019-05-30 15:39:38 +0100886 ALWAYS_INLINE bool FILL_ARRAY_DATA() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100887 const uint16_t* payload_addr = reinterpret_cast<const uint16_t*>(inst) + B();
David Srbecky6da82472018-10-23 14:03:08 +0100888 const Instruction::ArrayDataPayload* payload =
889 reinterpret_cast<const Instruction::ArrayDataPayload*>(payload_addr);
David Srbecky6baf6442019-05-30 14:57:43 +0100890 ObjPtr<mirror::Object> obj = GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +0100891 bool success = FillArrayData(obj, payload);
892 if (!success) {
893 HANDLE_PENDING_EXCEPTION();
894 }
895 if (transaction_active) {
896 RecordArrayElementsInTransaction(obj->AsArray(), payload->element_count);
897 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100898 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100899 }
900
David Srbeckybd613ec2019-05-30 15:39:38 +0100901 ALWAYS_INLINE bool THROW() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000902 if (!HandleAsyncException()) {
David Srbeckybd613ec2019-05-30 15:39:38 +0100903 return false;
David Srbecky47ad3762018-10-31 12:43:40 +0000904 }
David Srbecky6baf6442019-05-30 14:57:43 +0100905 ObjPtr<mirror::Object> exception = GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +0100906 if (UNLIKELY(exception == nullptr)) {
907 ThrowNullPointerException("throw with null exception");
908 } else if (do_assignability_check && !exception->GetClass()->IsThrowableClass()) {
909 // This should never happen.
910 std::string temp;
911 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
912 "Throwing '%s' that is not instance of Throwable",
913 exception->GetClass()->GetDescriptor(&temp));
914 } else {
915 self->SetException(exception->AsThrowable());
916 }
917 HANDLE_PENDING_EXCEPTION();
David Srbeckybd613ec2019-05-30 15:39:38 +0100918 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100919 }
920
David Srbeckybd613ec2019-05-30 15:39:38 +0100921 ALWAYS_INLINE bool GOTO() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100922 return HandleGoto(A());
David Srbecky6da82472018-10-23 14:03:08 +0100923 }
924
David Srbeckybd613ec2019-05-30 15:39:38 +0100925 ALWAYS_INLINE bool GOTO_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100926 return HandleGoto(A());
David Srbecky6da82472018-10-23 14:03:08 +0100927 }
928
David Srbeckybd613ec2019-05-30 15:39:38 +0100929 ALWAYS_INLINE bool GOTO_32() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100930 return HandleGoto(A());
David Srbecky6da82472018-10-23 14:03:08 +0100931 }
932
David Srbeckybd613ec2019-05-30 15:39:38 +0100933 ALWAYS_INLINE bool PACKED_SWITCH() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100934 int32_t offset = DoPackedSwitch(inst, shadow_frame, inst_data);
935 BRANCH_INSTRUMENTATION(offset);
David Srbecky8867f3b2019-05-31 20:01:46 +0100936 SetNextInstruction(inst->RelativeAt(offset));
David Srbecky47ad3762018-10-31 12:43:40 +0000937 HandleBackwardBranch(offset);
David Srbeckybd613ec2019-05-30 15:39:38 +0100938 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100939 }
940
David Srbeckybd613ec2019-05-30 15:39:38 +0100941 ALWAYS_INLINE bool SPARSE_SWITCH() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100942 int32_t offset = DoSparseSwitch(inst, shadow_frame, inst_data);
943 BRANCH_INSTRUMENTATION(offset);
David Srbecky8867f3b2019-05-31 20:01:46 +0100944 SetNextInstruction(inst->RelativeAt(offset));
David Srbecky47ad3762018-10-31 12:43:40 +0000945 HandleBackwardBranch(offset);
David Srbeckybd613ec2019-05-30 15:39:38 +0100946 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100947 }
948
David Srbeckybd613ec2019-05-30 15:39:38 +0100949 ALWAYS_INLINE bool CMPL_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100950 return HandleCmpl<float>(GetVRegFloat(B()), GetVRegFloat(C()));
David Srbecky6da82472018-10-23 14:03:08 +0100951 }
952
David Srbeckybd613ec2019-05-30 15:39:38 +0100953 ALWAYS_INLINE bool CMPG_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100954 return HandleCmpg<float>(GetVRegFloat(B()), GetVRegFloat(C()));
David Srbecky6da82472018-10-23 14:03:08 +0100955 }
956
David Srbeckybd613ec2019-05-30 15:39:38 +0100957 ALWAYS_INLINE bool CMPL_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100958 return HandleCmpl<double>(GetVRegDouble(B()), GetVRegDouble(C()));
David Srbecky6da82472018-10-23 14:03:08 +0100959 }
960
David Srbeckybd613ec2019-05-30 15:39:38 +0100961 ALWAYS_INLINE bool CMPG_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100962 return HandleCmpg<double>(GetVRegDouble(B()), GetVRegDouble(C()));
David Srbecky6da82472018-10-23 14:03:08 +0100963 }
964
David Srbeckybd613ec2019-05-30 15:39:38 +0100965 ALWAYS_INLINE bool CMP_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100966 return HandleCmpl<int64_t>(GetVRegLong(B()), GetVRegLong(C()));
David Srbecky6da82472018-10-23 14:03:08 +0100967 }
968
David Srbeckybd613ec2019-05-30 15:39:38 +0100969 ALWAYS_INLINE bool IF_EQ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100970 return HandleIf(GetVReg(A()) == GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +0100971 }
972
David Srbeckybd613ec2019-05-30 15:39:38 +0100973 ALWAYS_INLINE bool IF_NE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100974 return HandleIf(GetVReg(A()) != GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +0100975 }
976
David Srbeckybd613ec2019-05-30 15:39:38 +0100977 ALWAYS_INLINE bool IF_LT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100978 return HandleIf(GetVReg(A()) < GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +0100979 }
980
David Srbeckybd613ec2019-05-30 15:39:38 +0100981 ALWAYS_INLINE bool IF_GE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100982 return HandleIf(GetVReg(A()) >= GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +0100983 }
984
David Srbeckybd613ec2019-05-30 15:39:38 +0100985 ALWAYS_INLINE bool IF_GT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100986 return HandleIf(GetVReg(A()) > GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +0100987 }
988
David Srbeckybd613ec2019-05-30 15:39:38 +0100989 ALWAYS_INLINE bool IF_LE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100990 return HandleIf(GetVReg(A()) <= GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +0100991 }
992
David Srbeckybd613ec2019-05-30 15:39:38 +0100993 ALWAYS_INLINE bool IF_EQZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100994 return HandleIf(GetVReg(A()) == 0, B());
David Srbecky6da82472018-10-23 14:03:08 +0100995 }
996
David Srbeckybd613ec2019-05-30 15:39:38 +0100997 ALWAYS_INLINE bool IF_NEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100998 return HandleIf(GetVReg(A()) != 0, B());
David Srbecky6da82472018-10-23 14:03:08 +0100999 }
1000
David Srbeckybd613ec2019-05-30 15:39:38 +01001001 ALWAYS_INLINE bool IF_LTZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001002 return HandleIf(GetVReg(A()) < 0, B());
David Srbecky6da82472018-10-23 14:03:08 +01001003 }
1004
David Srbeckybd613ec2019-05-30 15:39:38 +01001005 ALWAYS_INLINE bool IF_GEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001006 return HandleIf(GetVReg(A()) >= 0, B());
David Srbecky6da82472018-10-23 14:03:08 +01001007 }
1008
David Srbeckybd613ec2019-05-30 15:39:38 +01001009 ALWAYS_INLINE bool IF_GTZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001010 return HandleIf(GetVReg(A()) > 0, B());
David Srbecky6da82472018-10-23 14:03:08 +01001011 }
1012
David Srbeckybd613ec2019-05-30 15:39:38 +01001013 ALWAYS_INLINE bool IF_LEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001014 return HandleIf(GetVReg(A()) <= 0, B());
David Srbecky6da82472018-10-23 14:03:08 +01001015 }
1016
David Srbeckybd613ec2019-05-30 15:39:38 +01001017 ALWAYS_INLINE bool AGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001018 return HandleAGet<mirror::BooleanArray>(&InstructionHandler::SetVReg);
David Srbecky6da82472018-10-23 14:03:08 +01001019 }
1020
David Srbeckybd613ec2019-05-30 15:39:38 +01001021 ALWAYS_INLINE bool AGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001022 return HandleAGet<mirror::ByteArray>(&InstructionHandler::SetVReg);
David Srbecky6da82472018-10-23 14:03:08 +01001023 }
1024
David Srbeckybd613ec2019-05-30 15:39:38 +01001025 ALWAYS_INLINE bool AGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001026 return HandleAGet<mirror::CharArray>(&InstructionHandler::SetVReg);
David Srbecky6da82472018-10-23 14:03:08 +01001027 }
1028
David Srbeckybd613ec2019-05-30 15:39:38 +01001029 ALWAYS_INLINE bool AGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001030 return HandleAGet<mirror::ShortArray>(&InstructionHandler::SetVReg);
David Srbecky6da82472018-10-23 14:03:08 +01001031 }
1032
David Srbeckybd613ec2019-05-30 15:39:38 +01001033 ALWAYS_INLINE bool AGET() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001034 return HandleAGet<mirror::IntArray>(&InstructionHandler::SetVReg);
David Srbecky6da82472018-10-23 14:03:08 +01001035 }
1036
David Srbeckybd613ec2019-05-30 15:39:38 +01001037 ALWAYS_INLINE bool AGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001038 return HandleAGet<mirror::LongArray>(&InstructionHandler::SetVRegLong);
David Srbecky6da82472018-10-23 14:03:08 +01001039 }
1040
David Srbeckybd613ec2019-05-30 15:39:38 +01001041 ALWAYS_INLINE bool AGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001042 return HandleAGet<mirror::ObjectArray<mirror::Object>>(&InstructionHandler::SetVRegReference);
David Srbecky6da82472018-10-23 14:03:08 +01001043 }
1044
David Srbeckybd613ec2019-05-30 15:39:38 +01001045 ALWAYS_INLINE bool APUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001046 return HandleAPut<mirror::BooleanArray>(GetVReg(A()));
David Srbecky6da82472018-10-23 14:03:08 +01001047 }
1048
David Srbeckybd613ec2019-05-30 15:39:38 +01001049 ALWAYS_INLINE bool APUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001050 return HandleAPut<mirror::ByteArray>(GetVReg(A()));
David Srbecky6da82472018-10-23 14:03:08 +01001051 }
1052
David Srbeckybd613ec2019-05-30 15:39:38 +01001053 ALWAYS_INLINE bool APUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001054 return HandleAPut<mirror::CharArray>(GetVReg(A()));
David Srbecky6da82472018-10-23 14:03:08 +01001055 }
1056
David Srbeckybd613ec2019-05-30 15:39:38 +01001057 ALWAYS_INLINE bool APUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001058 return HandleAPut<mirror::ShortArray>(GetVReg(A()));
David Srbecky6da82472018-10-23 14:03:08 +01001059 }
1060
David Srbeckybd613ec2019-05-30 15:39:38 +01001061 ALWAYS_INLINE bool APUT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001062 return HandleAPut<mirror::IntArray>(GetVReg(A()));
David Srbecky6da82472018-10-23 14:03:08 +01001063 }
1064
David Srbeckybd613ec2019-05-30 15:39:38 +01001065 ALWAYS_INLINE bool APUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001066 return HandleAPut<mirror::LongArray>(GetVRegLong(A()));
David Srbecky6da82472018-10-23 14:03:08 +01001067 }
1068
David Srbeckybd613ec2019-05-30 15:39:38 +01001069 ALWAYS_INLINE bool APUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001070 ObjPtr<mirror::Object> a = GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001071 if (UNLIKELY(a == nullptr)) {
1072 ThrowNullPointerExceptionFromInterpreter();
1073 HANDLE_PENDING_EXCEPTION();
1074 }
David Srbecky6baf6442019-05-30 14:57:43 +01001075 int32_t index = GetVReg(C());
1076 ObjPtr<mirror::Object> val = GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +01001077 ObjPtr<mirror::ObjectArray<mirror::Object>> array = a->AsObjectArray<mirror::Object>();
1078 if (array->CheckIsValidIndex(index) && array->CheckAssignable(val)) {
1079 array->SetWithoutChecks<transaction_active>(index, val);
David Srbecky6da82472018-10-23 14:03:08 +01001080 } else {
1081 HANDLE_PENDING_EXCEPTION();
1082 }
David Srbeckybd613ec2019-05-30 15:39:38 +01001083 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001084 }
1085
David Srbeckybd613ec2019-05-30 15:39:38 +01001086 ALWAYS_INLINE bool IGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001087 return HandleGet<InstancePrimitiveRead, Primitive::kPrimBoolean>();
David Srbecky6da82472018-10-23 14:03:08 +01001088 }
1089
David Srbeckybd613ec2019-05-30 15:39:38 +01001090 ALWAYS_INLINE bool IGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001091 return HandleGet<InstancePrimitiveRead, Primitive::kPrimByte>();
David Srbecky6da82472018-10-23 14:03:08 +01001092 }
1093
David Srbeckybd613ec2019-05-30 15:39:38 +01001094 ALWAYS_INLINE bool IGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001095 return HandleGet<InstancePrimitiveRead, Primitive::kPrimChar>();
David Srbecky6da82472018-10-23 14:03:08 +01001096 }
1097
David Srbeckybd613ec2019-05-30 15:39:38 +01001098 ALWAYS_INLINE bool IGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001099 return HandleGet<InstancePrimitiveRead, Primitive::kPrimShort>();
David Srbecky6da82472018-10-23 14:03:08 +01001100 }
1101
David Srbeckybd613ec2019-05-30 15:39:38 +01001102 ALWAYS_INLINE bool IGET() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001103 return HandleGet<InstancePrimitiveRead, Primitive::kPrimInt>();
David Srbecky6da82472018-10-23 14:03:08 +01001104 }
1105
David Srbeckybd613ec2019-05-30 15:39:38 +01001106 ALWAYS_INLINE bool IGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001107 return HandleGet<InstancePrimitiveRead, Primitive::kPrimLong>();
David Srbecky6da82472018-10-23 14:03:08 +01001108 }
1109
David Srbeckybd613ec2019-05-30 15:39:38 +01001110 ALWAYS_INLINE bool IGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001111 return HandleGet<InstanceObjectRead, Primitive::kPrimNot>();
David Srbecky6da82472018-10-23 14:03:08 +01001112 }
1113
David Srbeckybd613ec2019-05-30 15:39:38 +01001114 ALWAYS_INLINE bool IGET_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001115 return HandleGetQuick<Primitive::kPrimInt>();
David Srbecky6da82472018-10-23 14:03:08 +01001116 }
1117
David Srbeckybd613ec2019-05-30 15:39:38 +01001118 ALWAYS_INLINE bool IGET_WIDE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001119 return HandleGetQuick<Primitive::kPrimLong>();
David Srbecky6da82472018-10-23 14:03:08 +01001120 }
1121
David Srbeckybd613ec2019-05-30 15:39:38 +01001122 ALWAYS_INLINE bool IGET_OBJECT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001123 return HandleGetQuick<Primitive::kPrimNot>();
David Srbecky6da82472018-10-23 14:03:08 +01001124 }
1125
David Srbeckybd613ec2019-05-30 15:39:38 +01001126 ALWAYS_INLINE bool IGET_BOOLEAN_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001127 return HandleGetQuick<Primitive::kPrimBoolean>();
David Srbecky6da82472018-10-23 14:03:08 +01001128 }
1129
David Srbeckybd613ec2019-05-30 15:39:38 +01001130 ALWAYS_INLINE bool IGET_BYTE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001131 return HandleGetQuick<Primitive::kPrimByte>();
David Srbecky6da82472018-10-23 14:03:08 +01001132 }
1133
David Srbeckybd613ec2019-05-30 15:39:38 +01001134 ALWAYS_INLINE bool IGET_CHAR_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001135 return HandleGetQuick<Primitive::kPrimChar>();
David Srbecky6da82472018-10-23 14:03:08 +01001136 }
1137
David Srbeckybd613ec2019-05-30 15:39:38 +01001138 ALWAYS_INLINE bool IGET_SHORT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001139 return HandleGetQuick<Primitive::kPrimShort>();
David Srbecky6da82472018-10-23 14:03:08 +01001140 }
1141
David Srbeckybd613ec2019-05-30 15:39:38 +01001142 ALWAYS_INLINE bool SGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001143 return HandleGet<StaticPrimitiveRead, Primitive::kPrimBoolean>();
David Srbecky6da82472018-10-23 14:03:08 +01001144 }
1145
David Srbeckybd613ec2019-05-30 15:39:38 +01001146 ALWAYS_INLINE bool SGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001147 return HandleGet<StaticPrimitiveRead, Primitive::kPrimByte>();
David Srbecky6da82472018-10-23 14:03:08 +01001148 }
1149
David Srbeckybd613ec2019-05-30 15:39:38 +01001150 ALWAYS_INLINE bool SGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001151 return HandleGet<StaticPrimitiveRead, Primitive::kPrimChar>();
David Srbecky6da82472018-10-23 14:03:08 +01001152 }
1153
David Srbeckybd613ec2019-05-30 15:39:38 +01001154 ALWAYS_INLINE bool SGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001155 return HandleGet<StaticPrimitiveRead, Primitive::kPrimShort>();
David Srbecky6da82472018-10-23 14:03:08 +01001156 }
1157
David Srbeckybd613ec2019-05-30 15:39:38 +01001158 ALWAYS_INLINE bool SGET() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001159 return HandleGet<StaticPrimitiveRead, Primitive::kPrimInt>();
David Srbecky6da82472018-10-23 14:03:08 +01001160 }
1161
David Srbeckybd613ec2019-05-30 15:39:38 +01001162 ALWAYS_INLINE bool SGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001163 return HandleGet<StaticPrimitiveRead, Primitive::kPrimLong>();
David Srbecky6da82472018-10-23 14:03:08 +01001164 }
1165
David Srbeckybd613ec2019-05-30 15:39:38 +01001166 ALWAYS_INLINE bool SGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001167 return HandleGet<StaticObjectRead, Primitive::kPrimNot>();
David Srbecky6da82472018-10-23 14:03:08 +01001168 }
1169
David Srbeckybd613ec2019-05-30 15:39:38 +01001170 ALWAYS_INLINE bool IPUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001171 return HandlePut<InstancePrimitiveWrite, Primitive::kPrimBoolean>();
David Srbecky6da82472018-10-23 14:03:08 +01001172 }
1173
David Srbeckybd613ec2019-05-30 15:39:38 +01001174 ALWAYS_INLINE bool IPUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001175 return HandlePut<InstancePrimitiveWrite, Primitive::kPrimByte>();
David Srbecky6da82472018-10-23 14:03:08 +01001176 }
1177
David Srbeckybd613ec2019-05-30 15:39:38 +01001178 ALWAYS_INLINE bool IPUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001179 return HandlePut<InstancePrimitiveWrite, Primitive::kPrimChar>();
David Srbecky6da82472018-10-23 14:03:08 +01001180 }
1181
David Srbeckybd613ec2019-05-30 15:39:38 +01001182 ALWAYS_INLINE bool IPUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001183 return HandlePut<InstancePrimitiveWrite, Primitive::kPrimShort>();
David Srbecky6da82472018-10-23 14:03:08 +01001184 }
1185
David Srbeckybd613ec2019-05-30 15:39:38 +01001186 ALWAYS_INLINE bool IPUT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001187 return HandlePut<InstancePrimitiveWrite, Primitive::kPrimInt>();
David Srbecky6da82472018-10-23 14:03:08 +01001188 }
1189
David Srbeckybd613ec2019-05-30 15:39:38 +01001190 ALWAYS_INLINE bool IPUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001191 return HandlePut<InstancePrimitiveWrite, Primitive::kPrimLong>();
David Srbecky6da82472018-10-23 14:03:08 +01001192 }
1193
David Srbeckybd613ec2019-05-30 15:39:38 +01001194 ALWAYS_INLINE bool IPUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001195 return HandlePut<InstanceObjectWrite, Primitive::kPrimNot>();
David Srbecky6da82472018-10-23 14:03:08 +01001196 }
1197
David Srbeckybd613ec2019-05-30 15:39:38 +01001198 ALWAYS_INLINE bool IPUT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001199 return HandlePutQuick<Primitive::kPrimInt>();
David Srbecky6da82472018-10-23 14:03:08 +01001200 }
1201
David Srbeckybd613ec2019-05-30 15:39:38 +01001202 ALWAYS_INLINE bool IPUT_BOOLEAN_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001203 return HandlePutQuick<Primitive::kPrimBoolean>();
David Srbecky6da82472018-10-23 14:03:08 +01001204 }
1205
David Srbeckybd613ec2019-05-30 15:39:38 +01001206 ALWAYS_INLINE bool IPUT_BYTE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001207 return HandlePutQuick<Primitive::kPrimByte>();
David Srbecky6da82472018-10-23 14:03:08 +01001208 }
1209
David Srbeckybd613ec2019-05-30 15:39:38 +01001210 ALWAYS_INLINE bool IPUT_CHAR_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001211 return HandlePutQuick<Primitive::kPrimChar>();
David Srbecky6da82472018-10-23 14:03:08 +01001212 }
1213
David Srbeckybd613ec2019-05-30 15:39:38 +01001214 ALWAYS_INLINE bool IPUT_SHORT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001215 return HandlePutQuick<Primitive::kPrimShort>();
David Srbecky6da82472018-10-23 14:03:08 +01001216 }
1217
David Srbeckybd613ec2019-05-30 15:39:38 +01001218 ALWAYS_INLINE bool IPUT_WIDE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001219 return HandlePutQuick<Primitive::kPrimLong>();
David Srbecky6da82472018-10-23 14:03:08 +01001220 }
1221
David Srbeckybd613ec2019-05-30 15:39:38 +01001222 ALWAYS_INLINE bool IPUT_OBJECT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001223 return HandlePutQuick<Primitive::kPrimNot>();
David Srbecky6da82472018-10-23 14:03:08 +01001224 }
1225
David Srbeckybd613ec2019-05-30 15:39:38 +01001226 ALWAYS_INLINE bool SPUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001227 return HandlePut<StaticPrimitiveWrite, Primitive::kPrimBoolean>();
David Srbecky6da82472018-10-23 14:03:08 +01001228 }
1229
David Srbeckybd613ec2019-05-30 15:39:38 +01001230 ALWAYS_INLINE bool SPUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001231 return HandlePut<StaticPrimitiveWrite, Primitive::kPrimByte>();
David Srbecky6da82472018-10-23 14:03:08 +01001232 }
1233
David Srbeckybd613ec2019-05-30 15:39:38 +01001234 ALWAYS_INLINE bool SPUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001235 return HandlePut<StaticPrimitiveWrite, Primitive::kPrimChar>();
David Srbecky6da82472018-10-23 14:03:08 +01001236 }
1237
David Srbeckybd613ec2019-05-30 15:39:38 +01001238 ALWAYS_INLINE bool SPUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001239 return HandlePut<StaticPrimitiveWrite, Primitive::kPrimShort>();
David Srbecky6da82472018-10-23 14:03:08 +01001240 }
1241
David Srbeckybd613ec2019-05-30 15:39:38 +01001242 ALWAYS_INLINE bool SPUT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001243 return HandlePut<StaticPrimitiveWrite, Primitive::kPrimInt>();
David Srbecky6da82472018-10-23 14:03:08 +01001244 }
1245
David Srbeckybd613ec2019-05-30 15:39:38 +01001246 ALWAYS_INLINE bool SPUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001247 return HandlePut<StaticPrimitiveWrite, Primitive::kPrimLong>();
David Srbecky6da82472018-10-23 14:03:08 +01001248 }
1249
David Srbeckybd613ec2019-05-30 15:39:38 +01001250 ALWAYS_INLINE bool SPUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001251 return HandlePut<StaticObjectWrite, Primitive::kPrimNot>();
David Srbecky6da82472018-10-23 14:03:08 +01001252 }
1253
David Srbeckybd613ec2019-05-30 15:39:38 +01001254 ALWAYS_INLINE bool INVOKE_VIRTUAL() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001255 return HandleInvoke<kVirtual, /*is_range=*/ false>();
David Srbecky6da82472018-10-23 14:03:08 +01001256 }
1257
David Srbeckybd613ec2019-05-30 15:39:38 +01001258 ALWAYS_INLINE bool INVOKE_VIRTUAL_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001259 return HandleInvoke<kVirtual, /*is_range=*/ true>();
David Srbecky6da82472018-10-23 14:03:08 +01001260 }
1261
David Srbeckybd613ec2019-05-30 15:39:38 +01001262 ALWAYS_INLINE bool INVOKE_SUPER() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001263 return HandleInvoke<kSuper, /*is_range=*/ false>();
David Srbecky6da82472018-10-23 14:03:08 +01001264 }
1265
David Srbeckybd613ec2019-05-30 15:39:38 +01001266 ALWAYS_INLINE bool INVOKE_SUPER_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001267 return HandleInvoke<kSuper, /*is_range=*/ true>();
David Srbecky6da82472018-10-23 14:03:08 +01001268 }
1269
David Srbeckybd613ec2019-05-30 15:39:38 +01001270 ALWAYS_INLINE bool INVOKE_DIRECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001271 return HandleInvoke<kDirect, /*is_range=*/ false>();
David Srbecky6da82472018-10-23 14:03:08 +01001272 }
1273
David Srbeckybd613ec2019-05-30 15:39:38 +01001274 ALWAYS_INLINE bool INVOKE_DIRECT_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001275 return HandleInvoke<kDirect, /*is_range=*/ true>();
David Srbecky6da82472018-10-23 14:03:08 +01001276 }
1277
David Srbeckybd613ec2019-05-30 15:39:38 +01001278 ALWAYS_INLINE bool INVOKE_INTERFACE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001279 return HandleInvoke<kInterface, /*is_range=*/ false>();
David Srbecky6da82472018-10-23 14:03:08 +01001280 }
1281
David Srbeckybd613ec2019-05-30 15:39:38 +01001282 ALWAYS_INLINE bool INVOKE_INTERFACE_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001283 return HandleInvoke<kInterface, /*is_range=*/ true>();
David Srbecky6da82472018-10-23 14:03:08 +01001284 }
1285
David Srbeckybd613ec2019-05-30 15:39:38 +01001286 ALWAYS_INLINE bool INVOKE_STATIC() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001287 return HandleInvoke<kStatic, /*is_range=*/ false>();
David Srbecky6da82472018-10-23 14:03:08 +01001288 }
1289
David Srbeckybd613ec2019-05-30 15:39:38 +01001290 ALWAYS_INLINE bool INVOKE_STATIC_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001291 return HandleInvoke<kStatic, /*is_range=*/ true>();
David Srbecky6da82472018-10-23 14:03:08 +01001292 }
1293
David Srbeckybd613ec2019-05-30 15:39:38 +01001294 ALWAYS_INLINE bool INVOKE_VIRTUAL_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001295 return HandleInvoke<kVirtual, /*is_range=*/ false, /*is_quick=*/ true>();
David Srbecky6da82472018-10-23 14:03:08 +01001296 }
1297
David Srbeckybd613ec2019-05-30 15:39:38 +01001298 ALWAYS_INLINE bool INVOKE_VIRTUAL_RANGE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001299 return HandleInvoke<kVirtual, /*is_range=*/ true, /*is_quick=*/ true>();
David Srbecky6da82472018-10-23 14:03:08 +01001300 }
1301
David Srbeckybd613ec2019-05-30 15:39:38 +01001302 ALWAYS_INLINE bool INVOKE_POLYMORPHIC() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001303 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1304 bool success = DoInvokePolymorphic</* is_range= */ false>(
1305 self, shadow_frame, inst, inst_data, ResultRegister());
1306 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(!success);
David Srbeckybd613ec2019-05-30 15:39:38 +01001307 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001308 }
1309
David Srbeckybd613ec2019-05-30 15:39:38 +01001310 ALWAYS_INLINE bool INVOKE_POLYMORPHIC_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001311 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1312 bool success = DoInvokePolymorphic</* is_range= */ true>(
1313 self, shadow_frame, inst, inst_data, ResultRegister());
1314 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(!success);
David Srbeckybd613ec2019-05-30 15:39:38 +01001315 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001316 }
1317
David Srbeckybd613ec2019-05-30 15:39:38 +01001318 ALWAYS_INLINE bool INVOKE_CUSTOM() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001319 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1320 bool success = DoInvokeCustom</* is_range= */ false>(
1321 self, shadow_frame, inst, inst_data, ResultRegister());
1322 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
David Srbeckybd613ec2019-05-30 15:39:38 +01001323 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001324 }
1325
David Srbeckybd613ec2019-05-30 15:39:38 +01001326 ALWAYS_INLINE bool INVOKE_CUSTOM_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001327 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1328 bool success = DoInvokeCustom</* is_range= */ true>(
1329 self, shadow_frame, inst, inst_data, ResultRegister());
1330 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
David Srbeckybd613ec2019-05-30 15:39:38 +01001331 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001332 }
1333
David Srbeckybd613ec2019-05-30 15:39:38 +01001334 ALWAYS_INLINE bool NEG_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001335 SetVReg(A(), -GetVReg(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001336 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001337 }
1338
David Srbeckybd613ec2019-05-30 15:39:38 +01001339 ALWAYS_INLINE bool NOT_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001340 SetVReg(A(), ~GetVReg(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001341 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001342 }
1343
David Srbeckybd613ec2019-05-30 15:39:38 +01001344 ALWAYS_INLINE bool NEG_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001345 SetVRegLong(A(), -GetVRegLong(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001346 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001347 }
1348
David Srbeckybd613ec2019-05-30 15:39:38 +01001349 ALWAYS_INLINE bool NOT_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001350 SetVRegLong(A(), ~GetVRegLong(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001351 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001352 }
1353
David Srbeckybd613ec2019-05-30 15:39:38 +01001354 ALWAYS_INLINE bool NEG_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001355 SetVRegFloat(A(), -GetVRegFloat(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001356 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001357 }
1358
David Srbeckybd613ec2019-05-30 15:39:38 +01001359 ALWAYS_INLINE bool NEG_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001360 SetVRegDouble(A(), -GetVRegDouble(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001361 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001362 }
1363
David Srbeckybd613ec2019-05-30 15:39:38 +01001364 ALWAYS_INLINE bool INT_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001365 SetVRegLong(A(), GetVReg(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001366 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001367 }
1368
David Srbeckybd613ec2019-05-30 15:39:38 +01001369 ALWAYS_INLINE bool INT_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001370 SetVRegFloat(A(), GetVReg(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001371 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001372 }
1373
David Srbeckybd613ec2019-05-30 15:39:38 +01001374 ALWAYS_INLINE bool INT_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001375 SetVRegDouble(A(), GetVReg(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001376 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001377 }
1378
David Srbeckybd613ec2019-05-30 15:39:38 +01001379 ALWAYS_INLINE bool LONG_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001380 SetVReg(A(), GetVRegLong(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001381 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001382 }
1383
David Srbeckybd613ec2019-05-30 15:39:38 +01001384 ALWAYS_INLINE bool LONG_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001385 SetVRegFloat(A(), GetVRegLong(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001386 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001387 }
1388
David Srbeckybd613ec2019-05-30 15:39:38 +01001389 ALWAYS_INLINE bool LONG_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001390 SetVRegDouble(A(), GetVRegLong(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001391 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001392 }
1393
David Srbeckybd613ec2019-05-30 15:39:38 +01001394 ALWAYS_INLINE bool FLOAT_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001395 float val = GetVRegFloat(B());
David Srbecky6da82472018-10-23 14:03:08 +01001396 int32_t result = art_float_to_integral<int32_t, float>(val);
David Srbecky6baf6442019-05-30 14:57:43 +01001397 SetVReg(A(), result);
David Srbeckybd613ec2019-05-30 15:39:38 +01001398 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001399 }
1400
David Srbeckybd613ec2019-05-30 15:39:38 +01001401 ALWAYS_INLINE bool FLOAT_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001402 float val = GetVRegFloat(B());
David Srbecky6da82472018-10-23 14:03:08 +01001403 int64_t result = art_float_to_integral<int64_t, float>(val);
David Srbecky6baf6442019-05-30 14:57:43 +01001404 SetVRegLong(A(), result);
David Srbeckybd613ec2019-05-30 15:39:38 +01001405 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001406 }
1407
David Srbeckybd613ec2019-05-30 15:39:38 +01001408 ALWAYS_INLINE bool FLOAT_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001409 SetVRegDouble(A(), GetVRegFloat(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001410 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001411 }
1412
David Srbeckybd613ec2019-05-30 15:39:38 +01001413 ALWAYS_INLINE bool DOUBLE_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001414 double val = GetVRegDouble(B());
David Srbecky6da82472018-10-23 14:03:08 +01001415 int32_t result = art_float_to_integral<int32_t, double>(val);
David Srbecky6baf6442019-05-30 14:57:43 +01001416 SetVReg(A(), result);
David Srbeckybd613ec2019-05-30 15:39:38 +01001417 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001418 }
1419
David Srbeckybd613ec2019-05-30 15:39:38 +01001420 ALWAYS_INLINE bool DOUBLE_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001421 double val = GetVRegDouble(B());
David Srbecky6da82472018-10-23 14:03:08 +01001422 int64_t result = art_float_to_integral<int64_t, double>(val);
David Srbecky6baf6442019-05-30 14:57:43 +01001423 SetVRegLong(A(), result);
David Srbeckybd613ec2019-05-30 15:39:38 +01001424 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001425 }
1426
David Srbeckybd613ec2019-05-30 15:39:38 +01001427 ALWAYS_INLINE bool DOUBLE_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001428 SetVRegFloat(A(), GetVRegDouble(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001429 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001430 }
1431
David Srbeckybd613ec2019-05-30 15:39:38 +01001432 ALWAYS_INLINE bool INT_TO_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001433 SetVReg(A(), static_cast<int8_t>(GetVReg(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001434 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001435 }
1436
David Srbeckybd613ec2019-05-30 15:39:38 +01001437 ALWAYS_INLINE bool INT_TO_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001438 SetVReg(A(), static_cast<uint16_t>(GetVReg(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001439 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001440 }
1441
David Srbeckybd613ec2019-05-30 15:39:38 +01001442 ALWAYS_INLINE bool INT_TO_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001443 SetVReg(A(), static_cast<int16_t>(GetVReg(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001444 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001445 }
1446
David Srbeckybd613ec2019-05-30 15:39:38 +01001447 ALWAYS_INLINE bool ADD_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001448 SetVReg(A(), SafeAdd(GetVReg(B()), GetVReg(C())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001449 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001450 }
1451
David Srbeckybd613ec2019-05-30 15:39:38 +01001452 ALWAYS_INLINE bool SUB_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001453 SetVReg(A(), SafeSub(GetVReg(B()), GetVReg(C())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001454 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001455 }
1456
David Srbeckybd613ec2019-05-30 15:39:38 +01001457 ALWAYS_INLINE bool MUL_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001458 SetVReg(A(), SafeMul(GetVReg(B()), GetVReg(C())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001459 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001460 }
1461
David Srbeckybd613ec2019-05-30 15:39:38 +01001462 ALWAYS_INLINE bool DIV_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001463 bool success = DoIntDivide(shadow_frame, A(), GetVReg(B()), GetVReg(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001464 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
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 REM_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001469 bool success = DoIntRemainder(shadow_frame, A(), GetVReg(B()), GetVReg(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001470 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001471 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001472 }
1473
David Srbeckybd613ec2019-05-30 15:39:38 +01001474 ALWAYS_INLINE bool SHL_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001475 SetVReg(A(), GetVReg(B()) << (GetVReg(C()) & 0x1f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001476 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001477 }
1478
David Srbeckybd613ec2019-05-30 15:39:38 +01001479 ALWAYS_INLINE bool SHR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001480 SetVReg(A(), GetVReg(B()) >> (GetVReg(C()) & 0x1f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001481 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001482 }
1483
David Srbeckybd613ec2019-05-30 15:39:38 +01001484 ALWAYS_INLINE bool USHR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001485 SetVReg(A(), static_cast<uint32_t>(GetVReg(B())) >> (GetVReg(C()) & 0x1f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001486 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001487 }
1488
David Srbeckybd613ec2019-05-30 15:39:38 +01001489 ALWAYS_INLINE bool AND_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001490 SetVReg(A(), GetVReg(B()) & GetVReg(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001491 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001492 }
1493
David Srbeckybd613ec2019-05-30 15:39:38 +01001494 ALWAYS_INLINE bool OR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001495 SetVReg(A(), GetVReg(B()) | GetVReg(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001496 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001497 }
1498
David Srbeckybd613ec2019-05-30 15:39:38 +01001499 ALWAYS_INLINE bool XOR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001500 SetVReg(A(), GetVReg(B()) ^ GetVReg(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001501 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001502 }
1503
David Srbeckybd613ec2019-05-30 15:39:38 +01001504 ALWAYS_INLINE bool ADD_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001505 SetVRegLong(A(), SafeAdd(GetVRegLong(B()), GetVRegLong(C())));
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_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001510 SetVRegLong(A(), SafeSub(GetVRegLong(B()), GetVRegLong(C())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001511 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001512 }
1513
David Srbeckybd613ec2019-05-30 15:39:38 +01001514 ALWAYS_INLINE bool MUL_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001515 SetVRegLong(A(), SafeMul(GetVRegLong(B()), GetVRegLong(C())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001516 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001517 }
1518
David Srbeckybd613ec2019-05-30 15:39:38 +01001519 ALWAYS_INLINE bool DIV_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001520 DoLongDivide(shadow_frame, A(), GetVRegLong(B()), GetVRegLong(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001521 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_2xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001522 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001523 }
1524
David Srbeckybd613ec2019-05-30 15:39:38 +01001525 ALWAYS_INLINE bool REM_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001526 DoLongRemainder(shadow_frame, A(), GetVRegLong(B()), GetVRegLong(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001527 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_2xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001528 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001529 }
1530
David Srbeckybd613ec2019-05-30 15:39:38 +01001531 ALWAYS_INLINE bool AND_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001532 SetVRegLong(A(), GetVRegLong(B()) & GetVRegLong(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001533 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001534 }
1535
David Srbeckybd613ec2019-05-30 15:39:38 +01001536 ALWAYS_INLINE bool OR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001537 SetVRegLong(A(), GetVRegLong(B()) | GetVRegLong(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001538 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001539 }
1540
David Srbeckybd613ec2019-05-30 15:39:38 +01001541 ALWAYS_INLINE bool XOR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001542 SetVRegLong(A(), GetVRegLong(B()) ^ GetVRegLong(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001543 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001544 }
1545
David Srbeckybd613ec2019-05-30 15:39:38 +01001546 ALWAYS_INLINE bool SHL_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001547 SetVRegLong(A(), GetVRegLong(B()) << (GetVReg(C()) & 0x3f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001548 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001549 }
1550
David Srbeckybd613ec2019-05-30 15:39:38 +01001551 ALWAYS_INLINE bool SHR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001552 SetVRegLong(A(), GetVRegLong(B()) >> (GetVReg(C()) & 0x3f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001553 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001554 }
1555
David Srbeckybd613ec2019-05-30 15:39:38 +01001556 ALWAYS_INLINE bool USHR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001557 SetVRegLong(A(), static_cast<uint64_t>(GetVRegLong(B())) >> (GetVReg(C()) & 0x3f));
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 ADD_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001562 SetVRegFloat(A(), GetVRegFloat(B()) + GetVRegFloat(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001563 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001564 }
1565
David Srbeckybd613ec2019-05-30 15:39:38 +01001566 ALWAYS_INLINE bool SUB_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001567 SetVRegFloat(A(), GetVRegFloat(B()) - GetVRegFloat(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001568 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001569 }
1570
David Srbeckybd613ec2019-05-30 15:39:38 +01001571 ALWAYS_INLINE bool MUL_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001572 SetVRegFloat(A(), GetVRegFloat(B()) * GetVRegFloat(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001573 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001574 }
1575
David Srbeckybd613ec2019-05-30 15:39:38 +01001576 ALWAYS_INLINE bool DIV_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001577 SetVRegFloat(A(), GetVRegFloat(B()) / GetVRegFloat(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001578 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001579 }
1580
David Srbeckybd613ec2019-05-30 15:39:38 +01001581 ALWAYS_INLINE bool REM_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001582 SetVRegFloat(A(), fmodf(GetVRegFloat(B()), GetVRegFloat(C())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001583 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001584 }
1585
David Srbeckybd613ec2019-05-30 15:39:38 +01001586 ALWAYS_INLINE bool ADD_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001587 SetVRegDouble(A(), GetVRegDouble(B()) + GetVRegDouble(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001588 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001589 }
1590
David Srbeckybd613ec2019-05-30 15:39:38 +01001591 ALWAYS_INLINE bool SUB_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001592 SetVRegDouble(A(), GetVRegDouble(B()) - GetVRegDouble(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001593 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001594 }
1595
David Srbeckybd613ec2019-05-30 15:39:38 +01001596 ALWAYS_INLINE bool MUL_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001597 SetVRegDouble(A(), GetVRegDouble(B()) * GetVRegDouble(C()));
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 DIV_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001602 SetVRegDouble(A(), GetVRegDouble(B()) / GetVRegDouble(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001603 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001604 }
1605
David Srbeckybd613ec2019-05-30 15:39:38 +01001606 ALWAYS_INLINE bool REM_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001607 SetVRegDouble(A(), fmod(GetVRegDouble(B()), GetVRegDouble(C())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001608 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001609 }
1610
David Srbeckybd613ec2019-05-30 15:39:38 +01001611 ALWAYS_INLINE bool ADD_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001612 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001613 SetVReg(vregA, SafeAdd(GetVReg(vregA), GetVReg(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001614 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001615 }
1616
David Srbeckybd613ec2019-05-30 15:39:38 +01001617 ALWAYS_INLINE bool SUB_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001618 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001619 SetVReg(vregA, SafeSub(GetVReg(vregA), GetVReg(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001620 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001621 }
1622
David Srbeckybd613ec2019-05-30 15:39:38 +01001623 ALWAYS_INLINE bool MUL_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001624 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001625 SetVReg(vregA, SafeMul(GetVReg(vregA), GetVReg(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001626 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001627 }
1628
David Srbeckybd613ec2019-05-30 15:39:38 +01001629 ALWAYS_INLINE bool DIV_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001630 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001631 bool success = DoIntDivide(shadow_frame, vregA, GetVReg(vregA), GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001632 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_1xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001633 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001634 }
1635
David Srbeckybd613ec2019-05-30 15:39:38 +01001636 ALWAYS_INLINE bool REM_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001637 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001638 bool success = DoIntRemainder(shadow_frame, vregA, GetVReg(vregA), GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001639 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_1xx);
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 SHL_INT_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 SetVReg(vregA, GetVReg(vregA) << (GetVReg(B()) & 0x1f));
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 SHR_INT_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 SetVReg(vregA, GetVReg(vregA) >> (GetVReg(B()) & 0x1f));
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 USHR_INT_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 SetVReg(vregA, static_cast<uint32_t>(GetVReg(vregA)) >> (GetVReg(B()) & 0x1f));
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 AND_INT_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 SetVReg(vregA, GetVReg(vregA) & GetVReg(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 OR_INT_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 SetVReg(vregA, GetVReg(vregA) | GetVReg(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 XOR_INT_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 SetVReg(vregA, GetVReg(vregA) ^ GetVReg(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 ADD_LONG_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 SetVRegLong(vregA, SafeAdd(GetVRegLong(vregA), GetVRegLong(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 SUB_LONG_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 SetVRegLong(vregA, SafeSub(GetVRegLong(vregA), GetVRegLong(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 MUL_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001692 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001693 SetVRegLong(vregA, SafeMul(GetVRegLong(vregA), GetVRegLong(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001694 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001695 }
1696
David Srbeckybd613ec2019-05-30 15:39:38 +01001697 ALWAYS_INLINE bool DIV_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001698 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001699 DoLongDivide(shadow_frame, vregA, GetVRegLong(vregA), GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001700 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001701 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001702 }
1703
David Srbeckybd613ec2019-05-30 15:39:38 +01001704 ALWAYS_INLINE bool REM_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001705 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001706 DoLongRemainder(shadow_frame, vregA, GetVRegLong(vregA), GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001707 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001708 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001709 }
1710
David Srbeckybd613ec2019-05-30 15:39:38 +01001711 ALWAYS_INLINE bool AND_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001712 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001713 SetVRegLong(vregA, GetVRegLong(vregA) & GetVRegLong(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001714 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001715 }
1716
David Srbeckybd613ec2019-05-30 15:39:38 +01001717 ALWAYS_INLINE bool OR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001718 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001719 SetVRegLong(vregA, GetVRegLong(vregA) | GetVRegLong(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001720 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001721 }
1722
David Srbeckybd613ec2019-05-30 15:39:38 +01001723 ALWAYS_INLINE bool XOR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001724 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001725 SetVRegLong(vregA, GetVRegLong(vregA) ^ GetVRegLong(B()));
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 SHL_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001730 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001731 SetVRegLong(vregA, GetVRegLong(vregA) << (GetVReg(B()) & 0x3f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001732 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001733 }
1734
David Srbeckybd613ec2019-05-30 15:39:38 +01001735 ALWAYS_INLINE bool SHR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001736 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001737 SetVRegLong(vregA, GetVRegLong(vregA) >> (GetVReg(B()) & 0x3f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001738 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001739 }
1740
David Srbeckybd613ec2019-05-30 15:39:38 +01001741 ALWAYS_INLINE bool USHR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001742 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001743 SetVRegLong(vregA, static_cast<uint64_t>(GetVRegLong(vregA)) >> (GetVReg(B()) & 0x3f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001744 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001745 }
1746
David Srbeckybd613ec2019-05-30 15:39:38 +01001747 ALWAYS_INLINE bool ADD_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001748 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001749 SetVRegFloat(vregA, GetVRegFloat(vregA) + GetVRegFloat(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001750 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001751 }
1752
David Srbeckybd613ec2019-05-30 15:39:38 +01001753 ALWAYS_INLINE bool SUB_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001754 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001755 SetVRegFloat(vregA, GetVRegFloat(vregA) - GetVRegFloat(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001756 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001757 }
1758
David Srbeckybd613ec2019-05-30 15:39:38 +01001759 ALWAYS_INLINE bool MUL_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001760 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001761 SetVRegFloat(vregA, GetVRegFloat(vregA) * GetVRegFloat(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001762 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001763 }
1764
David Srbeckybd613ec2019-05-30 15:39:38 +01001765 ALWAYS_INLINE bool DIV_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001766 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001767 SetVRegFloat(vregA, GetVRegFloat(vregA) / GetVRegFloat(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001768 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001769 }
1770
David Srbeckybd613ec2019-05-30 15:39:38 +01001771 ALWAYS_INLINE bool REM_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001772 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001773 SetVRegFloat(vregA, fmodf(GetVRegFloat(vregA), GetVRegFloat(B())));
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 ADD_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001778 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001779 SetVRegDouble(vregA, GetVRegDouble(vregA) + GetVRegDouble(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001780 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001781 }
1782
David Srbeckybd613ec2019-05-30 15:39:38 +01001783 ALWAYS_INLINE bool SUB_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001784 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001785 SetVRegDouble(vregA, GetVRegDouble(vregA) - GetVRegDouble(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001786 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001787 }
1788
David Srbeckybd613ec2019-05-30 15:39:38 +01001789 ALWAYS_INLINE bool MUL_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001790 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001791 SetVRegDouble(vregA, GetVRegDouble(vregA) * GetVRegDouble(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001792 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001793 }
1794
David Srbeckybd613ec2019-05-30 15:39:38 +01001795 ALWAYS_INLINE bool DIV_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001796 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001797 SetVRegDouble(vregA, GetVRegDouble(vregA) / GetVRegDouble(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001798 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001799 }
1800
David Srbeckybd613ec2019-05-30 15:39:38 +01001801 ALWAYS_INLINE bool REM_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001802 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001803 SetVRegDouble(vregA, fmod(GetVRegDouble(vregA), GetVRegDouble(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001804 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001805 }
1806
David Srbeckybd613ec2019-05-30 15:39:38 +01001807 ALWAYS_INLINE bool ADD_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001808 SetVReg(A(), SafeAdd(GetVReg(B()), C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001809 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001810 }
1811
David Srbeckybd613ec2019-05-30 15:39:38 +01001812 ALWAYS_INLINE bool RSUB_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001813 SetVReg(A(), SafeSub(C(), GetVReg(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001814 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001815 }
1816
David Srbeckybd613ec2019-05-30 15:39:38 +01001817 ALWAYS_INLINE bool MUL_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001818 SetVReg(A(), SafeMul(GetVReg(B()), C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001819 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001820 }
1821
David Srbeckybd613ec2019-05-30 15:39:38 +01001822 ALWAYS_INLINE bool DIV_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001823 bool success = DoIntDivide(shadow_frame, A(), GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +01001824 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001825 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001826 }
1827
David Srbeckybd613ec2019-05-30 15:39:38 +01001828 ALWAYS_INLINE bool REM_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001829 bool success = DoIntRemainder(shadow_frame, A(), GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +01001830 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001831 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001832 }
1833
David Srbeckybd613ec2019-05-30 15:39:38 +01001834 ALWAYS_INLINE bool AND_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001835 SetVReg(A(), GetVReg(B()) & C());
David Srbeckybd613ec2019-05-30 15:39:38 +01001836 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001837 }
1838
David Srbeckybd613ec2019-05-30 15:39:38 +01001839 ALWAYS_INLINE bool OR_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001840 SetVReg(A(), GetVReg(B()) | C());
David Srbeckybd613ec2019-05-30 15:39:38 +01001841 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001842 }
1843
David Srbeckybd613ec2019-05-30 15:39:38 +01001844 ALWAYS_INLINE bool XOR_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001845 SetVReg(A(), GetVReg(B()) ^ C());
David Srbeckybd613ec2019-05-30 15:39:38 +01001846 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001847 }
1848
David Srbeckybd613ec2019-05-30 15:39:38 +01001849 ALWAYS_INLINE bool ADD_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001850 SetVReg(A(), SafeAdd(GetVReg(B()), C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001851 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001852 }
1853
David Srbeckybd613ec2019-05-30 15:39:38 +01001854 ALWAYS_INLINE bool RSUB_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001855 SetVReg(A(), SafeSub(C(), GetVReg(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001856 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001857 }
1858
David Srbeckybd613ec2019-05-30 15:39:38 +01001859 ALWAYS_INLINE bool MUL_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001860 SetVReg(A(), SafeMul(GetVReg(B()), C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001861 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001862 }
1863
David Srbeckybd613ec2019-05-30 15:39:38 +01001864 ALWAYS_INLINE bool DIV_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001865 bool success = DoIntDivide(shadow_frame, A(), GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +01001866 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001867 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001868 }
1869
David Srbeckybd613ec2019-05-30 15:39:38 +01001870 ALWAYS_INLINE bool REM_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001871 bool success = DoIntRemainder(shadow_frame, A(), GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +01001872 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001873 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001874 }
1875
David Srbeckybd613ec2019-05-30 15:39:38 +01001876 ALWAYS_INLINE bool AND_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001877 SetVReg(A(), GetVReg(B()) & C());
David Srbeckybd613ec2019-05-30 15:39:38 +01001878 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001879 }
1880
David Srbeckybd613ec2019-05-30 15:39:38 +01001881 ALWAYS_INLINE bool OR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001882 SetVReg(A(), GetVReg(B()) | C());
David Srbeckybd613ec2019-05-30 15:39:38 +01001883 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001884 }
1885
David Srbeckybd613ec2019-05-30 15:39:38 +01001886 ALWAYS_INLINE bool XOR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001887 SetVReg(A(), GetVReg(B()) ^ C());
David Srbeckybd613ec2019-05-30 15:39:38 +01001888 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001889 }
1890
David Srbeckybd613ec2019-05-30 15:39:38 +01001891 ALWAYS_INLINE bool SHL_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001892 SetVReg(A(), GetVReg(B()) << (C() & 0x1f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001893 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001894 }
1895
David Srbeckybd613ec2019-05-30 15:39:38 +01001896 ALWAYS_INLINE bool SHR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001897 SetVReg(A(), GetVReg(B()) >> (C() & 0x1f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001898 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001899 }
1900
David Srbeckybd613ec2019-05-30 15:39:38 +01001901 ALWAYS_INLINE bool USHR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001902 SetVReg(A(), static_cast<uint32_t>(GetVReg(B())) >> (C() & 0x1f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001903 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001904 }
1905
David Srbeckybd613ec2019-05-30 15:39:38 +01001906 ALWAYS_INLINE bool UNUSED_3E() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001907 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001908 }
1909
David Srbeckybd613ec2019-05-30 15:39:38 +01001910 ALWAYS_INLINE bool UNUSED_3F() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001911 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001912 }
1913
David Srbeckybd613ec2019-05-30 15:39:38 +01001914 ALWAYS_INLINE bool UNUSED_40() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001915 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001916 }
1917
David Srbeckybd613ec2019-05-30 15:39:38 +01001918 ALWAYS_INLINE bool UNUSED_41() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001919 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001920 }
1921
David Srbeckybd613ec2019-05-30 15:39:38 +01001922 ALWAYS_INLINE bool UNUSED_42() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001923 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001924 }
1925
David Srbeckybd613ec2019-05-30 15:39:38 +01001926 ALWAYS_INLINE bool UNUSED_43() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001927 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001928 }
1929
David Srbeckybd613ec2019-05-30 15:39:38 +01001930 ALWAYS_INLINE bool UNUSED_79() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001931 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001932 }
1933
David Srbeckybd613ec2019-05-30 15:39:38 +01001934 ALWAYS_INLINE bool UNUSED_7A() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001935 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001936 }
1937
David Srbeckybd613ec2019-05-30 15:39:38 +01001938 ALWAYS_INLINE bool UNUSED_F3() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001939 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001940 }
1941
David Srbeckybd613ec2019-05-30 15:39:38 +01001942 ALWAYS_INLINE bool UNUSED_F4() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001943 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001944 }
1945
David Srbeckybd613ec2019-05-30 15:39:38 +01001946 ALWAYS_INLINE bool UNUSED_F5() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001947 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001948 }
1949
David Srbeckybd613ec2019-05-30 15:39:38 +01001950 ALWAYS_INLINE bool UNUSED_F6() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001951 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001952 }
1953
David Srbeckybd613ec2019-05-30 15:39:38 +01001954 ALWAYS_INLINE bool UNUSED_F7() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001955 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001956 }
1957
David Srbeckybd613ec2019-05-30 15:39:38 +01001958 ALWAYS_INLINE bool UNUSED_F8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001959 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001960 }
1961
David Srbeckybd613ec2019-05-30 15:39:38 +01001962 ALWAYS_INLINE bool UNUSED_F9() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001963 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001964 }
1965
1966 ALWAYS_INLINE InstructionHandler(SwitchImplContext* ctx,
1967 const instrumentation::Instrumentation* instrumentation,
1968 Thread* self,
1969 ShadowFrame& shadow_frame,
1970 uint16_t dex_pc,
David Srbeckyc56a23e2019-06-05 17:45:49 +01001971 const Instruction* inst,
David Srbecky6da82472018-10-23 14:03:08 +01001972 uint16_t inst_data,
David Srbecky8867f3b2019-05-31 20:01:46 +01001973 const Instruction*& next,
David Srbecky6da82472018-10-23 14:03:08 +01001974 bool& exit_interpreter_loop)
1975 : ctx(ctx),
1976 instrumentation(instrumentation),
1977 self(self),
1978 shadow_frame(shadow_frame),
1979 dex_pc(dex_pc),
1980 inst(inst),
1981 inst_data(inst_data),
David Srbecky8867f3b2019-05-31 20:01:46 +01001982 next(next),
David Srbecky6da82472018-10-23 14:03:08 +01001983 exit_interpreter_loop(exit_interpreter_loop) {
1984 }
1985
1986 private:
1987 static constexpr bool do_assignability_check = do_access_check;
Alex Lightb7c640d2019-03-20 15:52:13 -07001988 static constexpr MonitorState kMonitorState =
1989 do_assignability_check ? MonitorState::kCountingMonitors : MonitorState::kNormalMonitors;
David Srbecky6da82472018-10-23 14:03:08 +01001990
1991 const CodeItemDataAccessor& Accessor() { return ctx->accessor; }
1992 const uint16_t* Insns() { return ctx->accessor.Insns(); }
1993 JValue* ResultRegister() { return &ctx->result_register; }
1994
David Srbecky436f6c12019-05-22 13:28:42 +01001995 ALWAYS_INLINE int32_t A() { return inst->VRegA(kFormat, inst_data); }
1996 ALWAYS_INLINE int32_t B() { return inst->VRegB(kFormat, inst_data); }
1997 ALWAYS_INLINE int32_t C() { return inst->VRegC(kFormat); }
1998
David Srbecky6baf6442019-05-30 14:57:43 +01001999 int32_t GetVReg(size_t i) const { return shadow_frame.GetVReg(i); }
2000 int64_t GetVRegLong(size_t i) const { return shadow_frame.GetVRegLong(i); }
2001 float GetVRegFloat(size_t i) const { return shadow_frame.GetVRegFloat(i); }
2002 double GetVRegDouble(size_t i) const { return shadow_frame.GetVRegDouble(i); }
2003 ObjPtr<mirror::Object> GetVRegReference(size_t i) const REQUIRES_SHARED(Locks::mutator_lock_) {
2004 return shadow_frame.GetVRegReference(i);
2005 }
2006
2007 void SetVReg(size_t i, int32_t val) { shadow_frame.SetVReg(i, val); }
2008 void SetVRegLong(size_t i, int64_t val) { shadow_frame.SetVRegLong(i, val); }
2009 void SetVRegFloat(size_t i, float val) { shadow_frame.SetVRegFloat(i, val); }
2010 void SetVRegDouble(size_t i, double val) { shadow_frame.SetVRegDouble(i, val); }
2011 void SetVRegReference(size_t i, ObjPtr<mirror::Object> val)
2012 REQUIRES_SHARED(Locks::mutator_lock_) {
2013 shadow_frame.SetVRegReference(i, val);
2014 }
2015
David Srbecky8867f3b2019-05-31 20:01:46 +01002016 // Set the next instruction to be executed. It is the 'fall-through' instruction by default.
2017 ALWAYS_INLINE void SetNextInstruction(const Instruction* next_inst) {
2018 DCHECK_LT(next_inst->GetDexPc(Insns()), Accessor().InsnsSizeInCodeUnits());
2019 next = next_inst;
2020 }
2021
David Srbecky6da82472018-10-23 14:03:08 +01002022 SwitchImplContext* const ctx;
2023 const instrumentation::Instrumentation* const instrumentation;
2024 Thread* const self;
2025 ShadowFrame& shadow_frame;
2026 uint32_t const dex_pc;
David Srbeckyc56a23e2019-06-05 17:45:49 +01002027 const Instruction* const inst;
David Srbecky6da82472018-10-23 14:03:08 +01002028 uint16_t const inst_data;
David Srbecky8867f3b2019-05-31 20:01:46 +01002029 const Instruction*& next;
2030
David Srbecky6da82472018-10-23 14:03:08 +01002031 bool& exit_interpreter_loop;
2032};
2033
David Srbecky6da82472018-10-23 14:03:08 +01002034#undef BRANCH_INSTRUMENTATION
David Srbecky6da82472018-10-23 14:03:08 +01002035#undef POSSIBLY_HANDLE_PENDING_EXCEPTION
2036#undef POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE
2037#undef POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC
David Srbecky6da82472018-10-23 14:03:08 +01002038#undef HANDLE_PENDING_EXCEPTION
David Srbecky6da82472018-10-23 14:03:08 +01002039
Alex Light6f22e062018-10-05 15:05:12 -07002040// TODO On ASAN builds this function gets a huge stack frame. Since normally we run in the mterp
2041// this shouldn't cause any problems for stack overflow detection. Remove this once b/117341496 is
2042// fixed.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +01002043template<bool do_access_check, bool transaction_active>
Alex Light6f22e062018-10-05 15:05:12 -07002044ATTRIBUTE_NO_SANITIZE_ADDRESS void ExecuteSwitchImplCpp(SwitchImplContext* ctx) {
David Srbecky946bb092018-03-09 17:23:01 +00002045 Thread* self = ctx->self;
2046 const CodeItemDataAccessor& accessor = ctx->accessor;
2047 ShadowFrame& shadow_frame = ctx->shadow_frame;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002048 if (UNLIKELY(!shadow_frame.HasReferenceArray())) {
2049 LOG(FATAL) << "Invalid shadow frame for interpreter use";
David Srbecky946bb092018-03-09 17:23:01 +00002050 ctx->result = JValue();
2051 return;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002052 }
2053 self->VerifyStack();
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002054
2055 uint32_t dex_pc = shadow_frame.GetDexPC();
Mathieu Chartier2cebb242015-04-21 16:50:40 -07002056 const auto* const instrumentation = Runtime::Current()->GetInstrumentation();
Mathieu Chartier808c7a52017-12-15 11:19:33 -08002057 const uint16_t* const insns = accessor.Insns();
David Srbeckyc56a23e2019-06-05 17:45:49 +01002058 const Instruction* next = Instruction::At(insns + dex_pc);
Sebastien Hertz3b588e02013-09-11 14:33:18 +02002059 uint16_t inst_data;
Igor Murashkin6918bf12015-09-27 19:19:06 -07002060
Alex Light0aa7a5a2018-10-10 15:58:14 +00002061 DCHECK(!shadow_frame.GetForceRetryInstruction())
2062 << "Entered interpreter from invoke without retry instruction being handled!";
2063
David Srbecky6da82472018-10-23 14:03:08 +01002064 bool const interpret_one_instruction = ctx->interpret_one_instruction;
2065 while (true) {
David Srbeckyc56a23e2019-06-05 17:45:49 +01002066 const Instruction* const inst = next;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002067 dex_pc = inst->GetDexPc(insns);
2068 shadow_frame.SetDexPC(dex_pc);
Ian Rogerse94652f2014-12-02 11:13:19 -08002069 TraceExecution(shadow_frame, inst, dex_pc);
Sebastien Hertz3b588e02013-09-11 14:33:18 +02002070 inst_data = inst->Fetch16(0);
David Srbeckya4a96af2018-10-31 16:34:58 +00002071 {
2072 bool exit_loop = false;
David Srbecky436f6c12019-05-22 13:28:42 +01002073 InstructionHandler<do_access_check, transaction_active, Instruction::kInvalidFormat> handler(
David Srbecky8867f3b2019-05-31 20:01:46 +01002074 ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, next, exit_loop);
David Srbeckya4a96af2018-10-31 16:34:58 +00002075 if (!handler.Preamble()) {
2076 if (UNLIKELY(exit_loop)) {
2077 return;
2078 }
2079 if (UNLIKELY(interpret_one_instruction)) {
2080 break;
2081 }
2082 continue;
2083 }
2084 }
Sebastien Hertz3b588e02013-09-11 14:33:18 +02002085 switch (inst->Opcode(inst_data)) {
David Srbecky8867f3b2019-05-31 20:01:46 +01002086#define OPCODE_CASE(OPCODE, OPCODE_NAME, NAME, FORMAT, i, a, e, v) \
David Srbecky6da82472018-10-23 14:03:08 +01002087 case OPCODE: { \
David Srbeckyc56a23e2019-06-05 17:45:49 +01002088 next = inst->RelativeAt(Instruction::SizeInCodeUnits(Instruction::FORMAT)); \
David Srbecky6da82472018-10-23 14:03:08 +01002089 bool exit_loop = false; \
David Srbecky436f6c12019-05-22 13:28:42 +01002090 InstructionHandler<do_access_check, transaction_active, Instruction::FORMAT> handler( \
David Srbecky8867f3b2019-05-31 20:01:46 +01002091 ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, next, exit_loop); \
David Srbeckya4a96af2018-10-31 16:34:58 +00002092 handler.OPCODE_NAME(); \
David Srbecky6da82472018-10-23 14:03:08 +01002093 if (UNLIKELY(exit_loop)) { \
2094 return; \
2095 } \
2096 break; \
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002097 }
David Srbecky6da82472018-10-23 14:03:08 +01002098DEX_INSTRUCTION_LIST(OPCODE_CASE)
2099#undef OPCODE_CASE
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002100 }
David Srbecky6da82472018-10-23 14:03:08 +01002101 if (UNLIKELY(interpret_one_instruction)) {
David Srbeckya4a96af2018-10-31 16:34:58 +00002102 break;
David Srbecky6da82472018-10-23 14:03:08 +01002103 }
2104 }
David Srbeckya4a96af2018-10-31 16:34:58 +00002105 // Record where we stopped.
David Srbeckyc56a23e2019-06-05 17:45:49 +01002106 shadow_frame.SetDexPC(next->GetDexPc(insns));
David Srbeckya4a96af2018-10-31 16:34:58 +00002107 ctx->result = ctx->result_register;
2108 return;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002109} // NOLINT(readability/fn_size)
2110
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002111} // namespace interpreter
2112} // namespace art
David Srbecky2ee09ff2018-10-24 13:24:22 +01002113
2114#endif // ART_RUNTIME_INTERPRETER_INTERPRETER_SWITCH_IMPL_INL_H_