blob: 13aa9e7decb8324a61dee6eaca3bbe3c4f267614 [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 Marko64b56032019-06-20 15:52:39 +0100831 // Don't allow finalizable objects to be allocated during a transaction since these can't
832 // be finalized without a started runtime.
833 if (transaction_active && c->IsFinalizable()) {
834 AbortTransactionF(self,
835 "Allocating finalizable object in transaction: %s",
836 c->PrettyDescriptor().c_str());
837 HANDLE_PENDING_EXCEPTION();
838 }
Vladimir Marko9b81ac32019-05-16 16:47:08 +0100839 gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
David Srbecky6da82472018-10-23 14:03:08 +0100840 if (UNLIKELY(c->IsStringClass())) {
Vladimir Marko9b81ac32019-05-16 16:47:08 +0100841 obj = mirror::String::AllocEmptyString(self, allocator_type);
David Srbecky6da82472018-10-23 14:03:08 +0100842 } else {
Vladimir Marko9b81ac32019-05-16 16:47:08 +0100843 obj = AllocObjectFromCode(c, self, allocator_type);
David Srbecky6da82472018-10-23 14:03:08 +0100844 }
845 }
846 if (UNLIKELY(obj == nullptr)) {
847 HANDLE_PENDING_EXCEPTION();
848 } else {
849 obj->GetClass()->AssertInitializedOrInitializingInThread(self);
David Srbecky6baf6442019-05-30 14:57:43 +0100850 SetVRegReference(A(), obj);
David Srbecky6da82472018-10-23 14:03:08 +0100851 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100852 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100853 }
854
David Srbeckybd613ec2019-05-30 15:39:38 +0100855 ALWAYS_INLINE bool NEW_ARRAY() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100856 int32_t length = GetVReg(B());
Vladimir Marko9b81ac32019-05-16 16:47:08 +0100857 ObjPtr<mirror::Object> obj = AllocArrayFromCode<do_access_check>(
David Srbeckyd6f579c2019-05-29 18:09:30 +0100858 dex::TypeIndex(C()),
David Srbecky6da82472018-10-23 14:03:08 +0100859 length,
860 shadow_frame.GetMethod(),
861 self,
862 Runtime::Current()->GetHeap()->GetCurrentAllocator());
863 if (UNLIKELY(obj == nullptr)) {
864 HANDLE_PENDING_EXCEPTION();
865 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100866 SetVRegReference(A(), obj);
David Srbecky6da82472018-10-23 14:03:08 +0100867 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100868 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100869 }
870
David Srbeckybd613ec2019-05-30 15:39:38 +0100871 ALWAYS_INLINE bool FILLED_NEW_ARRAY() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100872 bool success =
873 DoFilledNewArray<false, do_access_check, transaction_active>(inst, shadow_frame, self,
874 ResultRegister());
875 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
David Srbeckybd613ec2019-05-30 15:39:38 +0100876 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100877 }
878
David Srbeckybd613ec2019-05-30 15:39:38 +0100879 ALWAYS_INLINE bool FILLED_NEW_ARRAY_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100880 bool success =
881 DoFilledNewArray<true, do_access_check, transaction_active>(inst, shadow_frame,
882 self, ResultRegister());
883 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
David Srbeckybd613ec2019-05-30 15:39:38 +0100884 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100885 }
886
David Srbeckybd613ec2019-05-30 15:39:38 +0100887 ALWAYS_INLINE bool FILL_ARRAY_DATA() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100888 const uint16_t* payload_addr = reinterpret_cast<const uint16_t*>(inst) + B();
David Srbecky6da82472018-10-23 14:03:08 +0100889 const Instruction::ArrayDataPayload* payload =
890 reinterpret_cast<const Instruction::ArrayDataPayload*>(payload_addr);
David Srbecky6baf6442019-05-30 14:57:43 +0100891 ObjPtr<mirror::Object> obj = GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +0100892 bool success = FillArrayData(obj, payload);
893 if (!success) {
894 HANDLE_PENDING_EXCEPTION();
895 }
896 if (transaction_active) {
897 RecordArrayElementsInTransaction(obj->AsArray(), payload->element_count);
898 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100899 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100900 }
901
David Srbeckybd613ec2019-05-30 15:39:38 +0100902 ALWAYS_INLINE bool THROW() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000903 if (!HandleAsyncException()) {
David Srbeckybd613ec2019-05-30 15:39:38 +0100904 return false;
David Srbecky47ad3762018-10-31 12:43:40 +0000905 }
David Srbecky6baf6442019-05-30 14:57:43 +0100906 ObjPtr<mirror::Object> exception = GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +0100907 if (UNLIKELY(exception == nullptr)) {
908 ThrowNullPointerException("throw with null exception");
909 } else if (do_assignability_check && !exception->GetClass()->IsThrowableClass()) {
910 // This should never happen.
911 std::string temp;
912 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
913 "Throwing '%s' that is not instance of Throwable",
914 exception->GetClass()->GetDescriptor(&temp));
915 } else {
916 self->SetException(exception->AsThrowable());
917 }
918 HANDLE_PENDING_EXCEPTION();
David Srbeckybd613ec2019-05-30 15:39:38 +0100919 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100920 }
921
David Srbeckybd613ec2019-05-30 15:39:38 +0100922 ALWAYS_INLINE bool GOTO() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100923 return HandleGoto(A());
David Srbecky6da82472018-10-23 14:03:08 +0100924 }
925
David Srbeckybd613ec2019-05-30 15:39:38 +0100926 ALWAYS_INLINE bool GOTO_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100927 return HandleGoto(A());
David Srbecky6da82472018-10-23 14:03:08 +0100928 }
929
David Srbeckybd613ec2019-05-30 15:39:38 +0100930 ALWAYS_INLINE bool GOTO_32() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100931 return HandleGoto(A());
David Srbecky6da82472018-10-23 14:03:08 +0100932 }
933
David Srbeckybd613ec2019-05-30 15:39:38 +0100934 ALWAYS_INLINE bool PACKED_SWITCH() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100935 int32_t offset = DoPackedSwitch(inst, shadow_frame, inst_data);
936 BRANCH_INSTRUMENTATION(offset);
David Srbecky8867f3b2019-05-31 20:01:46 +0100937 SetNextInstruction(inst->RelativeAt(offset));
David Srbecky47ad3762018-10-31 12:43:40 +0000938 HandleBackwardBranch(offset);
David Srbeckybd613ec2019-05-30 15:39:38 +0100939 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100940 }
941
David Srbeckybd613ec2019-05-30 15:39:38 +0100942 ALWAYS_INLINE bool SPARSE_SWITCH() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100943 int32_t offset = DoSparseSwitch(inst, shadow_frame, inst_data);
944 BRANCH_INSTRUMENTATION(offset);
David Srbecky8867f3b2019-05-31 20:01:46 +0100945 SetNextInstruction(inst->RelativeAt(offset));
David Srbecky47ad3762018-10-31 12:43:40 +0000946 HandleBackwardBranch(offset);
David Srbeckybd613ec2019-05-30 15:39:38 +0100947 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100948 }
949
David Srbeckybd613ec2019-05-30 15:39:38 +0100950 ALWAYS_INLINE bool CMPL_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100951 return HandleCmpl<float>(GetVRegFloat(B()), GetVRegFloat(C()));
David Srbecky6da82472018-10-23 14:03:08 +0100952 }
953
David Srbeckybd613ec2019-05-30 15:39:38 +0100954 ALWAYS_INLINE bool CMPG_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100955 return HandleCmpg<float>(GetVRegFloat(B()), GetVRegFloat(C()));
David Srbecky6da82472018-10-23 14:03:08 +0100956 }
957
David Srbeckybd613ec2019-05-30 15:39:38 +0100958 ALWAYS_INLINE bool CMPL_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100959 return HandleCmpl<double>(GetVRegDouble(B()), GetVRegDouble(C()));
David Srbecky6da82472018-10-23 14:03:08 +0100960 }
961
David Srbeckybd613ec2019-05-30 15:39:38 +0100962 ALWAYS_INLINE bool CMPG_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100963 return HandleCmpg<double>(GetVRegDouble(B()), GetVRegDouble(C()));
David Srbecky6da82472018-10-23 14:03:08 +0100964 }
965
David Srbeckybd613ec2019-05-30 15:39:38 +0100966 ALWAYS_INLINE bool CMP_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100967 return HandleCmpl<int64_t>(GetVRegLong(B()), GetVRegLong(C()));
David Srbecky6da82472018-10-23 14:03:08 +0100968 }
969
David Srbeckybd613ec2019-05-30 15:39:38 +0100970 ALWAYS_INLINE bool IF_EQ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100971 return HandleIf(GetVReg(A()) == GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +0100972 }
973
David Srbeckybd613ec2019-05-30 15:39:38 +0100974 ALWAYS_INLINE bool IF_NE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100975 return HandleIf(GetVReg(A()) != GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +0100976 }
977
David Srbeckybd613ec2019-05-30 15:39:38 +0100978 ALWAYS_INLINE bool IF_LT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100979 return HandleIf(GetVReg(A()) < GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +0100980 }
981
David Srbeckybd613ec2019-05-30 15:39:38 +0100982 ALWAYS_INLINE bool IF_GE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100983 return HandleIf(GetVReg(A()) >= GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +0100984 }
985
David Srbeckybd613ec2019-05-30 15:39:38 +0100986 ALWAYS_INLINE bool IF_GT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100987 return HandleIf(GetVReg(A()) > GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +0100988 }
989
David Srbeckybd613ec2019-05-30 15:39:38 +0100990 ALWAYS_INLINE bool IF_LE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100991 return HandleIf(GetVReg(A()) <= GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +0100992 }
993
David Srbeckybd613ec2019-05-30 15:39:38 +0100994 ALWAYS_INLINE bool IF_EQZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100995 return HandleIf(GetVReg(A()) == 0, B());
David Srbecky6da82472018-10-23 14:03:08 +0100996 }
997
David Srbeckybd613ec2019-05-30 15:39:38 +0100998 ALWAYS_INLINE bool IF_NEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +0100999 return HandleIf(GetVReg(A()) != 0, B());
David Srbecky6da82472018-10-23 14:03:08 +01001000 }
1001
David Srbeckybd613ec2019-05-30 15:39:38 +01001002 ALWAYS_INLINE bool IF_LTZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001003 return HandleIf(GetVReg(A()) < 0, B());
David Srbecky6da82472018-10-23 14:03:08 +01001004 }
1005
David Srbeckybd613ec2019-05-30 15:39:38 +01001006 ALWAYS_INLINE bool IF_GEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001007 return HandleIf(GetVReg(A()) >= 0, B());
David Srbecky6da82472018-10-23 14:03:08 +01001008 }
1009
David Srbeckybd613ec2019-05-30 15:39:38 +01001010 ALWAYS_INLINE bool IF_GTZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001011 return HandleIf(GetVReg(A()) > 0, B());
David Srbecky6da82472018-10-23 14:03:08 +01001012 }
1013
David Srbeckybd613ec2019-05-30 15:39:38 +01001014 ALWAYS_INLINE bool IF_LEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001015 return HandleIf(GetVReg(A()) <= 0, B());
David Srbecky6da82472018-10-23 14:03:08 +01001016 }
1017
David Srbeckybd613ec2019-05-30 15:39:38 +01001018 ALWAYS_INLINE bool AGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001019 return HandleAGet<mirror::BooleanArray>(&InstructionHandler::SetVReg);
David Srbecky6da82472018-10-23 14:03:08 +01001020 }
1021
David Srbeckybd613ec2019-05-30 15:39:38 +01001022 ALWAYS_INLINE bool AGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001023 return HandleAGet<mirror::ByteArray>(&InstructionHandler::SetVReg);
David Srbecky6da82472018-10-23 14:03:08 +01001024 }
1025
David Srbeckybd613ec2019-05-30 15:39:38 +01001026 ALWAYS_INLINE bool AGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001027 return HandleAGet<mirror::CharArray>(&InstructionHandler::SetVReg);
David Srbecky6da82472018-10-23 14:03:08 +01001028 }
1029
David Srbeckybd613ec2019-05-30 15:39:38 +01001030 ALWAYS_INLINE bool AGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001031 return HandleAGet<mirror::ShortArray>(&InstructionHandler::SetVReg);
David Srbecky6da82472018-10-23 14:03:08 +01001032 }
1033
David Srbeckybd613ec2019-05-30 15:39:38 +01001034 ALWAYS_INLINE bool AGET() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001035 return HandleAGet<mirror::IntArray>(&InstructionHandler::SetVReg);
David Srbecky6da82472018-10-23 14:03:08 +01001036 }
1037
David Srbeckybd613ec2019-05-30 15:39:38 +01001038 ALWAYS_INLINE bool AGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001039 return HandleAGet<mirror::LongArray>(&InstructionHandler::SetVRegLong);
David Srbecky6da82472018-10-23 14:03:08 +01001040 }
1041
David Srbeckybd613ec2019-05-30 15:39:38 +01001042 ALWAYS_INLINE bool AGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001043 return HandleAGet<mirror::ObjectArray<mirror::Object>>(&InstructionHandler::SetVRegReference);
David Srbecky6da82472018-10-23 14:03:08 +01001044 }
1045
David Srbeckybd613ec2019-05-30 15:39:38 +01001046 ALWAYS_INLINE bool APUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001047 return HandleAPut<mirror::BooleanArray>(GetVReg(A()));
David Srbecky6da82472018-10-23 14:03:08 +01001048 }
1049
David Srbeckybd613ec2019-05-30 15:39:38 +01001050 ALWAYS_INLINE bool APUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001051 return HandleAPut<mirror::ByteArray>(GetVReg(A()));
David Srbecky6da82472018-10-23 14:03:08 +01001052 }
1053
David Srbeckybd613ec2019-05-30 15:39:38 +01001054 ALWAYS_INLINE bool APUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001055 return HandleAPut<mirror::CharArray>(GetVReg(A()));
David Srbecky6da82472018-10-23 14:03:08 +01001056 }
1057
David Srbeckybd613ec2019-05-30 15:39:38 +01001058 ALWAYS_INLINE bool APUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001059 return HandleAPut<mirror::ShortArray>(GetVReg(A()));
David Srbecky6da82472018-10-23 14:03:08 +01001060 }
1061
David Srbeckybd613ec2019-05-30 15:39:38 +01001062 ALWAYS_INLINE bool APUT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001063 return HandleAPut<mirror::IntArray>(GetVReg(A()));
David Srbecky6da82472018-10-23 14:03:08 +01001064 }
1065
David Srbeckybd613ec2019-05-30 15:39:38 +01001066 ALWAYS_INLINE bool APUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001067 return HandleAPut<mirror::LongArray>(GetVRegLong(A()));
David Srbecky6da82472018-10-23 14:03:08 +01001068 }
1069
David Srbeckybd613ec2019-05-30 15:39:38 +01001070 ALWAYS_INLINE bool APUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001071 ObjPtr<mirror::Object> a = GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001072 if (UNLIKELY(a == nullptr)) {
1073 ThrowNullPointerExceptionFromInterpreter();
1074 HANDLE_PENDING_EXCEPTION();
1075 }
David Srbecky6baf6442019-05-30 14:57:43 +01001076 int32_t index = GetVReg(C());
1077 ObjPtr<mirror::Object> val = GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +01001078 ObjPtr<mirror::ObjectArray<mirror::Object>> array = a->AsObjectArray<mirror::Object>();
1079 if (array->CheckIsValidIndex(index) && array->CheckAssignable(val)) {
1080 array->SetWithoutChecks<transaction_active>(index, val);
David Srbecky6da82472018-10-23 14:03:08 +01001081 } else {
1082 HANDLE_PENDING_EXCEPTION();
1083 }
David Srbeckybd613ec2019-05-30 15:39:38 +01001084 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001085 }
1086
David Srbeckybd613ec2019-05-30 15:39:38 +01001087 ALWAYS_INLINE bool IGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001088 return HandleGet<InstancePrimitiveRead, Primitive::kPrimBoolean>();
David Srbecky6da82472018-10-23 14:03:08 +01001089 }
1090
David Srbeckybd613ec2019-05-30 15:39:38 +01001091 ALWAYS_INLINE bool IGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001092 return HandleGet<InstancePrimitiveRead, Primitive::kPrimByte>();
David Srbecky6da82472018-10-23 14:03:08 +01001093 }
1094
David Srbeckybd613ec2019-05-30 15:39:38 +01001095 ALWAYS_INLINE bool IGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001096 return HandleGet<InstancePrimitiveRead, Primitive::kPrimChar>();
David Srbecky6da82472018-10-23 14:03:08 +01001097 }
1098
David Srbeckybd613ec2019-05-30 15:39:38 +01001099 ALWAYS_INLINE bool IGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001100 return HandleGet<InstancePrimitiveRead, Primitive::kPrimShort>();
David Srbecky6da82472018-10-23 14:03:08 +01001101 }
1102
David Srbeckybd613ec2019-05-30 15:39:38 +01001103 ALWAYS_INLINE bool IGET() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001104 return HandleGet<InstancePrimitiveRead, Primitive::kPrimInt>();
David Srbecky6da82472018-10-23 14:03:08 +01001105 }
1106
David Srbeckybd613ec2019-05-30 15:39:38 +01001107 ALWAYS_INLINE bool IGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001108 return HandleGet<InstancePrimitiveRead, Primitive::kPrimLong>();
David Srbecky6da82472018-10-23 14:03:08 +01001109 }
1110
David Srbeckybd613ec2019-05-30 15:39:38 +01001111 ALWAYS_INLINE bool IGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001112 return HandleGet<InstanceObjectRead, Primitive::kPrimNot>();
David Srbecky6da82472018-10-23 14:03:08 +01001113 }
1114
David Srbeckybd613ec2019-05-30 15:39:38 +01001115 ALWAYS_INLINE bool IGET_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001116 return HandleGetQuick<Primitive::kPrimInt>();
David Srbecky6da82472018-10-23 14:03:08 +01001117 }
1118
David Srbeckybd613ec2019-05-30 15:39:38 +01001119 ALWAYS_INLINE bool IGET_WIDE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001120 return HandleGetQuick<Primitive::kPrimLong>();
David Srbecky6da82472018-10-23 14:03:08 +01001121 }
1122
David Srbeckybd613ec2019-05-30 15:39:38 +01001123 ALWAYS_INLINE bool IGET_OBJECT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001124 return HandleGetQuick<Primitive::kPrimNot>();
David Srbecky6da82472018-10-23 14:03:08 +01001125 }
1126
David Srbeckybd613ec2019-05-30 15:39:38 +01001127 ALWAYS_INLINE bool IGET_BOOLEAN_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001128 return HandleGetQuick<Primitive::kPrimBoolean>();
David Srbecky6da82472018-10-23 14:03:08 +01001129 }
1130
David Srbeckybd613ec2019-05-30 15:39:38 +01001131 ALWAYS_INLINE bool IGET_BYTE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001132 return HandleGetQuick<Primitive::kPrimByte>();
David Srbecky6da82472018-10-23 14:03:08 +01001133 }
1134
David Srbeckybd613ec2019-05-30 15:39:38 +01001135 ALWAYS_INLINE bool IGET_CHAR_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001136 return HandleGetQuick<Primitive::kPrimChar>();
David Srbecky6da82472018-10-23 14:03:08 +01001137 }
1138
David Srbeckybd613ec2019-05-30 15:39:38 +01001139 ALWAYS_INLINE bool IGET_SHORT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001140 return HandleGetQuick<Primitive::kPrimShort>();
David Srbecky6da82472018-10-23 14:03:08 +01001141 }
1142
David Srbeckybd613ec2019-05-30 15:39:38 +01001143 ALWAYS_INLINE bool SGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001144 return HandleGet<StaticPrimitiveRead, Primitive::kPrimBoolean>();
David Srbecky6da82472018-10-23 14:03:08 +01001145 }
1146
David Srbeckybd613ec2019-05-30 15:39:38 +01001147 ALWAYS_INLINE bool SGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001148 return HandleGet<StaticPrimitiveRead, Primitive::kPrimByte>();
David Srbecky6da82472018-10-23 14:03:08 +01001149 }
1150
David Srbeckybd613ec2019-05-30 15:39:38 +01001151 ALWAYS_INLINE bool SGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001152 return HandleGet<StaticPrimitiveRead, Primitive::kPrimChar>();
David Srbecky6da82472018-10-23 14:03:08 +01001153 }
1154
David Srbeckybd613ec2019-05-30 15:39:38 +01001155 ALWAYS_INLINE bool SGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001156 return HandleGet<StaticPrimitiveRead, Primitive::kPrimShort>();
David Srbecky6da82472018-10-23 14:03:08 +01001157 }
1158
David Srbeckybd613ec2019-05-30 15:39:38 +01001159 ALWAYS_INLINE bool SGET() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001160 return HandleGet<StaticPrimitiveRead, Primitive::kPrimInt>();
David Srbecky6da82472018-10-23 14:03:08 +01001161 }
1162
David Srbeckybd613ec2019-05-30 15:39:38 +01001163 ALWAYS_INLINE bool SGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001164 return HandleGet<StaticPrimitiveRead, Primitive::kPrimLong>();
David Srbecky6da82472018-10-23 14:03:08 +01001165 }
1166
David Srbeckybd613ec2019-05-30 15:39:38 +01001167 ALWAYS_INLINE bool SGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001168 return HandleGet<StaticObjectRead, Primitive::kPrimNot>();
David Srbecky6da82472018-10-23 14:03:08 +01001169 }
1170
David Srbeckybd613ec2019-05-30 15:39:38 +01001171 ALWAYS_INLINE bool IPUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001172 return HandlePut<InstancePrimitiveWrite, Primitive::kPrimBoolean>();
David Srbecky6da82472018-10-23 14:03:08 +01001173 }
1174
David Srbeckybd613ec2019-05-30 15:39:38 +01001175 ALWAYS_INLINE bool IPUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001176 return HandlePut<InstancePrimitiveWrite, Primitive::kPrimByte>();
David Srbecky6da82472018-10-23 14:03:08 +01001177 }
1178
David Srbeckybd613ec2019-05-30 15:39:38 +01001179 ALWAYS_INLINE bool IPUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001180 return HandlePut<InstancePrimitiveWrite, Primitive::kPrimChar>();
David Srbecky6da82472018-10-23 14:03:08 +01001181 }
1182
David Srbeckybd613ec2019-05-30 15:39:38 +01001183 ALWAYS_INLINE bool IPUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001184 return HandlePut<InstancePrimitiveWrite, Primitive::kPrimShort>();
David Srbecky6da82472018-10-23 14:03:08 +01001185 }
1186
David Srbeckybd613ec2019-05-30 15:39:38 +01001187 ALWAYS_INLINE bool IPUT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001188 return HandlePut<InstancePrimitiveWrite, Primitive::kPrimInt>();
David Srbecky6da82472018-10-23 14:03:08 +01001189 }
1190
David Srbeckybd613ec2019-05-30 15:39:38 +01001191 ALWAYS_INLINE bool IPUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001192 return HandlePut<InstancePrimitiveWrite, Primitive::kPrimLong>();
David Srbecky6da82472018-10-23 14:03:08 +01001193 }
1194
David Srbeckybd613ec2019-05-30 15:39:38 +01001195 ALWAYS_INLINE bool IPUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001196 return HandlePut<InstanceObjectWrite, Primitive::kPrimNot>();
David Srbecky6da82472018-10-23 14:03:08 +01001197 }
1198
David Srbeckybd613ec2019-05-30 15:39:38 +01001199 ALWAYS_INLINE bool IPUT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001200 return HandlePutQuick<Primitive::kPrimInt>();
David Srbecky6da82472018-10-23 14:03:08 +01001201 }
1202
David Srbeckybd613ec2019-05-30 15:39:38 +01001203 ALWAYS_INLINE bool IPUT_BOOLEAN_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001204 return HandlePutQuick<Primitive::kPrimBoolean>();
David Srbecky6da82472018-10-23 14:03:08 +01001205 }
1206
David Srbeckybd613ec2019-05-30 15:39:38 +01001207 ALWAYS_INLINE bool IPUT_BYTE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001208 return HandlePutQuick<Primitive::kPrimByte>();
David Srbecky6da82472018-10-23 14:03:08 +01001209 }
1210
David Srbeckybd613ec2019-05-30 15:39:38 +01001211 ALWAYS_INLINE bool IPUT_CHAR_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001212 return HandlePutQuick<Primitive::kPrimChar>();
David Srbecky6da82472018-10-23 14:03:08 +01001213 }
1214
David Srbeckybd613ec2019-05-30 15:39:38 +01001215 ALWAYS_INLINE bool IPUT_SHORT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001216 return HandlePutQuick<Primitive::kPrimShort>();
David Srbecky6da82472018-10-23 14:03:08 +01001217 }
1218
David Srbeckybd613ec2019-05-30 15:39:38 +01001219 ALWAYS_INLINE bool IPUT_WIDE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001220 return HandlePutQuick<Primitive::kPrimLong>();
David Srbecky6da82472018-10-23 14:03:08 +01001221 }
1222
David Srbeckybd613ec2019-05-30 15:39:38 +01001223 ALWAYS_INLINE bool IPUT_OBJECT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001224 return HandlePutQuick<Primitive::kPrimNot>();
David Srbecky6da82472018-10-23 14:03:08 +01001225 }
1226
David Srbeckybd613ec2019-05-30 15:39:38 +01001227 ALWAYS_INLINE bool SPUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001228 return HandlePut<StaticPrimitiveWrite, Primitive::kPrimBoolean>();
David Srbecky6da82472018-10-23 14:03:08 +01001229 }
1230
David Srbeckybd613ec2019-05-30 15:39:38 +01001231 ALWAYS_INLINE bool SPUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001232 return HandlePut<StaticPrimitiveWrite, Primitive::kPrimByte>();
David Srbecky6da82472018-10-23 14:03:08 +01001233 }
1234
David Srbeckybd613ec2019-05-30 15:39:38 +01001235 ALWAYS_INLINE bool SPUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001236 return HandlePut<StaticPrimitiveWrite, Primitive::kPrimChar>();
David Srbecky6da82472018-10-23 14:03:08 +01001237 }
1238
David Srbeckybd613ec2019-05-30 15:39:38 +01001239 ALWAYS_INLINE bool SPUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001240 return HandlePut<StaticPrimitiveWrite, Primitive::kPrimShort>();
David Srbecky6da82472018-10-23 14:03:08 +01001241 }
1242
David Srbeckybd613ec2019-05-30 15:39:38 +01001243 ALWAYS_INLINE bool SPUT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001244 return HandlePut<StaticPrimitiveWrite, Primitive::kPrimInt>();
David Srbecky6da82472018-10-23 14:03:08 +01001245 }
1246
David Srbeckybd613ec2019-05-30 15:39:38 +01001247 ALWAYS_INLINE bool SPUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001248 return HandlePut<StaticPrimitiveWrite, Primitive::kPrimLong>();
David Srbecky6da82472018-10-23 14:03:08 +01001249 }
1250
David Srbeckybd613ec2019-05-30 15:39:38 +01001251 ALWAYS_INLINE bool SPUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001252 return HandlePut<StaticObjectWrite, Primitive::kPrimNot>();
David Srbecky6da82472018-10-23 14:03:08 +01001253 }
1254
David Srbeckybd613ec2019-05-30 15:39:38 +01001255 ALWAYS_INLINE bool INVOKE_VIRTUAL() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001256 return HandleInvoke<kVirtual, /*is_range=*/ false>();
David Srbecky6da82472018-10-23 14:03:08 +01001257 }
1258
David Srbeckybd613ec2019-05-30 15:39:38 +01001259 ALWAYS_INLINE bool INVOKE_VIRTUAL_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001260 return HandleInvoke<kVirtual, /*is_range=*/ true>();
David Srbecky6da82472018-10-23 14:03:08 +01001261 }
1262
David Srbeckybd613ec2019-05-30 15:39:38 +01001263 ALWAYS_INLINE bool INVOKE_SUPER() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001264 return HandleInvoke<kSuper, /*is_range=*/ false>();
David Srbecky6da82472018-10-23 14:03:08 +01001265 }
1266
David Srbeckybd613ec2019-05-30 15:39:38 +01001267 ALWAYS_INLINE bool INVOKE_SUPER_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001268 return HandleInvoke<kSuper, /*is_range=*/ true>();
David Srbecky6da82472018-10-23 14:03:08 +01001269 }
1270
David Srbeckybd613ec2019-05-30 15:39:38 +01001271 ALWAYS_INLINE bool INVOKE_DIRECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001272 return HandleInvoke<kDirect, /*is_range=*/ false>();
David Srbecky6da82472018-10-23 14:03:08 +01001273 }
1274
David Srbeckybd613ec2019-05-30 15:39:38 +01001275 ALWAYS_INLINE bool INVOKE_DIRECT_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001276 return HandleInvoke<kDirect, /*is_range=*/ true>();
David Srbecky6da82472018-10-23 14:03:08 +01001277 }
1278
David Srbeckybd613ec2019-05-30 15:39:38 +01001279 ALWAYS_INLINE bool INVOKE_INTERFACE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001280 return HandleInvoke<kInterface, /*is_range=*/ false>();
David Srbecky6da82472018-10-23 14:03:08 +01001281 }
1282
David Srbeckybd613ec2019-05-30 15:39:38 +01001283 ALWAYS_INLINE bool INVOKE_INTERFACE_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001284 return HandleInvoke<kInterface, /*is_range=*/ true>();
David Srbecky6da82472018-10-23 14:03:08 +01001285 }
1286
David Srbeckybd613ec2019-05-30 15:39:38 +01001287 ALWAYS_INLINE bool INVOKE_STATIC() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001288 return HandleInvoke<kStatic, /*is_range=*/ false>();
David Srbecky6da82472018-10-23 14:03:08 +01001289 }
1290
David Srbeckybd613ec2019-05-30 15:39:38 +01001291 ALWAYS_INLINE bool INVOKE_STATIC_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001292 return HandleInvoke<kStatic, /*is_range=*/ true>();
David Srbecky6da82472018-10-23 14:03:08 +01001293 }
1294
David Srbeckybd613ec2019-05-30 15:39:38 +01001295 ALWAYS_INLINE bool INVOKE_VIRTUAL_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001296 return HandleInvoke<kVirtual, /*is_range=*/ false, /*is_quick=*/ true>();
David Srbecky6da82472018-10-23 14:03:08 +01001297 }
1298
David Srbeckybd613ec2019-05-30 15:39:38 +01001299 ALWAYS_INLINE bool INVOKE_VIRTUAL_RANGE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001300 return HandleInvoke<kVirtual, /*is_range=*/ true, /*is_quick=*/ true>();
David Srbecky6da82472018-10-23 14:03:08 +01001301 }
1302
David Srbeckybd613ec2019-05-30 15:39:38 +01001303 ALWAYS_INLINE bool INVOKE_POLYMORPHIC() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001304 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1305 bool success = DoInvokePolymorphic</* is_range= */ false>(
1306 self, shadow_frame, inst, inst_data, ResultRegister());
1307 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(!success);
David Srbeckybd613ec2019-05-30 15:39:38 +01001308 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001309 }
1310
David Srbeckybd613ec2019-05-30 15:39:38 +01001311 ALWAYS_INLINE bool INVOKE_POLYMORPHIC_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001312 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1313 bool success = DoInvokePolymorphic</* is_range= */ true>(
1314 self, shadow_frame, inst, inst_data, ResultRegister());
1315 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(!success);
David Srbeckybd613ec2019-05-30 15:39:38 +01001316 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001317 }
1318
David Srbeckybd613ec2019-05-30 15:39:38 +01001319 ALWAYS_INLINE bool INVOKE_CUSTOM() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001320 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1321 bool success = DoInvokeCustom</* is_range= */ false>(
1322 self, shadow_frame, inst, inst_data, ResultRegister());
1323 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
David Srbeckybd613ec2019-05-30 15:39:38 +01001324 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001325 }
1326
David Srbeckybd613ec2019-05-30 15:39:38 +01001327 ALWAYS_INLINE bool INVOKE_CUSTOM_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001328 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1329 bool success = DoInvokeCustom</* is_range= */ true>(
1330 self, shadow_frame, inst, inst_data, ResultRegister());
1331 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
David Srbeckybd613ec2019-05-30 15:39:38 +01001332 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001333 }
1334
David Srbeckybd613ec2019-05-30 15:39:38 +01001335 ALWAYS_INLINE bool NEG_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001336 SetVReg(A(), -GetVReg(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001337 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001338 }
1339
David Srbeckybd613ec2019-05-30 15:39:38 +01001340 ALWAYS_INLINE bool NOT_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001341 SetVReg(A(), ~GetVReg(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001342 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001343 }
1344
David Srbeckybd613ec2019-05-30 15:39:38 +01001345 ALWAYS_INLINE bool NEG_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001346 SetVRegLong(A(), -GetVRegLong(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001347 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001348 }
1349
David Srbeckybd613ec2019-05-30 15:39:38 +01001350 ALWAYS_INLINE bool NOT_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001351 SetVRegLong(A(), ~GetVRegLong(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001352 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001353 }
1354
David Srbeckybd613ec2019-05-30 15:39:38 +01001355 ALWAYS_INLINE bool NEG_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001356 SetVRegFloat(A(), -GetVRegFloat(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001357 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001358 }
1359
David Srbeckybd613ec2019-05-30 15:39:38 +01001360 ALWAYS_INLINE bool NEG_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001361 SetVRegDouble(A(), -GetVRegDouble(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001362 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001363 }
1364
David Srbeckybd613ec2019-05-30 15:39:38 +01001365 ALWAYS_INLINE bool INT_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001366 SetVRegLong(A(), GetVReg(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001367 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001368 }
1369
David Srbeckybd613ec2019-05-30 15:39:38 +01001370 ALWAYS_INLINE bool INT_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001371 SetVRegFloat(A(), GetVReg(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001372 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001373 }
1374
David Srbeckybd613ec2019-05-30 15:39:38 +01001375 ALWAYS_INLINE bool INT_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001376 SetVRegDouble(A(), GetVReg(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001377 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001378 }
1379
David Srbeckybd613ec2019-05-30 15:39:38 +01001380 ALWAYS_INLINE bool LONG_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001381 SetVReg(A(), GetVRegLong(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001382 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001383 }
1384
David Srbeckybd613ec2019-05-30 15:39:38 +01001385 ALWAYS_INLINE bool LONG_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001386 SetVRegFloat(A(), GetVRegLong(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001387 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001388 }
1389
David Srbeckybd613ec2019-05-30 15:39:38 +01001390 ALWAYS_INLINE bool LONG_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001391 SetVRegDouble(A(), GetVRegLong(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001392 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001393 }
1394
David Srbeckybd613ec2019-05-30 15:39:38 +01001395 ALWAYS_INLINE bool FLOAT_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001396 float val = GetVRegFloat(B());
David Srbecky6da82472018-10-23 14:03:08 +01001397 int32_t result = art_float_to_integral<int32_t, float>(val);
David Srbecky6baf6442019-05-30 14:57:43 +01001398 SetVReg(A(), result);
David Srbeckybd613ec2019-05-30 15:39:38 +01001399 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001400 }
1401
David Srbeckybd613ec2019-05-30 15:39:38 +01001402 ALWAYS_INLINE bool FLOAT_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001403 float val = GetVRegFloat(B());
David Srbecky6da82472018-10-23 14:03:08 +01001404 int64_t result = art_float_to_integral<int64_t, float>(val);
David Srbecky6baf6442019-05-30 14:57:43 +01001405 SetVRegLong(A(), result);
David Srbeckybd613ec2019-05-30 15:39:38 +01001406 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001407 }
1408
David Srbeckybd613ec2019-05-30 15:39:38 +01001409 ALWAYS_INLINE bool FLOAT_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001410 SetVRegDouble(A(), GetVRegFloat(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001411 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001412 }
1413
David Srbeckybd613ec2019-05-30 15:39:38 +01001414 ALWAYS_INLINE bool DOUBLE_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001415 double val = GetVRegDouble(B());
David Srbecky6da82472018-10-23 14:03:08 +01001416 int32_t result = art_float_to_integral<int32_t, double>(val);
David Srbecky6baf6442019-05-30 14:57:43 +01001417 SetVReg(A(), result);
David Srbeckybd613ec2019-05-30 15:39:38 +01001418 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001419 }
1420
David Srbeckybd613ec2019-05-30 15:39:38 +01001421 ALWAYS_INLINE bool DOUBLE_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001422 double val = GetVRegDouble(B());
David Srbecky6da82472018-10-23 14:03:08 +01001423 int64_t result = art_float_to_integral<int64_t, double>(val);
David Srbecky6baf6442019-05-30 14:57:43 +01001424 SetVRegLong(A(), result);
David Srbeckybd613ec2019-05-30 15:39:38 +01001425 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001426 }
1427
David Srbeckybd613ec2019-05-30 15:39:38 +01001428 ALWAYS_INLINE bool DOUBLE_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001429 SetVRegFloat(A(), GetVRegDouble(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001430 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001431 }
1432
David Srbeckybd613ec2019-05-30 15:39:38 +01001433 ALWAYS_INLINE bool INT_TO_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001434 SetVReg(A(), static_cast<int8_t>(GetVReg(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001435 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001436 }
1437
David Srbeckybd613ec2019-05-30 15:39:38 +01001438 ALWAYS_INLINE bool INT_TO_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001439 SetVReg(A(), static_cast<uint16_t>(GetVReg(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001440 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001441 }
1442
David Srbeckybd613ec2019-05-30 15:39:38 +01001443 ALWAYS_INLINE bool INT_TO_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001444 SetVReg(A(), static_cast<int16_t>(GetVReg(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001445 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001446 }
1447
David Srbeckybd613ec2019-05-30 15:39:38 +01001448 ALWAYS_INLINE bool ADD_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001449 SetVReg(A(), SafeAdd(GetVReg(B()), GetVReg(C())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001450 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001451 }
1452
David Srbeckybd613ec2019-05-30 15:39:38 +01001453 ALWAYS_INLINE bool SUB_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001454 SetVReg(A(), SafeSub(GetVReg(B()), GetVReg(C())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001455 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001456 }
1457
David Srbeckybd613ec2019-05-30 15:39:38 +01001458 ALWAYS_INLINE bool MUL_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001459 SetVReg(A(), SafeMul(GetVReg(B()), GetVReg(C())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001460 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001461 }
1462
David Srbeckybd613ec2019-05-30 15:39:38 +01001463 ALWAYS_INLINE bool DIV_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001464 bool success = DoIntDivide(shadow_frame, A(), GetVReg(B()), GetVReg(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001465 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001466 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001467 }
1468
David Srbeckybd613ec2019-05-30 15:39:38 +01001469 ALWAYS_INLINE bool REM_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001470 bool success = DoIntRemainder(shadow_frame, A(), GetVReg(B()), GetVReg(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001471 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001472 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001473 }
1474
David Srbeckybd613ec2019-05-30 15:39:38 +01001475 ALWAYS_INLINE bool SHL_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001476 SetVReg(A(), GetVReg(B()) << (GetVReg(C()) & 0x1f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001477 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001478 }
1479
David Srbeckybd613ec2019-05-30 15:39:38 +01001480 ALWAYS_INLINE bool SHR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001481 SetVReg(A(), GetVReg(B()) >> (GetVReg(C()) & 0x1f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001482 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001483 }
1484
David Srbeckybd613ec2019-05-30 15:39:38 +01001485 ALWAYS_INLINE bool USHR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001486 SetVReg(A(), static_cast<uint32_t>(GetVReg(B())) >> (GetVReg(C()) & 0x1f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001487 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001488 }
1489
David Srbeckybd613ec2019-05-30 15:39:38 +01001490 ALWAYS_INLINE bool AND_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001491 SetVReg(A(), GetVReg(B()) & GetVReg(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001492 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001493 }
1494
David Srbeckybd613ec2019-05-30 15:39:38 +01001495 ALWAYS_INLINE bool OR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001496 SetVReg(A(), GetVReg(B()) | GetVReg(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001497 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001498 }
1499
David Srbeckybd613ec2019-05-30 15:39:38 +01001500 ALWAYS_INLINE bool XOR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001501 SetVReg(A(), GetVReg(B()) ^ GetVReg(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001502 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001503 }
1504
David Srbeckybd613ec2019-05-30 15:39:38 +01001505 ALWAYS_INLINE bool ADD_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001506 SetVRegLong(A(), SafeAdd(GetVRegLong(B()), GetVRegLong(C())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001507 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001508 }
1509
David Srbeckybd613ec2019-05-30 15:39:38 +01001510 ALWAYS_INLINE bool SUB_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001511 SetVRegLong(A(), SafeSub(GetVRegLong(B()), GetVRegLong(C())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001512 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001513 }
1514
David Srbeckybd613ec2019-05-30 15:39:38 +01001515 ALWAYS_INLINE bool MUL_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001516 SetVRegLong(A(), SafeMul(GetVRegLong(B()), GetVRegLong(C())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001517 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001518 }
1519
David Srbeckybd613ec2019-05-30 15:39:38 +01001520 ALWAYS_INLINE bool DIV_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001521 DoLongDivide(shadow_frame, A(), GetVRegLong(B()), GetVRegLong(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001522 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_2xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001523 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001524 }
1525
David Srbeckybd613ec2019-05-30 15:39:38 +01001526 ALWAYS_INLINE bool REM_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001527 DoLongRemainder(shadow_frame, A(), GetVRegLong(B()), GetVRegLong(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001528 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_2xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001529 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001530 }
1531
David Srbeckybd613ec2019-05-30 15:39:38 +01001532 ALWAYS_INLINE bool AND_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001533 SetVRegLong(A(), GetVRegLong(B()) & GetVRegLong(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001534 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001535 }
1536
David Srbeckybd613ec2019-05-30 15:39:38 +01001537 ALWAYS_INLINE bool OR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001538 SetVRegLong(A(), GetVRegLong(B()) | GetVRegLong(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001539 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001540 }
1541
David Srbeckybd613ec2019-05-30 15:39:38 +01001542 ALWAYS_INLINE bool XOR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001543 SetVRegLong(A(), GetVRegLong(B()) ^ GetVRegLong(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001544 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001545 }
1546
David Srbeckybd613ec2019-05-30 15:39:38 +01001547 ALWAYS_INLINE bool SHL_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001548 SetVRegLong(A(), GetVRegLong(B()) << (GetVReg(C()) & 0x3f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001549 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001550 }
1551
David Srbeckybd613ec2019-05-30 15:39:38 +01001552 ALWAYS_INLINE bool SHR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001553 SetVRegLong(A(), GetVRegLong(B()) >> (GetVReg(C()) & 0x3f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001554 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001555 }
1556
David Srbeckybd613ec2019-05-30 15:39:38 +01001557 ALWAYS_INLINE bool USHR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001558 SetVRegLong(A(), static_cast<uint64_t>(GetVRegLong(B())) >> (GetVReg(C()) & 0x3f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001559 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001560 }
1561
David Srbeckybd613ec2019-05-30 15:39:38 +01001562 ALWAYS_INLINE bool ADD_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001563 SetVRegFloat(A(), GetVRegFloat(B()) + GetVRegFloat(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001564 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001565 }
1566
David Srbeckybd613ec2019-05-30 15:39:38 +01001567 ALWAYS_INLINE bool SUB_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001568 SetVRegFloat(A(), GetVRegFloat(B()) - GetVRegFloat(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001569 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001570 }
1571
David Srbeckybd613ec2019-05-30 15:39:38 +01001572 ALWAYS_INLINE bool MUL_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001573 SetVRegFloat(A(), GetVRegFloat(B()) * GetVRegFloat(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001574 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001575 }
1576
David Srbeckybd613ec2019-05-30 15:39:38 +01001577 ALWAYS_INLINE bool DIV_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001578 SetVRegFloat(A(), GetVRegFloat(B()) / GetVRegFloat(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001579 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001580 }
1581
David Srbeckybd613ec2019-05-30 15:39:38 +01001582 ALWAYS_INLINE bool REM_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001583 SetVRegFloat(A(), fmodf(GetVRegFloat(B()), GetVRegFloat(C())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001584 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001585 }
1586
David Srbeckybd613ec2019-05-30 15:39:38 +01001587 ALWAYS_INLINE bool ADD_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001588 SetVRegDouble(A(), GetVRegDouble(B()) + GetVRegDouble(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001589 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001590 }
1591
David Srbeckybd613ec2019-05-30 15:39:38 +01001592 ALWAYS_INLINE bool SUB_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001593 SetVRegDouble(A(), GetVRegDouble(B()) - GetVRegDouble(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001594 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001595 }
1596
David Srbeckybd613ec2019-05-30 15:39:38 +01001597 ALWAYS_INLINE bool MUL_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001598 SetVRegDouble(A(), GetVRegDouble(B()) * GetVRegDouble(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001599 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001600 }
1601
David Srbeckybd613ec2019-05-30 15:39:38 +01001602 ALWAYS_INLINE bool DIV_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001603 SetVRegDouble(A(), GetVRegDouble(B()) / GetVRegDouble(C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001604 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001605 }
1606
David Srbeckybd613ec2019-05-30 15:39:38 +01001607 ALWAYS_INLINE bool REM_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001608 SetVRegDouble(A(), fmod(GetVRegDouble(B()), GetVRegDouble(C())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001609 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001610 }
1611
David Srbeckybd613ec2019-05-30 15:39:38 +01001612 ALWAYS_INLINE bool ADD_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001613 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001614 SetVReg(vregA, SafeAdd(GetVReg(vregA), GetVReg(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001615 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001616 }
1617
David Srbeckybd613ec2019-05-30 15:39:38 +01001618 ALWAYS_INLINE bool SUB_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001619 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001620 SetVReg(vregA, SafeSub(GetVReg(vregA), GetVReg(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001621 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001622 }
1623
David Srbeckybd613ec2019-05-30 15:39:38 +01001624 ALWAYS_INLINE bool MUL_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001625 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001626 SetVReg(vregA, SafeMul(GetVReg(vregA), GetVReg(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001627 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001628 }
1629
David Srbeckybd613ec2019-05-30 15:39:38 +01001630 ALWAYS_INLINE bool DIV_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001631 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001632 bool success = DoIntDivide(shadow_frame, vregA, GetVReg(vregA), GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001633 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_1xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001634 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001635 }
1636
David Srbeckybd613ec2019-05-30 15:39:38 +01001637 ALWAYS_INLINE bool REM_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001638 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001639 bool success = DoIntRemainder(shadow_frame, vregA, GetVReg(vregA), GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001640 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_1xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001641 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001642 }
1643
David Srbeckybd613ec2019-05-30 15:39:38 +01001644 ALWAYS_INLINE bool SHL_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001645 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001646 SetVReg(vregA, GetVReg(vregA) << (GetVReg(B()) & 0x1f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001647 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001648 }
1649
David Srbeckybd613ec2019-05-30 15:39:38 +01001650 ALWAYS_INLINE bool SHR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001651 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001652 SetVReg(vregA, GetVReg(vregA) >> (GetVReg(B()) & 0x1f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001653 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001654 }
1655
David Srbeckybd613ec2019-05-30 15:39:38 +01001656 ALWAYS_INLINE bool USHR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001657 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001658 SetVReg(vregA, static_cast<uint32_t>(GetVReg(vregA)) >> (GetVReg(B()) & 0x1f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001659 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001660 }
1661
David Srbeckybd613ec2019-05-30 15:39:38 +01001662 ALWAYS_INLINE bool AND_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001663 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001664 SetVReg(vregA, GetVReg(vregA) & GetVReg(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001665 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001666 }
1667
David Srbeckybd613ec2019-05-30 15:39:38 +01001668 ALWAYS_INLINE bool OR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001669 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001670 SetVReg(vregA, GetVReg(vregA) | GetVReg(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001671 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001672 }
1673
David Srbeckybd613ec2019-05-30 15:39:38 +01001674 ALWAYS_INLINE bool XOR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001675 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001676 SetVReg(vregA, GetVReg(vregA) ^ GetVReg(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001677 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001678 }
1679
David Srbeckybd613ec2019-05-30 15:39:38 +01001680 ALWAYS_INLINE bool ADD_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001681 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001682 SetVRegLong(vregA, SafeAdd(GetVRegLong(vregA), GetVRegLong(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001683 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001684 }
1685
David Srbeckybd613ec2019-05-30 15:39:38 +01001686 ALWAYS_INLINE bool SUB_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001687 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001688 SetVRegLong(vregA, SafeSub(GetVRegLong(vregA), GetVRegLong(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001689 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001690 }
1691
David Srbeckybd613ec2019-05-30 15:39:38 +01001692 ALWAYS_INLINE bool MUL_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001693 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001694 SetVRegLong(vregA, SafeMul(GetVRegLong(vregA), GetVRegLong(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001695 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001696 }
1697
David Srbeckybd613ec2019-05-30 15:39:38 +01001698 ALWAYS_INLINE bool DIV_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001699 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001700 DoLongDivide(shadow_frame, vregA, GetVRegLong(vregA), GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001701 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001702 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001703 }
1704
David Srbeckybd613ec2019-05-30 15:39:38 +01001705 ALWAYS_INLINE bool REM_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001706 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001707 DoLongRemainder(shadow_frame, vregA, GetVRegLong(vregA), GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001708 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001709 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001710 }
1711
David Srbeckybd613ec2019-05-30 15:39:38 +01001712 ALWAYS_INLINE bool AND_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001713 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001714 SetVRegLong(vregA, GetVRegLong(vregA) & GetVRegLong(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001715 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001716 }
1717
David Srbeckybd613ec2019-05-30 15:39:38 +01001718 ALWAYS_INLINE bool OR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001719 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001720 SetVRegLong(vregA, GetVRegLong(vregA) | GetVRegLong(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001721 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001722 }
1723
David Srbeckybd613ec2019-05-30 15:39:38 +01001724 ALWAYS_INLINE bool XOR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001725 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001726 SetVRegLong(vregA, GetVRegLong(vregA) ^ GetVRegLong(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001727 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001728 }
1729
David Srbeckybd613ec2019-05-30 15:39:38 +01001730 ALWAYS_INLINE bool SHL_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001731 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001732 SetVRegLong(vregA, GetVRegLong(vregA) << (GetVReg(B()) & 0x3f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001733 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001734 }
1735
David Srbeckybd613ec2019-05-30 15:39:38 +01001736 ALWAYS_INLINE bool SHR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001737 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001738 SetVRegLong(vregA, GetVRegLong(vregA) >> (GetVReg(B()) & 0x3f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001739 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001740 }
1741
David Srbeckybd613ec2019-05-30 15:39:38 +01001742 ALWAYS_INLINE bool USHR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001743 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001744 SetVRegLong(vregA, static_cast<uint64_t>(GetVRegLong(vregA)) >> (GetVReg(B()) & 0x3f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001745 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001746 }
1747
David Srbeckybd613ec2019-05-30 15:39:38 +01001748 ALWAYS_INLINE bool ADD_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001749 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001750 SetVRegFloat(vregA, GetVRegFloat(vregA) + GetVRegFloat(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001751 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001752 }
1753
David Srbeckybd613ec2019-05-30 15:39:38 +01001754 ALWAYS_INLINE bool SUB_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001755 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001756 SetVRegFloat(vregA, GetVRegFloat(vregA) - GetVRegFloat(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001757 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001758 }
1759
David Srbeckybd613ec2019-05-30 15:39:38 +01001760 ALWAYS_INLINE bool MUL_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001761 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001762 SetVRegFloat(vregA, GetVRegFloat(vregA) * GetVRegFloat(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001763 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001764 }
1765
David Srbeckybd613ec2019-05-30 15:39:38 +01001766 ALWAYS_INLINE bool DIV_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001767 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001768 SetVRegFloat(vregA, GetVRegFloat(vregA) / GetVRegFloat(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001769 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001770 }
1771
David Srbeckybd613ec2019-05-30 15:39:38 +01001772 ALWAYS_INLINE bool REM_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001773 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001774 SetVRegFloat(vregA, fmodf(GetVRegFloat(vregA), GetVRegFloat(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001775 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001776 }
1777
David Srbeckybd613ec2019-05-30 15:39:38 +01001778 ALWAYS_INLINE bool ADD_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001779 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001780 SetVRegDouble(vregA, GetVRegDouble(vregA) + GetVRegDouble(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001781 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001782 }
1783
David Srbeckybd613ec2019-05-30 15:39:38 +01001784 ALWAYS_INLINE bool SUB_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001785 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001786 SetVRegDouble(vregA, GetVRegDouble(vregA) - GetVRegDouble(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001787 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001788 }
1789
David Srbeckybd613ec2019-05-30 15:39:38 +01001790 ALWAYS_INLINE bool MUL_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001791 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001792 SetVRegDouble(vregA, GetVRegDouble(vregA) * GetVRegDouble(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001793 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001794 }
1795
David Srbeckybd613ec2019-05-30 15:39:38 +01001796 ALWAYS_INLINE bool DIV_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001797 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001798 SetVRegDouble(vregA, GetVRegDouble(vregA) / GetVRegDouble(B()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001799 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001800 }
1801
David Srbeckybd613ec2019-05-30 15:39:38 +01001802 ALWAYS_INLINE bool REM_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001803 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001804 SetVRegDouble(vregA, fmod(GetVRegDouble(vregA), GetVRegDouble(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001805 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001806 }
1807
David Srbeckybd613ec2019-05-30 15:39:38 +01001808 ALWAYS_INLINE bool ADD_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001809 SetVReg(A(), SafeAdd(GetVReg(B()), C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001810 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001811 }
1812
David Srbeckybd613ec2019-05-30 15:39:38 +01001813 ALWAYS_INLINE bool RSUB_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001814 SetVReg(A(), SafeSub(C(), GetVReg(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001815 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001816 }
1817
David Srbeckybd613ec2019-05-30 15:39:38 +01001818 ALWAYS_INLINE bool MUL_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001819 SetVReg(A(), SafeMul(GetVReg(B()), C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001820 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001821 }
1822
David Srbeckybd613ec2019-05-30 15:39:38 +01001823 ALWAYS_INLINE bool DIV_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001824 bool success = DoIntDivide(shadow_frame, A(), GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +01001825 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001826 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001827 }
1828
David Srbeckybd613ec2019-05-30 15:39:38 +01001829 ALWAYS_INLINE bool REM_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001830 bool success = DoIntRemainder(shadow_frame, A(), GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +01001831 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001832 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001833 }
1834
David Srbeckybd613ec2019-05-30 15:39:38 +01001835 ALWAYS_INLINE bool AND_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001836 SetVReg(A(), GetVReg(B()) & C());
David Srbeckybd613ec2019-05-30 15:39:38 +01001837 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001838 }
1839
David Srbeckybd613ec2019-05-30 15:39:38 +01001840 ALWAYS_INLINE bool OR_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001841 SetVReg(A(), GetVReg(B()) | C());
David Srbeckybd613ec2019-05-30 15:39:38 +01001842 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001843 }
1844
David Srbeckybd613ec2019-05-30 15:39:38 +01001845 ALWAYS_INLINE bool XOR_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001846 SetVReg(A(), GetVReg(B()) ^ C());
David Srbeckybd613ec2019-05-30 15:39:38 +01001847 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001848 }
1849
David Srbeckybd613ec2019-05-30 15:39:38 +01001850 ALWAYS_INLINE bool ADD_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001851 SetVReg(A(), SafeAdd(GetVReg(B()), C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001852 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001853 }
1854
David Srbeckybd613ec2019-05-30 15:39:38 +01001855 ALWAYS_INLINE bool RSUB_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001856 SetVReg(A(), SafeSub(C(), GetVReg(B())));
David Srbeckybd613ec2019-05-30 15:39:38 +01001857 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001858 }
1859
David Srbeckybd613ec2019-05-30 15:39:38 +01001860 ALWAYS_INLINE bool MUL_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001861 SetVReg(A(), SafeMul(GetVReg(B()), C()));
David Srbeckybd613ec2019-05-30 15:39:38 +01001862 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001863 }
1864
David Srbeckybd613ec2019-05-30 15:39:38 +01001865 ALWAYS_INLINE bool DIV_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001866 bool success = DoIntDivide(shadow_frame, A(), GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +01001867 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001868 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001869 }
1870
David Srbeckybd613ec2019-05-30 15:39:38 +01001871 ALWAYS_INLINE bool REM_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001872 bool success = DoIntRemainder(shadow_frame, A(), GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +01001873 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001874 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001875 }
1876
David Srbeckybd613ec2019-05-30 15:39:38 +01001877 ALWAYS_INLINE bool AND_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001878 SetVReg(A(), GetVReg(B()) & C());
David Srbeckybd613ec2019-05-30 15:39:38 +01001879 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001880 }
1881
David Srbeckybd613ec2019-05-30 15:39:38 +01001882 ALWAYS_INLINE bool OR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001883 SetVReg(A(), GetVReg(B()) | C());
David Srbeckybd613ec2019-05-30 15:39:38 +01001884 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001885 }
1886
David Srbeckybd613ec2019-05-30 15:39:38 +01001887 ALWAYS_INLINE bool XOR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001888 SetVReg(A(), GetVReg(B()) ^ C());
David Srbeckybd613ec2019-05-30 15:39:38 +01001889 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001890 }
1891
David Srbeckybd613ec2019-05-30 15:39:38 +01001892 ALWAYS_INLINE bool SHL_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001893 SetVReg(A(), GetVReg(B()) << (C() & 0x1f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001894 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001895 }
1896
David Srbeckybd613ec2019-05-30 15:39:38 +01001897 ALWAYS_INLINE bool SHR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001898 SetVReg(A(), GetVReg(B()) >> (C() & 0x1f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001899 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001900 }
1901
David Srbeckybd613ec2019-05-30 15:39:38 +01001902 ALWAYS_INLINE bool USHR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001903 SetVReg(A(), static_cast<uint32_t>(GetVReg(B())) >> (C() & 0x1f));
David Srbeckybd613ec2019-05-30 15:39:38 +01001904 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001905 }
1906
David Srbeckybd613ec2019-05-30 15:39:38 +01001907 ALWAYS_INLINE bool UNUSED_3E() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001908 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001909 }
1910
David Srbeckybd613ec2019-05-30 15:39:38 +01001911 ALWAYS_INLINE bool UNUSED_3F() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001912 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001913 }
1914
David Srbeckybd613ec2019-05-30 15:39:38 +01001915 ALWAYS_INLINE bool UNUSED_40() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001916 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001917 }
1918
David Srbeckybd613ec2019-05-30 15:39:38 +01001919 ALWAYS_INLINE bool UNUSED_41() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001920 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001921 }
1922
David Srbeckybd613ec2019-05-30 15:39:38 +01001923 ALWAYS_INLINE bool UNUSED_42() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001924 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001925 }
1926
David Srbeckybd613ec2019-05-30 15:39:38 +01001927 ALWAYS_INLINE bool UNUSED_43() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001928 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001929 }
1930
David Srbeckybd613ec2019-05-30 15:39:38 +01001931 ALWAYS_INLINE bool UNUSED_79() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001932 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001933 }
1934
David Srbeckybd613ec2019-05-30 15:39:38 +01001935 ALWAYS_INLINE bool UNUSED_7A() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001936 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001937 }
1938
David Srbeckybd613ec2019-05-30 15:39:38 +01001939 ALWAYS_INLINE bool UNUSED_F3() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001940 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001941 }
1942
David Srbeckybd613ec2019-05-30 15:39:38 +01001943 ALWAYS_INLINE bool UNUSED_F4() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001944 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001945 }
1946
David Srbeckybd613ec2019-05-30 15:39:38 +01001947 ALWAYS_INLINE bool UNUSED_F5() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001948 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001949 }
1950
David Srbeckybd613ec2019-05-30 15:39:38 +01001951 ALWAYS_INLINE bool UNUSED_F6() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001952 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001953 }
1954
David Srbeckybd613ec2019-05-30 15:39:38 +01001955 ALWAYS_INLINE bool UNUSED_F7() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001956 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001957 }
1958
David Srbeckybd613ec2019-05-30 15:39:38 +01001959 ALWAYS_INLINE bool UNUSED_F8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001960 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001961 }
1962
David Srbeckybd613ec2019-05-30 15:39:38 +01001963 ALWAYS_INLINE bool UNUSED_F9() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001964 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01001965 }
1966
1967 ALWAYS_INLINE InstructionHandler(SwitchImplContext* ctx,
1968 const instrumentation::Instrumentation* instrumentation,
1969 Thread* self,
1970 ShadowFrame& shadow_frame,
1971 uint16_t dex_pc,
David Srbeckyc56a23e2019-06-05 17:45:49 +01001972 const Instruction* inst,
David Srbecky6da82472018-10-23 14:03:08 +01001973 uint16_t inst_data,
David Srbecky8867f3b2019-05-31 20:01:46 +01001974 const Instruction*& next,
David Srbecky6da82472018-10-23 14:03:08 +01001975 bool& exit_interpreter_loop)
1976 : ctx(ctx),
1977 instrumentation(instrumentation),
1978 self(self),
1979 shadow_frame(shadow_frame),
1980 dex_pc(dex_pc),
1981 inst(inst),
1982 inst_data(inst_data),
David Srbecky8867f3b2019-05-31 20:01:46 +01001983 next(next),
David Srbecky6da82472018-10-23 14:03:08 +01001984 exit_interpreter_loop(exit_interpreter_loop) {
1985 }
1986
1987 private:
1988 static constexpr bool do_assignability_check = do_access_check;
Alex Lightb7c640d2019-03-20 15:52:13 -07001989 static constexpr MonitorState kMonitorState =
1990 do_assignability_check ? MonitorState::kCountingMonitors : MonitorState::kNormalMonitors;
David Srbecky6da82472018-10-23 14:03:08 +01001991
1992 const CodeItemDataAccessor& Accessor() { return ctx->accessor; }
1993 const uint16_t* Insns() { return ctx->accessor.Insns(); }
1994 JValue* ResultRegister() { return &ctx->result_register; }
1995
David Srbecky436f6c12019-05-22 13:28:42 +01001996 ALWAYS_INLINE int32_t A() { return inst->VRegA(kFormat, inst_data); }
1997 ALWAYS_INLINE int32_t B() { return inst->VRegB(kFormat, inst_data); }
1998 ALWAYS_INLINE int32_t C() { return inst->VRegC(kFormat); }
1999
David Srbecky6baf6442019-05-30 14:57:43 +01002000 int32_t GetVReg(size_t i) const { return shadow_frame.GetVReg(i); }
2001 int64_t GetVRegLong(size_t i) const { return shadow_frame.GetVRegLong(i); }
2002 float GetVRegFloat(size_t i) const { return shadow_frame.GetVRegFloat(i); }
2003 double GetVRegDouble(size_t i) const { return shadow_frame.GetVRegDouble(i); }
2004 ObjPtr<mirror::Object> GetVRegReference(size_t i) const REQUIRES_SHARED(Locks::mutator_lock_) {
2005 return shadow_frame.GetVRegReference(i);
2006 }
2007
2008 void SetVReg(size_t i, int32_t val) { shadow_frame.SetVReg(i, val); }
2009 void SetVRegLong(size_t i, int64_t val) { shadow_frame.SetVRegLong(i, val); }
2010 void SetVRegFloat(size_t i, float val) { shadow_frame.SetVRegFloat(i, val); }
2011 void SetVRegDouble(size_t i, double val) { shadow_frame.SetVRegDouble(i, val); }
2012 void SetVRegReference(size_t i, ObjPtr<mirror::Object> val)
2013 REQUIRES_SHARED(Locks::mutator_lock_) {
2014 shadow_frame.SetVRegReference(i, val);
2015 }
2016
David Srbecky8867f3b2019-05-31 20:01:46 +01002017 // Set the next instruction to be executed. It is the 'fall-through' instruction by default.
2018 ALWAYS_INLINE void SetNextInstruction(const Instruction* next_inst) {
2019 DCHECK_LT(next_inst->GetDexPc(Insns()), Accessor().InsnsSizeInCodeUnits());
2020 next = next_inst;
2021 }
2022
David Srbecky6da82472018-10-23 14:03:08 +01002023 SwitchImplContext* const ctx;
2024 const instrumentation::Instrumentation* const instrumentation;
2025 Thread* const self;
2026 ShadowFrame& shadow_frame;
2027 uint32_t const dex_pc;
David Srbeckyc56a23e2019-06-05 17:45:49 +01002028 const Instruction* const inst;
David Srbecky6da82472018-10-23 14:03:08 +01002029 uint16_t const inst_data;
David Srbecky8867f3b2019-05-31 20:01:46 +01002030 const Instruction*& next;
2031
David Srbecky6da82472018-10-23 14:03:08 +01002032 bool& exit_interpreter_loop;
2033};
2034
David Srbecky6da82472018-10-23 14:03:08 +01002035#undef BRANCH_INSTRUMENTATION
David Srbecky6da82472018-10-23 14:03:08 +01002036#undef POSSIBLY_HANDLE_PENDING_EXCEPTION
2037#undef POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE
2038#undef POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC
David Srbecky6da82472018-10-23 14:03:08 +01002039#undef HANDLE_PENDING_EXCEPTION
David Srbecky6da82472018-10-23 14:03:08 +01002040
Alex Light6f22e062018-10-05 15:05:12 -07002041// TODO On ASAN builds this function gets a huge stack frame. Since normally we run in the mterp
2042// this shouldn't cause any problems for stack overflow detection. Remove this once b/117341496 is
2043// fixed.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +01002044template<bool do_access_check, bool transaction_active>
Alex Light6f22e062018-10-05 15:05:12 -07002045ATTRIBUTE_NO_SANITIZE_ADDRESS void ExecuteSwitchImplCpp(SwitchImplContext* ctx) {
David Srbecky946bb092018-03-09 17:23:01 +00002046 Thread* self = ctx->self;
2047 const CodeItemDataAccessor& accessor = ctx->accessor;
2048 ShadowFrame& shadow_frame = ctx->shadow_frame;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002049 if (UNLIKELY(!shadow_frame.HasReferenceArray())) {
2050 LOG(FATAL) << "Invalid shadow frame for interpreter use";
David Srbecky946bb092018-03-09 17:23:01 +00002051 ctx->result = JValue();
2052 return;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002053 }
2054 self->VerifyStack();
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002055
2056 uint32_t dex_pc = shadow_frame.GetDexPC();
Mathieu Chartier2cebb242015-04-21 16:50:40 -07002057 const auto* const instrumentation = Runtime::Current()->GetInstrumentation();
Mathieu Chartier808c7a52017-12-15 11:19:33 -08002058 const uint16_t* const insns = accessor.Insns();
David Srbeckyc56a23e2019-06-05 17:45:49 +01002059 const Instruction* next = Instruction::At(insns + dex_pc);
Sebastien Hertz3b588e02013-09-11 14:33:18 +02002060 uint16_t inst_data;
Igor Murashkin6918bf12015-09-27 19:19:06 -07002061
Alex Light0aa7a5a2018-10-10 15:58:14 +00002062 DCHECK(!shadow_frame.GetForceRetryInstruction())
2063 << "Entered interpreter from invoke without retry instruction being handled!";
2064
David Srbecky6da82472018-10-23 14:03:08 +01002065 bool const interpret_one_instruction = ctx->interpret_one_instruction;
2066 while (true) {
David Srbeckyc56a23e2019-06-05 17:45:49 +01002067 const Instruction* const inst = next;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002068 dex_pc = inst->GetDexPc(insns);
2069 shadow_frame.SetDexPC(dex_pc);
Ian Rogerse94652f2014-12-02 11:13:19 -08002070 TraceExecution(shadow_frame, inst, dex_pc);
Sebastien Hertz3b588e02013-09-11 14:33:18 +02002071 inst_data = inst->Fetch16(0);
David Srbeckya4a96af2018-10-31 16:34:58 +00002072 {
2073 bool exit_loop = false;
David Srbecky436f6c12019-05-22 13:28:42 +01002074 InstructionHandler<do_access_check, transaction_active, Instruction::kInvalidFormat> handler(
David Srbecky8867f3b2019-05-31 20:01:46 +01002075 ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, next, exit_loop);
David Srbeckya4a96af2018-10-31 16:34:58 +00002076 if (!handler.Preamble()) {
2077 if (UNLIKELY(exit_loop)) {
2078 return;
2079 }
2080 if (UNLIKELY(interpret_one_instruction)) {
2081 break;
2082 }
2083 continue;
2084 }
2085 }
Sebastien Hertz3b588e02013-09-11 14:33:18 +02002086 switch (inst->Opcode(inst_data)) {
David Srbecky8867f3b2019-05-31 20:01:46 +01002087#define OPCODE_CASE(OPCODE, OPCODE_NAME, NAME, FORMAT, i, a, e, v) \
David Srbecky6da82472018-10-23 14:03:08 +01002088 case OPCODE: { \
David Srbeckyc56a23e2019-06-05 17:45:49 +01002089 next = inst->RelativeAt(Instruction::SizeInCodeUnits(Instruction::FORMAT)); \
David Srbecky6da82472018-10-23 14:03:08 +01002090 bool exit_loop = false; \
David Srbecky436f6c12019-05-22 13:28:42 +01002091 InstructionHandler<do_access_check, transaction_active, Instruction::FORMAT> handler( \
David Srbecky8867f3b2019-05-31 20:01:46 +01002092 ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, next, exit_loop); \
David Srbeckya4a96af2018-10-31 16:34:58 +00002093 handler.OPCODE_NAME(); \
David Srbecky6da82472018-10-23 14:03:08 +01002094 if (UNLIKELY(exit_loop)) { \
2095 return; \
2096 } \
2097 break; \
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002098 }
David Srbecky6da82472018-10-23 14:03:08 +01002099DEX_INSTRUCTION_LIST(OPCODE_CASE)
2100#undef OPCODE_CASE
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002101 }
David Srbecky6da82472018-10-23 14:03:08 +01002102 if (UNLIKELY(interpret_one_instruction)) {
David Srbeckya4a96af2018-10-31 16:34:58 +00002103 break;
David Srbecky6da82472018-10-23 14:03:08 +01002104 }
2105 }
David Srbeckya4a96af2018-10-31 16:34:58 +00002106 // Record where we stopped.
David Srbeckyc56a23e2019-06-05 17:45:49 +01002107 shadow_frame.SetDexPC(next->GetDexPc(insns));
David Srbeckya4a96af2018-10-31 16:34:58 +00002108 ctx->result = ctx->result_register;
2109 return;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002110} // NOLINT(readability/fn_size)
2111
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002112} // namespace interpreter
2113} // namespace art
David Srbecky2ee09ff2018-10-24 13:24:22 +01002114
2115#endif // ART_RUNTIME_INTERPRETER_INTERPRETER_SWITCH_IMPL_INL_H_