blob: 7553527d177dd90ad43a60c1cf3831de78725c11 [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 Light6f22e062018-10-05 15:05:12 -070023#include "base/memory_tool.h"
David Sehrc431b9d2018-03-02 12:01:51 -080024#include "base/quasi_atomic.h"
David Sehr9e734c72018-01-04 17:56:19 -080025#include "dex/dex_file_types.h"
David Srbecky6da82472018-10-23 14:03:08 +010026#include "dex/dex_instruction_list.h"
Alex Lighteb7c1442015-08-31 13:17:42 -070027#include "experimental_flags.h"
Sebastien Hertz8ece0502013-08-07 11:26:41 +020028#include "interpreter_common.h"
David Srbeckye3fc2d12018-11-30 13:41:14 +000029#include "jit/jit-inl.h"
Mathieu Chartier28bd2e42016-10-04 13:54:57 -070030#include "jvalue-inl.h"
Andreas Gampefd63bbf2018-10-29 12:55:35 -070031#include "mirror/string-alloc-inl.h"
Alex Light0aa7a5a2018-10-10 15:58:14 +000032#include "nth_caller_visitor.h"
Ian Rogersf72a11d2014-10-30 15:41:08 -070033#include "safe_math.h"
Vladimir Marko6ec2a1b2018-05-22 15:33:48 +010034#include "shadow_frame-inl.h"
Alex Light0aa7a5a2018-10-10 15:58:14 +000035#include "thread.h"
Sebastien Hertz8ece0502013-08-07 11:26:41 +020036
37namespace art {
38namespace interpreter {
39
David Srbecky6da82472018-10-23 14:03:08 +010040// Short-lived helper class which executes single DEX bytecode. It is inlined by compiler.
41//
42// The function names must match the names from dex_instruction_list.h and have no arguments.
43//
44// Any relevant execution information is stored in the fields - it should be kept to minimum.
45//
David Srbecky47ad3762018-10-31 12:43:40 +000046// Helper methods may return boolean value - in which case 'false' always means
47// "stop executing current opcode" (which does not necessarily exit the interpreter loop).
48//
David Srbecky436f6c12019-05-22 13:28:42 +010049template<bool do_access_check, bool transaction_active, Instruction::Format kFormat>
David Srbecky6da82472018-10-23 14:03:08 +010050class InstructionHandler {
51 public:
David Srbecky47ad3762018-10-31 12:43:40 +000052 ALWAYS_INLINE WARN_UNUSED bool CheckForceReturn()
53 REQUIRES_SHARED(Locks::mutator_lock_) {
54 if (UNLIKELY(shadow_frame.GetForcePopFrame())) {
55 DCHECK(PrevFrameWillRetry(self, shadow_frame))
56 << "Pop frame forced without previous frame ready to retry instruction!";
57 DCHECK(Runtime::Current()->AreNonStandardExitsEnabled());
58 if (UNLIKELY(NeedsMethodExitEvent(instrumentation))) {
59 SendMethodExitEvents(self,
60 instrumentation,
61 shadow_frame,
62 shadow_frame.GetThisObject(Accessor().InsSize()),
63 shadow_frame.GetMethod(),
64 inst->GetDexPc(Insns()),
65 JValue());
66 }
67 ctx->result = JValue(); /* Handled in caller. */
68 exit_interpreter_loop = true;
69 return false;
70 }
71 return true;
72 }
73
David Srbecky5f250012018-11-08 14:16:38 +000074 NO_INLINE WARN_UNUSED bool HandlePendingExceptionWithInstrumentationImpl(
David Srbecky47ad3762018-10-31 12:43:40 +000075 const instrumentation::Instrumentation* instr)
76 REQUIRES_SHARED(Locks::mutator_lock_) {
77 DCHECK(self->IsExceptionPending());
78 self->AllowThreadSuspension();
79 if (!CheckForceReturn()) {
80 return false;
81 }
82 if (!MoveToExceptionHandler(self, shadow_frame, instr)) {
83 /* Structured locking is to be enforced for abnormal termination, too. */
84 DoMonitorCheckOnExit<do_assignability_check>(self, &shadow_frame);
85 if (ctx->interpret_one_instruction) {
86 /* Signal mterp to return to caller */
87 shadow_frame.SetDexPC(dex::kDexNoIndex);
88 }
89 ctx->result = JValue(); /* Handled in caller. */
90 exit_interpreter_loop = true;
91 return false; // Return to caller.
92 }
93 if (!CheckForceReturn()) {
94 return false;
95 }
96 int32_t displacement =
97 static_cast<int32_t>(shadow_frame.GetDexPC()) - static_cast<int32_t>(dex_pc);
98 inst = inst->RelativeAt(displacement);
99 return false; // Stop executing this opcode and continue in the exception handler.
100 }
101
David Srbecky5f250012018-11-08 14:16:38 +0000102 // Forwards the call to the NO_INLINE HandlePendingExceptionWithInstrumentationImpl.
103 ALWAYS_INLINE WARN_UNUSED bool HandlePendingExceptionWithInstrumentation(
104 const instrumentation::Instrumentation* instr)
105 REQUIRES_SHARED(Locks::mutator_lock_) {
106 // We need to help the compiler a bit to make the NO_INLINE call efficient.
107 // * All handler fields should be in registers, so we do not want to take the object
108 // address (for 'this' argument). Make a copy of the handler just for the slow path.
109 // * The modifiable fields should also be in registers, so we don't want to store their
110 // address even in the handler copy. Make a copy of them just for the call as well.
111 const Instruction* inst_copy = inst;
112 bool exit_loop_copy = exit_interpreter_loop;
David Srbecky436f6c12019-05-22 13:28:42 +0100113 InstructionHandler<do_access_check, transaction_active, kFormat> handler_copy(
David Srbecky5f250012018-11-08 14:16:38 +0000114 ctx, instrumentation, self, shadow_frame, dex_pc, inst_copy, inst_data, exit_loop_copy);
115 bool result = handler_copy.HandlePendingExceptionWithInstrumentationImpl(instr);
116 inst = inst_copy;
117 exit_interpreter_loop = exit_loop_copy;
118 return result;
119 }
120
David Srbecky47ad3762018-10-31 12:43:40 +0000121 ALWAYS_INLINE WARN_UNUSED bool HandlePendingException()
122 REQUIRES_SHARED(Locks::mutator_lock_) {
123 return HandlePendingExceptionWithInstrumentation(instrumentation);
124 }
125
126 ALWAYS_INLINE WARN_UNUSED bool PossiblyHandlePendingExceptionOnInvokeImpl(
127 bool is_exception_pending,
128 const Instruction* next_inst)
129 REQUIRES_SHARED(Locks::mutator_lock_) {
130 if (UNLIKELY(shadow_frame.GetForceRetryInstruction())) {
131 /* Don't need to do anything except clear the flag and exception. We leave the */
132 /* instruction the same so it will be re-executed on the next go-around. */
133 DCHECK(inst->IsInvoke());
134 shadow_frame.SetForceRetryInstruction(false);
135 if (UNLIKELY(is_exception_pending)) {
136 DCHECK(self->IsExceptionPending());
137 if (kIsDebugBuild) {
138 LOG(WARNING) << "Suppressing exception for instruction-retry: "
139 << self->GetException()->Dump();
140 }
141 self->ClearException();
142 }
143 } else if (UNLIKELY(is_exception_pending)) {
144 /* Should have succeeded. */
145 DCHECK(!shadow_frame.GetForceRetryInstruction());
146 if (!HandlePendingException()) {
147 return false;
148 }
149 } else {
150 inst = next_inst;
151 }
152 return true;
153 }
154
155 ALWAYS_INLINE WARN_UNUSED bool PossiblyHandlePendingException(
156 bool is_exception_pending,
157 const Instruction* next_inst)
158 REQUIRES_SHARED(Locks::mutator_lock_) {
159 /* Should only be on invoke instructions. */
160 DCHECK(!shadow_frame.GetForceRetryInstruction());
161 if (UNLIKELY(is_exception_pending)) {
162 if (!HandlePendingException()) {
163 return false;
164 }
165 } else {
166 inst = next_inst;
167 }
168 return true;
169 }
170
171 ALWAYS_INLINE WARN_UNUSED bool HandleMonitorChecks()
172 REQUIRES_SHARED(Locks::mutator_lock_) {
173 if (!DoMonitorCheckOnExit<do_assignability_check>(self, &shadow_frame)) {
174 if (!HandlePendingException()) {
175 return false;
176 }
177 }
178 return true;
179 }
180
181 // Code to run before each dex instruction.
David Srbeckya4a96af2018-10-31 16:34:58 +0000182 ALWAYS_INLINE WARN_UNUSED bool Preamble()
David Srbecky47ad3762018-10-31 12:43:40 +0000183 REQUIRES_SHARED(Locks::mutator_lock_) {
184 /* We need to put this before & after the instrumentation to avoid having to put in a */
185 /* post-script macro. */
186 if (!CheckForceReturn()) {
187 return false;
188 }
189 if (UNLIKELY(instrumentation->HasDexPcListeners())) {
David Srbeckya4a96af2018-10-31 16:34:58 +0000190 uint8_t opcode = inst->Opcode(inst_data);
191 bool is_move_result_object = (opcode == Instruction::MOVE_RESULT_OBJECT);
192 JValue* save_ref = is_move_result_object ? &ctx->result_register : nullptr;
David Srbecky47ad3762018-10-31 12:43:40 +0000193 if (UNLIKELY(!DoDexPcMoveEvent(self,
194 Accessor(),
195 shadow_frame,
196 dex_pc,
197 instrumentation,
198 save_ref))) {
199 if (!HandlePendingException()) {
200 return false;
201 }
202 }
203 if (!CheckForceReturn()) {
204 return false;
205 }
206 }
207 return true;
208 }
209
210 ALWAYS_INLINE WARN_UNUSED bool BranchInstrumentation(int32_t offset)
211 REQUIRES_SHARED(Locks::mutator_lock_) {
212 if (UNLIKELY(instrumentation->HasBranchListeners())) {
213 instrumentation->Branch(self, shadow_frame.GetMethod(), dex_pc, offset);
214 }
215 JValue result;
216 if (jit::Jit::MaybeDoOnStackReplacement(self,
217 shadow_frame.GetMethod(),
218 dex_pc,
219 offset,
220 &result)) {
221 if (ctx->interpret_one_instruction) {
222 /* OSR has completed execution of the method. Signal mterp to return to caller */
223 shadow_frame.SetDexPC(dex::kDexNoIndex);
224 }
225 ctx->result = result;
226 exit_interpreter_loop = true;
227 return false;
228 }
229 return true;
230 }
231
232 ALWAYS_INLINE void HotnessUpdate()
233 REQUIRES_SHARED(Locks::mutator_lock_) {
234 jit::Jit* jit = Runtime::Current()->GetJit();
235 if (jit != nullptr) {
236 jit->AddSamples(self, shadow_frame.GetMethod(), 1, /*with_backedges=*/ true);
237 }
238 }
239
240 ALWAYS_INLINE WARN_UNUSED bool HandleAsyncException()
241 REQUIRES_SHARED(Locks::mutator_lock_) {
242 if (UNLIKELY(self->ObserveAsyncException())) {
243 if (!HandlePendingException()) {
244 return false;
245 }
246 }
247 return true;
248 }
249
250 ALWAYS_INLINE void HandleBackwardBranch(int32_t offset)
251 REQUIRES_SHARED(Locks::mutator_lock_) {
252 if (IsBackwardBranch(offset)) {
253 HotnessUpdate();
254 /* Record new dex pc early to have consistent suspend point at loop header. */
255 shadow_frame.SetDexPC(inst->GetDexPc(Insns()));
256 self->AllowThreadSuspension();
257 }
258 }
259
260 // Unlike most other events the DexPcMovedEvent can be sent when there is a pending exception (if
261 // the next instruction is MOVE_EXCEPTION). This means it needs to be handled carefully to be able
262 // to detect exceptions thrown by the DexPcMovedEvent itself. These exceptions could be thrown by
263 // jvmti-agents while handling breakpoint or single step events. We had to move this into its own
264 // function because it was making ExecuteSwitchImpl have too large a stack.
265 NO_INLINE static bool DoDexPcMoveEvent(Thread* self,
266 const CodeItemDataAccessor& accessor,
267 const ShadowFrame& shadow_frame,
268 uint32_t dex_pc,
269 const instrumentation::Instrumentation* instrumentation,
270 JValue* save_ref)
271 REQUIRES_SHARED(Locks::mutator_lock_) {
272 DCHECK(instrumentation->HasDexPcListeners());
273 StackHandleScope<2> hs(self);
274 Handle<mirror::Throwable> thr(hs.NewHandle(self->GetException()));
275 mirror::Object* null_obj = nullptr;
276 HandleWrapper<mirror::Object> h(
277 hs.NewHandleWrapper(LIKELY(save_ref == nullptr) ? &null_obj : save_ref->GetGCRoot()));
278 self->ClearException();
279 instrumentation->DexPcMovedEvent(self,
280 shadow_frame.GetThisObject(accessor.InsSize()),
281 shadow_frame.GetMethod(),
282 dex_pc);
283 if (UNLIKELY(self->IsExceptionPending())) {
284 // We got a new exception in the dex-pc-moved event.
285 // We just let this exception replace the old one.
286 // TODO It would be good to add the old exception to the
287 // suppressed exceptions of the new one if possible.
288 return false;
289 } else {
290 if (UNLIKELY(!thr.IsNull())) {
291 self->SetException(thr.Get());
292 }
293 return true;
294 }
295 }
296
297 static bool NeedsMethodExitEvent(const instrumentation::Instrumentation* ins)
298 REQUIRES_SHARED(Locks::mutator_lock_) {
299 return ins->HasMethodExitListeners() || ins->HasWatchedFramePopListeners();
300 }
301
302 // Sends the normal method exit event.
303 // Returns true if the events succeeded and false if there is a pending exception.
304 NO_INLINE static bool SendMethodExitEvents(
305 Thread* self,
306 const instrumentation::Instrumentation* instrumentation,
307 const ShadowFrame& frame,
308 ObjPtr<mirror::Object> thiz,
309 ArtMethod* method,
310 uint32_t dex_pc,
311 const JValue& result)
312 REQUIRES_SHARED(Locks::mutator_lock_) {
313 bool had_event = false;
314 // We don't send method-exit if it's a pop-frame. We still send frame_popped though.
315 if (UNLIKELY(instrumentation->HasMethodExitListeners() && !frame.GetForcePopFrame())) {
316 had_event = true;
Vladimir Marko19711d42019-04-12 14:05:34 +0100317 instrumentation->MethodExitEvent(self, thiz, method, dex_pc, result);
David Srbecky47ad3762018-10-31 12:43:40 +0000318 }
319 if (UNLIKELY(frame.NeedsNotifyPop() && instrumentation->HasWatchedFramePopListeners())) {
320 had_event = true;
321 instrumentation->WatchedFramePopped(self, frame);
322 }
323 if (UNLIKELY(had_event)) {
324 return !self->IsExceptionPending();
325 } else {
326 return true;
327 }
328 }
329
330#define BRANCH_INSTRUMENTATION(offset) \
331 if (!BranchInstrumentation(offset)) { \
332 return; \
333 }
334
335#define HANDLE_PENDING_EXCEPTION() \
336 if (!HandlePendingException()) { \
337 return; \
338 }
339
340#define POSSIBLY_HANDLE_PENDING_EXCEPTION(is_exception_pending, next_function) \
341 if (!PossiblyHandlePendingException(is_exception_pending, inst->next_function())) { \
342 return; \
343 }
344
345#define POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(is_exception_pending) \
346 if (!PossiblyHandlePendingExceptionOnInvokeImpl(is_exception_pending, inst->Next_4xx())) { \
347 return; \
348 }
349
350#define POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(is_exception_pending) \
351 if (!PossiblyHandlePendingExceptionOnInvokeImpl(is_exception_pending, inst->Next_3xx())) { \
352 return; \
353 }
354
David Srbecky6da82472018-10-23 14:03:08 +0100355 ALWAYS_INLINE void NOP() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100356 inst = inst->Next_1xx();
357 }
358
359 ALWAYS_INLINE void MOVE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100360 shadow_frame.SetVReg(A(),
361 shadow_frame.GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100362 inst = inst->Next_1xx();
363 }
364
365 ALWAYS_INLINE void MOVE_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100366 shadow_frame.SetVReg(A(),
367 shadow_frame.GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100368 inst = inst->Next_2xx();
369 }
370
371 ALWAYS_INLINE void MOVE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100372 shadow_frame.SetVReg(A(),
373 shadow_frame.GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100374 inst = inst->Next_3xx();
375 }
376
377 ALWAYS_INLINE void MOVE_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100378 shadow_frame.SetVRegLong(A(),
379 shadow_frame.GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100380 inst = inst->Next_1xx();
381 }
382
383 ALWAYS_INLINE void MOVE_WIDE_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100384 shadow_frame.SetVRegLong(A(),
385 shadow_frame.GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100386 inst = inst->Next_2xx();
387 }
388
389 ALWAYS_INLINE void MOVE_WIDE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100390 shadow_frame.SetVRegLong(A(),
391 shadow_frame.GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100392 inst = inst->Next_3xx();
393 }
394
395 ALWAYS_INLINE void MOVE_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100396 shadow_frame.SetVRegReference(A(),
397 shadow_frame.GetVRegReference(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100398 inst = inst->Next_1xx();
399 }
400
401 ALWAYS_INLINE void MOVE_OBJECT_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100402 shadow_frame.SetVRegReference(A(),
403 shadow_frame.GetVRegReference(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100404 inst = inst->Next_2xx();
405 }
406
407 ALWAYS_INLINE void MOVE_OBJECT_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100408 shadow_frame.SetVRegReference(A(),
409 shadow_frame.GetVRegReference(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100410 inst = inst->Next_3xx();
411 }
412
413 ALWAYS_INLINE void MOVE_RESULT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100414 shadow_frame.SetVReg(A(), ResultRegister()->GetI());
David Srbecky6da82472018-10-23 14:03:08 +0100415 inst = inst->Next_1xx();
416 }
417
418 ALWAYS_INLINE void MOVE_RESULT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100419 shadow_frame.SetVRegLong(A(), ResultRegister()->GetJ());
David Srbecky6da82472018-10-23 14:03:08 +0100420 inst = inst->Next_1xx();
421 }
422
423 ALWAYS_INLINE void MOVE_RESULT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100424 shadow_frame.SetVRegReference(A(), ResultRegister()->GetL());
David Srbecky6da82472018-10-23 14:03:08 +0100425 inst = inst->Next_1xx();
426 }
427
428 ALWAYS_INLINE void MOVE_EXCEPTION() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100429 ObjPtr<mirror::Throwable> exception = self->GetException();
430 DCHECK(exception != nullptr) << "No pending exception on MOVE_EXCEPTION instruction";
David Srbecky436f6c12019-05-22 13:28:42 +0100431 shadow_frame.SetVRegReference(A(), exception);
David Srbecky6da82472018-10-23 14:03:08 +0100432 self->ClearException();
433 inst = inst->Next_1xx();
434 }
435
436 ALWAYS_INLINE void RETURN_VOID_NO_BARRIER() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100437 JValue result;
438 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000439 if (!HandleMonitorChecks()) {
440 return;
441 }
David Srbecky6da82472018-10-23 14:03:08 +0100442 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
443 !SendMethodExitEvents(self,
444 instrumentation,
445 shadow_frame,
446 shadow_frame.GetThisObject(Accessor().InsSize()),
447 shadow_frame.GetMethod(),
448 inst->GetDexPc(Insns()),
449 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000450 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
451 return;
452 }
David Srbecky6da82472018-10-23 14:03:08 +0100453 }
454 if (ctx->interpret_one_instruction) {
455 /* Signal mterp to return to caller */
456 shadow_frame.SetDexPC(dex::kDexNoIndex);
457 }
458 ctx->result = result;
459 exit_interpreter_loop = true;
460 }
461
462 ALWAYS_INLINE void RETURN_VOID() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100463 QuasiAtomic::ThreadFenceForConstructor();
464 JValue result;
465 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000466 if (!HandleMonitorChecks()) {
467 return;
468 }
David Srbecky6da82472018-10-23 14:03:08 +0100469 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
470 !SendMethodExitEvents(self,
471 instrumentation,
472 shadow_frame,
473 shadow_frame.GetThisObject(Accessor().InsSize()),
474 shadow_frame.GetMethod(),
475 inst->GetDexPc(Insns()),
476 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000477 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
478 return;
479 }
David Srbecky6da82472018-10-23 14:03:08 +0100480 }
481 if (ctx->interpret_one_instruction) {
482 /* Signal mterp to return to caller */
483 shadow_frame.SetDexPC(dex::kDexNoIndex);
484 }
485 ctx->result = result;
486 exit_interpreter_loop = true;
487 }
488
489 ALWAYS_INLINE void RETURN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100490 JValue result;
491 result.SetJ(0);
David Srbecky436f6c12019-05-22 13:28:42 +0100492 result.SetI(shadow_frame.GetVReg(A()));
David Srbecky6da82472018-10-23 14:03:08 +0100493 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000494 if (!HandleMonitorChecks()) {
495 return;
496 }
David Srbecky6da82472018-10-23 14:03:08 +0100497 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
498 !SendMethodExitEvents(self,
499 instrumentation,
500 shadow_frame,
501 shadow_frame.GetThisObject(Accessor().InsSize()),
502 shadow_frame.GetMethod(),
503 inst->GetDexPc(Insns()),
504 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000505 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
506 return;
507 }
David Srbecky6da82472018-10-23 14:03:08 +0100508 }
509 if (ctx->interpret_one_instruction) {
510 /* Signal mterp to return to caller */
511 shadow_frame.SetDexPC(dex::kDexNoIndex);
512 }
513 ctx->result = result;
514 exit_interpreter_loop = true;
515 }
516
517 ALWAYS_INLINE void RETURN_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100518 JValue result;
David Srbecky436f6c12019-05-22 13:28:42 +0100519 result.SetJ(shadow_frame.GetVRegLong(A()));
David Srbecky6da82472018-10-23 14:03:08 +0100520 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000521 if (!HandleMonitorChecks()) {
522 return;
523 }
David Srbecky6da82472018-10-23 14:03:08 +0100524 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
525 !SendMethodExitEvents(self,
526 instrumentation,
527 shadow_frame,
528 shadow_frame.GetThisObject(Accessor().InsSize()),
529 shadow_frame.GetMethod(),
530 inst->GetDexPc(Insns()),
531 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000532 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
533 return;
534 }
David Srbecky6da82472018-10-23 14:03:08 +0100535 }
536 if (ctx->interpret_one_instruction) {
537 /* Signal mterp to return to caller */
538 shadow_frame.SetDexPC(dex::kDexNoIndex);
539 }
540 ctx->result = result;
541 exit_interpreter_loop = true;
542 }
543
544 ALWAYS_INLINE void RETURN_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100545 JValue result;
546 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000547 if (!HandleMonitorChecks()) {
548 return;
549 }
David Srbecky6da82472018-10-23 14:03:08 +0100550 const size_t ref_idx = inst->VRegA_11x(inst_data);
551 ObjPtr<mirror::Object> obj_result = shadow_frame.GetVRegReference(ref_idx);
552 if (do_assignability_check && obj_result != nullptr) {
553 ObjPtr<mirror::Class> return_type = shadow_frame.GetMethod()->ResolveReturnType();
554 // Re-load since it might have moved.
555 obj_result = shadow_frame.GetVRegReference(ref_idx);
556 if (return_type == nullptr) {
557 // Return the pending exception.
558 HANDLE_PENDING_EXCEPTION();
559 }
560 if (!obj_result->VerifierInstanceOf(return_type)) {
561 // This should never happen.
562 std::string temp1, temp2;
563 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
564 "Returning '%s' that is not instance of return type '%s'",
565 obj_result->GetClass()->GetDescriptor(&temp1),
566 return_type->GetDescriptor(&temp2));
567 HANDLE_PENDING_EXCEPTION();
568 }
569 }
570 result.SetL(obj_result);
571 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
572 !SendMethodExitEvents(self,
573 instrumentation,
574 shadow_frame,
575 shadow_frame.GetThisObject(Accessor().InsSize()),
576 shadow_frame.GetMethod(),
577 inst->GetDexPc(Insns()),
578 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000579 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
580 return;
581 }
David Srbecky6da82472018-10-23 14:03:08 +0100582 }
583 // Re-load since it might have moved during the MethodExitEvent.
584 result.SetL(shadow_frame.GetVRegReference(ref_idx));
585 if (ctx->interpret_one_instruction) {
586 /* Signal mterp to return to caller */
587 shadow_frame.SetDexPC(dex::kDexNoIndex);
588 }
589 ctx->result = result;
590 exit_interpreter_loop = true;
591 }
592
593 ALWAYS_INLINE void CONST_4() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100594 uint4_t dst = inst->VRegA_11n(inst_data);
595 int4_t val = inst->VRegB_11n(inst_data);
596 shadow_frame.SetVReg(dst, val);
597 if (val == 0) {
598 shadow_frame.SetVRegReference(dst, nullptr);
599 }
600 inst = inst->Next_1xx();
601 }
602
603 ALWAYS_INLINE void CONST_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100604 uint8_t dst = inst->VRegA_21s(inst_data);
605 int16_t val = inst->VRegB_21s();
606 shadow_frame.SetVReg(dst, val);
607 if (val == 0) {
608 shadow_frame.SetVRegReference(dst, nullptr);
609 }
610 inst = inst->Next_2xx();
611 }
612
613 ALWAYS_INLINE void CONST() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100614 uint8_t dst = inst->VRegA_31i(inst_data);
615 int32_t val = inst->VRegB_31i();
616 shadow_frame.SetVReg(dst, val);
617 if (val == 0) {
618 shadow_frame.SetVRegReference(dst, nullptr);
619 }
620 inst = inst->Next_3xx();
621 }
622
623 ALWAYS_INLINE void CONST_HIGH16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100624 uint8_t dst = inst->VRegA_21h(inst_data);
625 int32_t val = static_cast<int32_t>(inst->VRegB_21h() << 16);
626 shadow_frame.SetVReg(dst, val);
627 if (val == 0) {
628 shadow_frame.SetVRegReference(dst, nullptr);
629 }
630 inst = inst->Next_2xx();
631 }
632
633 ALWAYS_INLINE void CONST_WIDE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100634 shadow_frame.SetVRegLong(A(), inst->VRegB_21s());
David Srbecky6da82472018-10-23 14:03:08 +0100635 inst = inst->Next_2xx();
636 }
637
638 ALWAYS_INLINE void CONST_WIDE_32() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100639 shadow_frame.SetVRegLong(A(), inst->VRegB_31i());
David Srbecky6da82472018-10-23 14:03:08 +0100640 inst = inst->Next_3xx();
641 }
642
643 ALWAYS_INLINE void CONST_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100644 shadow_frame.SetVRegLong(A(), inst->VRegB_51l());
David Srbecky6da82472018-10-23 14:03:08 +0100645 inst = inst->Next_51l();
646 }
647
648 ALWAYS_INLINE void CONST_WIDE_HIGH16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100649 shadow_frame.SetVRegLong(A(),
David Srbecky6da82472018-10-23 14:03:08 +0100650 static_cast<uint64_t>(inst->VRegB_21h()) << 48);
651 inst = inst->Next_2xx();
652 }
653
654 ALWAYS_INLINE void CONST_STRING() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100655 ObjPtr<mirror::String> s = ResolveString(self,
656 shadow_frame,
657 dex::StringIndex(inst->VRegB_21c()));
658 if (UNLIKELY(s == nullptr)) {
659 HANDLE_PENDING_EXCEPTION();
660 } else {
David Srbecky436f6c12019-05-22 13:28:42 +0100661 shadow_frame.SetVRegReference(A(), s);
David Srbecky6da82472018-10-23 14:03:08 +0100662 inst = inst->Next_2xx();
663 }
664 }
665
666 ALWAYS_INLINE void CONST_STRING_JUMBO() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100667 ObjPtr<mirror::String> s = ResolveString(self,
668 shadow_frame,
669 dex::StringIndex(inst->VRegB_31c()));
670 if (UNLIKELY(s == nullptr)) {
671 HANDLE_PENDING_EXCEPTION();
672 } else {
David Srbecky436f6c12019-05-22 13:28:42 +0100673 shadow_frame.SetVRegReference(A(), s);
David Srbecky6da82472018-10-23 14:03:08 +0100674 inst = inst->Next_3xx();
675 }
676 }
677
678 ALWAYS_INLINE void CONST_CLASS() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100679 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(inst->VRegB_21c()),
680 shadow_frame.GetMethod(),
681 self,
682 false,
683 do_access_check);
684 if (UNLIKELY(c == nullptr)) {
685 HANDLE_PENDING_EXCEPTION();
686 } else {
David Srbecky436f6c12019-05-22 13:28:42 +0100687 shadow_frame.SetVRegReference(A(), c);
David Srbecky6da82472018-10-23 14:03:08 +0100688 inst = inst->Next_2xx();
689 }
690 }
691
692 ALWAYS_INLINE void CONST_METHOD_HANDLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100693 ClassLinker* cl = Runtime::Current()->GetClassLinker();
694 ObjPtr<mirror::MethodHandle> mh = cl->ResolveMethodHandle(self,
695 inst->VRegB_21c(),
696 shadow_frame.GetMethod());
697 if (UNLIKELY(mh == nullptr)) {
698 HANDLE_PENDING_EXCEPTION();
699 } else {
David Srbecky436f6c12019-05-22 13:28:42 +0100700 shadow_frame.SetVRegReference(A(), mh);
David Srbecky6da82472018-10-23 14:03:08 +0100701 inst = inst->Next_2xx();
702 }
703 }
704
705 ALWAYS_INLINE void CONST_METHOD_TYPE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100706 ClassLinker* cl = Runtime::Current()->GetClassLinker();
707 ObjPtr<mirror::MethodType> mt = cl->ResolveMethodType(self,
708 dex::ProtoIndex(inst->VRegB_21c()),
709 shadow_frame.GetMethod());
710 if (UNLIKELY(mt == nullptr)) {
711 HANDLE_PENDING_EXCEPTION();
712 } else {
David Srbecky436f6c12019-05-22 13:28:42 +0100713 shadow_frame.SetVRegReference(A(), mt);
David Srbecky6da82472018-10-23 14:03:08 +0100714 inst = inst->Next_2xx();
715 }
716 }
717
718 ALWAYS_INLINE void MONITOR_ENTER() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000719 if (!HandleAsyncException()) {
720 return;
721 }
David Srbecky436f6c12019-05-22 13:28:42 +0100722 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +0100723 if (UNLIKELY(obj == nullptr)) {
724 ThrowNullPointerExceptionFromInterpreter();
725 HANDLE_PENDING_EXCEPTION();
726 } else {
727 DoMonitorEnter<do_assignability_check>(self, &shadow_frame, obj);
728 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
729 }
730 }
731
732 ALWAYS_INLINE void MONITOR_EXIT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000733 if (!HandleAsyncException()) {
734 return;
735 }
David Srbecky436f6c12019-05-22 13:28:42 +0100736 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +0100737 if (UNLIKELY(obj == nullptr)) {
738 ThrowNullPointerExceptionFromInterpreter();
739 HANDLE_PENDING_EXCEPTION();
740 } else {
741 DoMonitorExit<do_assignability_check>(self, &shadow_frame, obj);
742 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
743 }
744 }
745
746 ALWAYS_INLINE void CHECK_CAST() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100747 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(inst->VRegB_21c()),
748 shadow_frame.GetMethod(),
749 self,
750 false,
751 do_access_check);
752 if (UNLIKELY(c == nullptr)) {
753 HANDLE_PENDING_EXCEPTION();
754 } else {
David Srbecky436f6c12019-05-22 13:28:42 +0100755 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +0100756 if (UNLIKELY(obj != nullptr && !obj->InstanceOf(c))) {
757 ThrowClassCastException(c, obj->GetClass());
758 HANDLE_PENDING_EXCEPTION();
759 } else {
760 inst = inst->Next_2xx();
761 }
762 }
763 }
764
765 ALWAYS_INLINE void INSTANCE_OF() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100766 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(inst->VRegC_22c()),
767 shadow_frame.GetMethod(),
768 self,
769 false,
770 do_access_check);
771 if (UNLIKELY(c == nullptr)) {
772 HANDLE_PENDING_EXCEPTION();
773 } else {
David Srbecky436f6c12019-05-22 13:28:42 +0100774 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(B());
775 shadow_frame.SetVReg(A(),
David Srbecky6da82472018-10-23 14:03:08 +0100776 (obj != nullptr && obj->InstanceOf(c)) ? 1 : 0);
777 inst = inst->Next_2xx();
778 }
779 }
780
781 ALWAYS_INLINE void ARRAY_LENGTH() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100782 ObjPtr<mirror::Object> array = shadow_frame.GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +0100783 if (UNLIKELY(array == nullptr)) {
784 ThrowNullPointerExceptionFromInterpreter();
785 HANDLE_PENDING_EXCEPTION();
786 } else {
David Srbecky436f6c12019-05-22 13:28:42 +0100787 shadow_frame.SetVReg(A(), array->AsArray()->GetLength());
David Srbecky6da82472018-10-23 14:03:08 +0100788 inst = inst->Next_1xx();
789 }
790 }
791
792 ALWAYS_INLINE void NEW_INSTANCE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100793 ObjPtr<mirror::Object> obj = nullptr;
794 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(inst->VRegB_21c()),
795 shadow_frame.GetMethod(),
796 self,
797 false,
798 do_access_check);
799 if (LIKELY(c != nullptr)) {
Vladimir Marko9b81ac32019-05-16 16:47:08 +0100800 gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
David Srbecky6da82472018-10-23 14:03:08 +0100801 if (UNLIKELY(c->IsStringClass())) {
Vladimir Marko9b81ac32019-05-16 16:47:08 +0100802 obj = mirror::String::AllocEmptyString(self, allocator_type);
David Srbecky6da82472018-10-23 14:03:08 +0100803 } else {
Vladimir Marko9b81ac32019-05-16 16:47:08 +0100804 obj = AllocObjectFromCode(c, self, allocator_type);
David Srbecky6da82472018-10-23 14:03:08 +0100805 }
806 }
807 if (UNLIKELY(obj == nullptr)) {
808 HANDLE_PENDING_EXCEPTION();
809 } else {
810 obj->GetClass()->AssertInitializedOrInitializingInThread(self);
811 // Don't allow finalizable objects to be allocated during a transaction since these can't
812 // be finalized without a started runtime.
813 if (transaction_active && obj->GetClass()->IsFinalizable()) {
814 AbortTransactionF(self, "Allocating finalizable object in transaction: %s",
815 obj->PrettyTypeOf().c_str());
816 HANDLE_PENDING_EXCEPTION();
817 }
David Srbecky436f6c12019-05-22 13:28:42 +0100818 shadow_frame.SetVRegReference(A(), obj);
David Srbecky6da82472018-10-23 14:03:08 +0100819 inst = inst->Next_2xx();
820 }
821 }
822
823 ALWAYS_INLINE void NEW_ARRAY() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100824 int32_t length = shadow_frame.GetVReg(B());
Vladimir Marko9b81ac32019-05-16 16:47:08 +0100825 ObjPtr<mirror::Object> obj = AllocArrayFromCode<do_access_check>(
David Srbecky6da82472018-10-23 14:03:08 +0100826 dex::TypeIndex(inst->VRegC_22c()),
827 length,
828 shadow_frame.GetMethod(),
829 self,
830 Runtime::Current()->GetHeap()->GetCurrentAllocator());
831 if (UNLIKELY(obj == nullptr)) {
832 HANDLE_PENDING_EXCEPTION();
833 } else {
David Srbecky436f6c12019-05-22 13:28:42 +0100834 shadow_frame.SetVRegReference(A(), obj);
David Srbecky6da82472018-10-23 14:03:08 +0100835 inst = inst->Next_2xx();
836 }
837 }
838
839 ALWAYS_INLINE void FILLED_NEW_ARRAY() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100840 bool success =
841 DoFilledNewArray<false, do_access_check, transaction_active>(inst, shadow_frame, self,
842 ResultRegister());
843 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
844 }
845
846 ALWAYS_INLINE void FILLED_NEW_ARRAY_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100847 bool success =
848 DoFilledNewArray<true, do_access_check, transaction_active>(inst, shadow_frame,
849 self, ResultRegister());
850 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
851 }
852
853 ALWAYS_INLINE void FILL_ARRAY_DATA() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100854 const uint16_t* payload_addr = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
855 const Instruction::ArrayDataPayload* payload =
856 reinterpret_cast<const Instruction::ArrayDataPayload*>(payload_addr);
David Srbecky436f6c12019-05-22 13:28:42 +0100857 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +0100858 bool success = FillArrayData(obj, payload);
859 if (!success) {
860 HANDLE_PENDING_EXCEPTION();
861 }
862 if (transaction_active) {
863 RecordArrayElementsInTransaction(obj->AsArray(), payload->element_count);
864 }
865 inst = inst->Next_3xx();
866 }
867
868 ALWAYS_INLINE void THROW() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000869 if (!HandleAsyncException()) {
870 return;
871 }
David Srbecky6da82472018-10-23 14:03:08 +0100872 ObjPtr<mirror::Object> exception =
David Srbecky436f6c12019-05-22 13:28:42 +0100873 shadow_frame.GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +0100874 if (UNLIKELY(exception == nullptr)) {
875 ThrowNullPointerException("throw with null exception");
876 } else if (do_assignability_check && !exception->GetClass()->IsThrowableClass()) {
877 // This should never happen.
878 std::string temp;
879 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
880 "Throwing '%s' that is not instance of Throwable",
881 exception->GetClass()->GetDescriptor(&temp));
882 } else {
883 self->SetException(exception->AsThrowable());
884 }
885 HANDLE_PENDING_EXCEPTION();
886 }
887
888 ALWAYS_INLINE void GOTO() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000889 if (!HandleAsyncException()) {
890 return;
891 }
David Srbecky6da82472018-10-23 14:03:08 +0100892 int8_t offset = inst->VRegA_10t(inst_data);
893 BRANCH_INSTRUMENTATION(offset);
894 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +0000895 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +0100896 }
897
898 ALWAYS_INLINE void GOTO_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000899 if (!HandleAsyncException()) {
900 return;
901 }
David Srbecky6da82472018-10-23 14:03:08 +0100902 int16_t offset = inst->VRegA_20t();
903 BRANCH_INSTRUMENTATION(offset);
904 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +0000905 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +0100906 }
907
908 ALWAYS_INLINE void GOTO_32() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000909 if (!HandleAsyncException()) {
910 return;
911 }
David Srbecky6da82472018-10-23 14:03:08 +0100912 int32_t offset = inst->VRegA_30t();
913 BRANCH_INSTRUMENTATION(offset);
914 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +0000915 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +0100916 }
917
918 ALWAYS_INLINE void PACKED_SWITCH() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100919 int32_t offset = DoPackedSwitch(inst, shadow_frame, inst_data);
920 BRANCH_INSTRUMENTATION(offset);
921 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +0000922 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +0100923 }
924
925 ALWAYS_INLINE void SPARSE_SWITCH() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100926 int32_t offset = DoSparseSwitch(inst, shadow_frame, inst_data);
927 BRANCH_INSTRUMENTATION(offset);
928 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +0000929 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +0100930 }
931
932#pragma clang diagnostic push
933#pragma clang diagnostic ignored "-Wfloat-equal"
934
935
936 ALWAYS_INLINE void CMPL_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100937 float val1 = shadow_frame.GetVRegFloat(B());
938 float val2 = shadow_frame.GetVRegFloat(C());
David Srbecky6da82472018-10-23 14:03:08 +0100939 int32_t result;
940 if (val1 > val2) {
941 result = 1;
942 } else if (val1 == val2) {
943 result = 0;
944 } else {
945 result = -1;
946 }
David Srbecky436f6c12019-05-22 13:28:42 +0100947 shadow_frame.SetVReg(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +0100948 inst = inst->Next_2xx();
949 }
950
951 ALWAYS_INLINE void CMPG_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100952 float val1 = shadow_frame.GetVRegFloat(B());
953 float val2 = shadow_frame.GetVRegFloat(C());
David Srbecky6da82472018-10-23 14:03:08 +0100954 int32_t result;
955 if (val1 < val2) {
956 result = -1;
957 } else if (val1 == val2) {
958 result = 0;
959 } else {
960 result = 1;
961 }
David Srbecky436f6c12019-05-22 13:28:42 +0100962 shadow_frame.SetVReg(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +0100963 inst = inst->Next_2xx();
964 }
965
966 ALWAYS_INLINE void CMPL_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100967 double val1 = shadow_frame.GetVRegDouble(B());
968 double val2 = shadow_frame.GetVRegDouble(C());
David Srbecky6da82472018-10-23 14:03:08 +0100969 int32_t result;
970 if (val1 > val2) {
971 result = 1;
972 } else if (val1 == val2) {
973 result = 0;
974 } else {
975 result = -1;
976 }
David Srbecky436f6c12019-05-22 13:28:42 +0100977 shadow_frame.SetVReg(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +0100978 inst = inst->Next_2xx();
979 }
980
981
982 ALWAYS_INLINE void CMPG_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100983 double val1 = shadow_frame.GetVRegDouble(B());
984 double val2 = shadow_frame.GetVRegDouble(C());
David Srbecky6da82472018-10-23 14:03:08 +0100985 int32_t result;
986 if (val1 < val2) {
987 result = -1;
988 } else if (val1 == val2) {
989 result = 0;
990 } else {
991 result = 1;
992 }
David Srbecky436f6c12019-05-22 13:28:42 +0100993 shadow_frame.SetVReg(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +0100994 inst = inst->Next_2xx();
995 }
996
997#pragma clang diagnostic pop
998
999
1000 ALWAYS_INLINE void CMP_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001001 int64_t val1 = shadow_frame.GetVRegLong(B());
1002 int64_t val2 = shadow_frame.GetVRegLong(C());
David Srbecky6da82472018-10-23 14:03:08 +01001003 int32_t result;
1004 if (val1 > val2) {
1005 result = 1;
1006 } else if (val1 == val2) {
1007 result = 0;
1008 } else {
1009 result = -1;
1010 }
David Srbecky436f6c12019-05-22 13:28:42 +01001011 shadow_frame.SetVReg(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +01001012 inst = inst->Next_2xx();
1013 }
1014
1015 ALWAYS_INLINE void IF_EQ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001016 if (shadow_frame.GetVReg(A()) ==
1017 shadow_frame.GetVReg(B())) {
David Srbecky6da82472018-10-23 14:03:08 +01001018 int16_t offset = inst->VRegC_22t();
1019 BRANCH_INSTRUMENTATION(offset);
1020 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001021 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001022 } else {
1023 BRANCH_INSTRUMENTATION(2);
1024 inst = inst->Next_2xx();
1025 }
1026 }
1027
1028 ALWAYS_INLINE void IF_NE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001029 if (shadow_frame.GetVReg(A()) !=
1030 shadow_frame.GetVReg(B())) {
David Srbecky6da82472018-10-23 14:03:08 +01001031 int16_t offset = inst->VRegC_22t();
1032 BRANCH_INSTRUMENTATION(offset);
1033 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001034 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001035 } else {
1036 BRANCH_INSTRUMENTATION(2);
1037 inst = inst->Next_2xx();
1038 }
1039 }
1040
1041 ALWAYS_INLINE void IF_LT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001042 if (shadow_frame.GetVReg(A()) <
1043 shadow_frame.GetVReg(B())) {
David Srbecky6da82472018-10-23 14:03:08 +01001044 int16_t offset = inst->VRegC_22t();
1045 BRANCH_INSTRUMENTATION(offset);
1046 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001047 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001048 } else {
1049 BRANCH_INSTRUMENTATION(2);
1050 inst = inst->Next_2xx();
1051 }
1052 }
1053
1054 ALWAYS_INLINE void IF_GE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001055 if (shadow_frame.GetVReg(A()) >=
1056 shadow_frame.GetVReg(B())) {
David Srbecky6da82472018-10-23 14:03:08 +01001057 int16_t offset = inst->VRegC_22t();
1058 BRANCH_INSTRUMENTATION(offset);
1059 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001060 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001061 } else {
1062 BRANCH_INSTRUMENTATION(2);
1063 inst = inst->Next_2xx();
1064 }
1065 }
1066
1067 ALWAYS_INLINE void IF_GT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001068 if (shadow_frame.GetVReg(A()) >
1069 shadow_frame.GetVReg(B())) {
David Srbecky6da82472018-10-23 14:03:08 +01001070 int16_t offset = inst->VRegC_22t();
1071 BRANCH_INSTRUMENTATION(offset);
1072 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001073 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001074 } else {
1075 BRANCH_INSTRUMENTATION(2);
1076 inst = inst->Next_2xx();
1077 }
1078 }
1079
1080 ALWAYS_INLINE void IF_LE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001081 if (shadow_frame.GetVReg(A()) <=
1082 shadow_frame.GetVReg(B())) {
David Srbecky6da82472018-10-23 14:03:08 +01001083 int16_t offset = inst->VRegC_22t();
1084 BRANCH_INSTRUMENTATION(offset);
1085 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001086 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001087 } else {
1088 BRANCH_INSTRUMENTATION(2);
1089 inst = inst->Next_2xx();
1090 }
1091 }
1092
1093 ALWAYS_INLINE void IF_EQZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001094 if (shadow_frame.GetVReg(A()) == 0) {
David Srbecky6da82472018-10-23 14:03:08 +01001095 int16_t offset = inst->VRegB_21t();
1096 BRANCH_INSTRUMENTATION(offset);
1097 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001098 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001099 } else {
1100 BRANCH_INSTRUMENTATION(2);
1101 inst = inst->Next_2xx();
1102 }
1103 }
1104
1105 ALWAYS_INLINE void IF_NEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001106 if (shadow_frame.GetVReg(A()) != 0) {
David Srbecky6da82472018-10-23 14:03:08 +01001107 int16_t offset = inst->VRegB_21t();
1108 BRANCH_INSTRUMENTATION(offset);
1109 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001110 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001111 } else {
1112 BRANCH_INSTRUMENTATION(2);
1113 inst = inst->Next_2xx();
1114 }
1115 }
1116
1117 ALWAYS_INLINE void IF_LTZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001118 if (shadow_frame.GetVReg(A()) < 0) {
David Srbecky6da82472018-10-23 14:03:08 +01001119 int16_t offset = inst->VRegB_21t();
1120 BRANCH_INSTRUMENTATION(offset);
1121 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001122 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001123 } else {
1124 BRANCH_INSTRUMENTATION(2);
1125 inst = inst->Next_2xx();
1126 }
1127 }
1128
1129 ALWAYS_INLINE void IF_GEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001130 if (shadow_frame.GetVReg(A()) >= 0) {
David Srbecky6da82472018-10-23 14:03:08 +01001131 int16_t offset = inst->VRegB_21t();
1132 BRANCH_INSTRUMENTATION(offset);
1133 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001134 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001135 } else {
1136 BRANCH_INSTRUMENTATION(2);
1137 inst = inst->Next_2xx();
1138 }
1139 }
1140
1141 ALWAYS_INLINE void IF_GTZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001142 if (shadow_frame.GetVReg(A()) > 0) {
David Srbecky6da82472018-10-23 14:03:08 +01001143 int16_t offset = inst->VRegB_21t();
1144 BRANCH_INSTRUMENTATION(offset);
1145 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001146 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001147 } else {
1148 BRANCH_INSTRUMENTATION(2);
1149 inst = inst->Next_2xx();
1150 }
1151 }
1152
1153 ALWAYS_INLINE void IF_LEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001154 if (shadow_frame.GetVReg(A()) <= 0) {
David Srbecky6da82472018-10-23 14:03:08 +01001155 int16_t offset = inst->VRegB_21t();
1156 BRANCH_INSTRUMENTATION(offset);
1157 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001158 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001159 } else {
1160 BRANCH_INSTRUMENTATION(2);
1161 inst = inst->Next_2xx();
1162 }
1163 }
1164
1165 ALWAYS_INLINE void AGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001166 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001167 if (UNLIKELY(a == nullptr)) {
1168 ThrowNullPointerExceptionFromInterpreter();
1169 HANDLE_PENDING_EXCEPTION();
1170 }
David Srbecky436f6c12019-05-22 13:28:42 +01001171 int32_t index = shadow_frame.GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001172 ObjPtr<mirror::BooleanArray> array = a->AsBooleanArray();
1173 if (array->CheckIsValidIndex(index)) {
David Srbecky436f6c12019-05-22 13:28:42 +01001174 shadow_frame.SetVReg(A(), array->GetWithoutChecks(index));
David Srbecky6da82472018-10-23 14:03:08 +01001175 inst = inst->Next_2xx();
1176 } else {
1177 HANDLE_PENDING_EXCEPTION();
1178 }
1179 }
1180
1181 ALWAYS_INLINE void AGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001182 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001183 if (UNLIKELY(a == nullptr)) {
1184 ThrowNullPointerExceptionFromInterpreter();
1185 HANDLE_PENDING_EXCEPTION();
1186 }
David Srbecky436f6c12019-05-22 13:28:42 +01001187 int32_t index = shadow_frame.GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001188 ObjPtr<mirror::ByteArray> array = a->AsByteArray();
1189 if (array->CheckIsValidIndex(index)) {
David Srbecky436f6c12019-05-22 13:28:42 +01001190 shadow_frame.SetVReg(A(), array->GetWithoutChecks(index));
David Srbecky6da82472018-10-23 14:03:08 +01001191 inst = inst->Next_2xx();
1192 } else {
1193 HANDLE_PENDING_EXCEPTION();
1194 }
1195 }
1196
1197 ALWAYS_INLINE void AGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001198 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001199 if (UNLIKELY(a == nullptr)) {
1200 ThrowNullPointerExceptionFromInterpreter();
1201 HANDLE_PENDING_EXCEPTION();
1202 }
David Srbecky436f6c12019-05-22 13:28:42 +01001203 int32_t index = shadow_frame.GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001204 ObjPtr<mirror::CharArray> array = a->AsCharArray();
1205 if (array->CheckIsValidIndex(index)) {
David Srbecky436f6c12019-05-22 13:28:42 +01001206 shadow_frame.SetVReg(A(), array->GetWithoutChecks(index));
David Srbecky6da82472018-10-23 14:03:08 +01001207 inst = inst->Next_2xx();
1208 } else {
1209 HANDLE_PENDING_EXCEPTION();
1210 }
1211 }
1212
1213 ALWAYS_INLINE void AGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001214 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001215 if (UNLIKELY(a == nullptr)) {
1216 ThrowNullPointerExceptionFromInterpreter();
1217 HANDLE_PENDING_EXCEPTION();
1218 }
David Srbecky436f6c12019-05-22 13:28:42 +01001219 int32_t index = shadow_frame.GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001220 ObjPtr<mirror::ShortArray> array = a->AsShortArray();
1221 if (array->CheckIsValidIndex(index)) {
David Srbecky436f6c12019-05-22 13:28:42 +01001222 shadow_frame.SetVReg(A(), array->GetWithoutChecks(index));
David Srbecky6da82472018-10-23 14:03:08 +01001223 inst = inst->Next_2xx();
1224 } else {
1225 HANDLE_PENDING_EXCEPTION();
1226 }
1227 }
1228
1229 ALWAYS_INLINE void AGET() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001230 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001231 if (UNLIKELY(a == nullptr)) {
1232 ThrowNullPointerExceptionFromInterpreter();
1233 HANDLE_PENDING_EXCEPTION();
1234 }
David Srbecky436f6c12019-05-22 13:28:42 +01001235 int32_t index = shadow_frame.GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001236 DCHECK(a->IsIntArray() || a->IsFloatArray()) << a->PrettyTypeOf();
1237 ObjPtr<mirror::IntArray> array = ObjPtr<mirror::IntArray>::DownCast(a);
1238 if (array->CheckIsValidIndex(index)) {
David Srbecky436f6c12019-05-22 13:28:42 +01001239 shadow_frame.SetVReg(A(), array->GetWithoutChecks(index));
David Srbecky6da82472018-10-23 14:03:08 +01001240 inst = inst->Next_2xx();
1241 } else {
1242 HANDLE_PENDING_EXCEPTION();
1243 }
1244 }
1245
1246 ALWAYS_INLINE void AGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001247 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001248 if (UNLIKELY(a == nullptr)) {
1249 ThrowNullPointerExceptionFromInterpreter();
1250 HANDLE_PENDING_EXCEPTION();
1251 }
David Srbecky436f6c12019-05-22 13:28:42 +01001252 int32_t index = shadow_frame.GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001253 DCHECK(a->IsLongArray() || a->IsDoubleArray()) << a->PrettyTypeOf();
1254 ObjPtr<mirror::LongArray> array = ObjPtr<mirror::LongArray>::DownCast(a);
1255 if (array->CheckIsValidIndex(index)) {
David Srbecky436f6c12019-05-22 13:28:42 +01001256 shadow_frame.SetVRegLong(A(), array->GetWithoutChecks(index));
David Srbecky6da82472018-10-23 14:03:08 +01001257 inst = inst->Next_2xx();
1258 } else {
1259 HANDLE_PENDING_EXCEPTION();
1260 }
1261 }
1262
1263 ALWAYS_INLINE void AGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001264 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001265 if (UNLIKELY(a == nullptr)) {
1266 ThrowNullPointerExceptionFromInterpreter();
1267 HANDLE_PENDING_EXCEPTION();
1268 }
David Srbecky436f6c12019-05-22 13:28:42 +01001269 int32_t index = shadow_frame.GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001270 ObjPtr<mirror::ObjectArray<mirror::Object>> array = a->AsObjectArray<mirror::Object>();
1271 if (array->CheckIsValidIndex(index)) {
David Srbecky436f6c12019-05-22 13:28:42 +01001272 shadow_frame.SetVRegReference(A(), array->GetWithoutChecks(index));
David Srbecky6da82472018-10-23 14:03:08 +01001273 inst = inst->Next_2xx();
1274 } else {
1275 HANDLE_PENDING_EXCEPTION();
1276 }
1277 }
1278
1279 ALWAYS_INLINE void APUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001280 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001281 if (UNLIKELY(a == nullptr)) {
1282 ThrowNullPointerExceptionFromInterpreter();
1283 HANDLE_PENDING_EXCEPTION();
1284 }
David Srbecky436f6c12019-05-22 13:28:42 +01001285 uint8_t val = shadow_frame.GetVReg(A());
1286 int32_t index = shadow_frame.GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001287 ObjPtr<mirror::BooleanArray> array = a->AsBooleanArray();
1288 if (array->CheckIsValidIndex(index)) {
1289 array->SetWithoutChecks<transaction_active>(index, val);
1290 inst = inst->Next_2xx();
1291 } else {
1292 HANDLE_PENDING_EXCEPTION();
1293 }
1294 }
1295
1296 ALWAYS_INLINE void APUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001297 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001298 if (UNLIKELY(a == nullptr)) {
1299 ThrowNullPointerExceptionFromInterpreter();
1300 HANDLE_PENDING_EXCEPTION();
1301 }
David Srbecky436f6c12019-05-22 13:28:42 +01001302 int8_t val = shadow_frame.GetVReg(A());
1303 int32_t index = shadow_frame.GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001304 ObjPtr<mirror::ByteArray> array = a->AsByteArray();
1305 if (array->CheckIsValidIndex(index)) {
1306 array->SetWithoutChecks<transaction_active>(index, val);
1307 inst = inst->Next_2xx();
1308 } else {
1309 HANDLE_PENDING_EXCEPTION();
1310 }
1311 }
1312
1313 ALWAYS_INLINE void APUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001314 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001315 if (UNLIKELY(a == nullptr)) {
1316 ThrowNullPointerExceptionFromInterpreter();
1317 HANDLE_PENDING_EXCEPTION();
1318 }
David Srbecky436f6c12019-05-22 13:28:42 +01001319 uint16_t val = shadow_frame.GetVReg(A());
1320 int32_t index = shadow_frame.GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001321 ObjPtr<mirror::CharArray> array = a->AsCharArray();
1322 if (array->CheckIsValidIndex(index)) {
1323 array->SetWithoutChecks<transaction_active>(index, val);
1324 inst = inst->Next_2xx();
1325 } else {
1326 HANDLE_PENDING_EXCEPTION();
1327 }
1328 }
1329
1330 ALWAYS_INLINE void APUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001331 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001332 if (UNLIKELY(a == nullptr)) {
1333 ThrowNullPointerExceptionFromInterpreter();
1334 HANDLE_PENDING_EXCEPTION();
1335 }
David Srbecky436f6c12019-05-22 13:28:42 +01001336 int16_t val = shadow_frame.GetVReg(A());
1337 int32_t index = shadow_frame.GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001338 ObjPtr<mirror::ShortArray> array = a->AsShortArray();
1339 if (array->CheckIsValidIndex(index)) {
1340 array->SetWithoutChecks<transaction_active>(index, val);
1341 inst = inst->Next_2xx();
1342 } else {
1343 HANDLE_PENDING_EXCEPTION();
1344 }
1345 }
1346
1347 ALWAYS_INLINE void APUT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001348 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001349 if (UNLIKELY(a == nullptr)) {
1350 ThrowNullPointerExceptionFromInterpreter();
1351 HANDLE_PENDING_EXCEPTION();
1352 }
David Srbecky436f6c12019-05-22 13:28:42 +01001353 int32_t val = shadow_frame.GetVReg(A());
1354 int32_t index = shadow_frame.GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001355 DCHECK(a->IsIntArray() || a->IsFloatArray()) << a->PrettyTypeOf();
1356 ObjPtr<mirror::IntArray> array = ObjPtr<mirror::IntArray>::DownCast(a);
1357 if (array->CheckIsValidIndex(index)) {
1358 array->SetWithoutChecks<transaction_active>(index, val);
1359 inst = inst->Next_2xx();
1360 } else {
1361 HANDLE_PENDING_EXCEPTION();
1362 }
1363 }
1364
1365 ALWAYS_INLINE void APUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001366 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001367 if (UNLIKELY(a == nullptr)) {
1368 ThrowNullPointerExceptionFromInterpreter();
1369 HANDLE_PENDING_EXCEPTION();
1370 }
David Srbecky436f6c12019-05-22 13:28:42 +01001371 int64_t val = shadow_frame.GetVRegLong(A());
1372 int32_t index = shadow_frame.GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001373 DCHECK(a->IsLongArray() || a->IsDoubleArray()) << a->PrettyTypeOf();
1374 ObjPtr<mirror::LongArray> array = ObjPtr<mirror::LongArray>::DownCast(a);
1375 if (array->CheckIsValidIndex(index)) {
1376 array->SetWithoutChecks<transaction_active>(index, val);
1377 inst = inst->Next_2xx();
1378 } else {
1379 HANDLE_PENDING_EXCEPTION();
1380 }
1381 }
1382
1383 ALWAYS_INLINE void APUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001384 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001385 if (UNLIKELY(a == nullptr)) {
1386 ThrowNullPointerExceptionFromInterpreter();
1387 HANDLE_PENDING_EXCEPTION();
1388 }
David Srbecky436f6c12019-05-22 13:28:42 +01001389 int32_t index = shadow_frame.GetVReg(C());
1390 ObjPtr<mirror::Object> val = shadow_frame.GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +01001391 ObjPtr<mirror::ObjectArray<mirror::Object>> array = a->AsObjectArray<mirror::Object>();
1392 if (array->CheckIsValidIndex(index) && array->CheckAssignable(val)) {
1393 array->SetWithoutChecks<transaction_active>(index, val);
1394 inst = inst->Next_2xx();
1395 } else {
1396 HANDLE_PENDING_EXCEPTION();
1397 }
1398 }
1399
1400 ALWAYS_INLINE void IGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001401 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimBoolean, do_access_check>(
1402 self, shadow_frame, inst, inst_data);
1403 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1404 }
1405
1406 ALWAYS_INLINE void IGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001407 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimByte, do_access_check>(
1408 self, shadow_frame, inst, inst_data);
1409 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1410 }
1411
1412 ALWAYS_INLINE void IGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001413 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimChar, do_access_check>(
1414 self, shadow_frame, inst, inst_data);
1415 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1416 }
1417
1418 ALWAYS_INLINE void IGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001419 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimShort, do_access_check>(
1420 self, shadow_frame, inst, inst_data);
1421 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1422 }
1423
1424 ALWAYS_INLINE void IGET() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001425 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimInt, do_access_check>(
1426 self, shadow_frame, inst, inst_data);
1427 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1428 }
1429
1430 ALWAYS_INLINE void IGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001431 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimLong, do_access_check>(
1432 self, shadow_frame, inst, inst_data);
1433 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1434 }
1435
1436 ALWAYS_INLINE void IGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001437 bool success = DoFieldGet<InstanceObjectRead, Primitive::kPrimNot, do_access_check>(
1438 self, shadow_frame, inst, inst_data);
1439 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1440 }
1441
1442 ALWAYS_INLINE void IGET_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001443 bool success = DoIGetQuick<Primitive::kPrimInt>(shadow_frame, inst, inst_data);
1444 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1445 }
1446
1447 ALWAYS_INLINE void IGET_WIDE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001448 bool success = DoIGetQuick<Primitive::kPrimLong>(shadow_frame, inst, inst_data);
1449 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1450 }
1451
1452 ALWAYS_INLINE void IGET_OBJECT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001453 bool success = DoIGetQuick<Primitive::kPrimNot>(shadow_frame, inst, inst_data);
1454 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1455 }
1456
1457 ALWAYS_INLINE void IGET_BOOLEAN_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001458 bool success = DoIGetQuick<Primitive::kPrimBoolean>(shadow_frame, inst, inst_data);
1459 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1460 }
1461
1462 ALWAYS_INLINE void IGET_BYTE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001463 bool success = DoIGetQuick<Primitive::kPrimByte>(shadow_frame, inst, inst_data);
1464 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1465 }
1466
1467 ALWAYS_INLINE void IGET_CHAR_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001468 bool success = DoIGetQuick<Primitive::kPrimChar>(shadow_frame, inst, inst_data);
1469 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1470 }
1471
1472 ALWAYS_INLINE void IGET_SHORT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001473 bool success = DoIGetQuick<Primitive::kPrimShort>(shadow_frame, inst, inst_data);
1474 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1475 }
1476
1477 ALWAYS_INLINE void SGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001478 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimBoolean, do_access_check,
1479 transaction_active>(self, shadow_frame, inst, inst_data);
1480 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1481 }
1482
1483 ALWAYS_INLINE void SGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001484 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimByte, do_access_check,
1485 transaction_active>(self, shadow_frame, inst, inst_data);
1486 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1487 }
1488
1489 ALWAYS_INLINE void SGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001490 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimChar, do_access_check,
1491 transaction_active>(self, shadow_frame, inst, inst_data);
1492 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1493 }
1494
1495 ALWAYS_INLINE void SGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001496 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimShort, do_access_check,
1497 transaction_active>(self, shadow_frame, inst, inst_data);
1498 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1499 }
1500
1501 ALWAYS_INLINE void SGET() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001502 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimInt, do_access_check,
1503 transaction_active>(self, shadow_frame, inst, inst_data);
1504 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1505 }
1506
1507 ALWAYS_INLINE void SGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001508 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimLong, do_access_check,
1509 transaction_active>(self, shadow_frame, inst, inst_data);
1510 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1511 }
1512
1513 ALWAYS_INLINE void SGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001514 bool success = DoFieldGet<StaticObjectRead, Primitive::kPrimNot, do_access_check,
1515 transaction_active>(self, shadow_frame, inst, inst_data);
1516 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1517 }
1518
1519 ALWAYS_INLINE void IPUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001520 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimBoolean, do_access_check,
1521 transaction_active>(self, shadow_frame, inst, inst_data);
1522 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1523 }
1524
1525 ALWAYS_INLINE void IPUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001526 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimByte, do_access_check,
1527 transaction_active>(self, shadow_frame, inst, inst_data);
1528 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1529 }
1530
1531 ALWAYS_INLINE void IPUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001532 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimChar, do_access_check,
1533 transaction_active>(self, shadow_frame, inst, inst_data);
1534 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1535 }
1536
1537 ALWAYS_INLINE void IPUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001538 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimShort, do_access_check,
1539 transaction_active>(self, shadow_frame, inst, inst_data);
1540 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1541 }
1542
1543 ALWAYS_INLINE void IPUT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001544 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimInt, do_access_check,
1545 transaction_active>(self, shadow_frame, inst, inst_data);
1546 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1547 }
1548
1549 ALWAYS_INLINE void IPUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001550 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimLong, do_access_check,
1551 transaction_active>(self, shadow_frame, inst, inst_data);
1552 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1553 }
1554
1555 ALWAYS_INLINE void IPUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001556 bool success = DoFieldPut<InstanceObjectWrite, Primitive::kPrimNot, do_access_check,
1557 transaction_active>(self, shadow_frame, inst, inst_data);
1558 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1559 }
1560
1561 ALWAYS_INLINE void IPUT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001562 bool success = DoIPutQuick<Primitive::kPrimInt, transaction_active>(
1563 shadow_frame, inst, inst_data);
1564 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1565 }
1566
1567 ALWAYS_INLINE void IPUT_BOOLEAN_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001568 bool success = DoIPutQuick<Primitive::kPrimBoolean, transaction_active>(
1569 shadow_frame, inst, inst_data);
1570 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1571 }
1572
1573 ALWAYS_INLINE void IPUT_BYTE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001574 bool success = DoIPutQuick<Primitive::kPrimByte, transaction_active>(
1575 shadow_frame, inst, inst_data);
1576 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1577 }
1578
1579 ALWAYS_INLINE void IPUT_CHAR_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001580 bool success = DoIPutQuick<Primitive::kPrimChar, transaction_active>(
1581 shadow_frame, inst, inst_data);
1582 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1583 }
1584
1585 ALWAYS_INLINE void IPUT_SHORT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001586 bool success = DoIPutQuick<Primitive::kPrimShort, transaction_active>(
1587 shadow_frame, inst, inst_data);
1588 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1589 }
1590
1591 ALWAYS_INLINE void IPUT_WIDE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001592 bool success = DoIPutQuick<Primitive::kPrimLong, transaction_active>(
1593 shadow_frame, inst, inst_data);
1594 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1595 }
1596
1597 ALWAYS_INLINE void IPUT_OBJECT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001598 bool success = DoIPutQuick<Primitive::kPrimNot, transaction_active>(
1599 shadow_frame, inst, inst_data);
1600 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1601 }
1602
1603 ALWAYS_INLINE void SPUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001604 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimBoolean, do_access_check,
1605 transaction_active>(self, shadow_frame, inst, inst_data);
1606 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1607 }
1608
1609 ALWAYS_INLINE void SPUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001610 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimByte, do_access_check,
1611 transaction_active>(self, shadow_frame, inst, inst_data);
1612 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1613 }
1614
1615 ALWAYS_INLINE void SPUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001616 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimChar, do_access_check,
1617 transaction_active>(self, shadow_frame, inst, inst_data);
1618 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1619 }
1620
1621 ALWAYS_INLINE void SPUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001622 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimShort, do_access_check,
1623 transaction_active>(self, shadow_frame, inst, inst_data);
1624 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1625 }
1626
1627 ALWAYS_INLINE void SPUT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001628 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimInt, do_access_check,
1629 transaction_active>(self, shadow_frame, inst, inst_data);
1630 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1631 }
1632
1633 ALWAYS_INLINE void SPUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001634 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimLong, do_access_check,
1635 transaction_active>(self, shadow_frame, inst, inst_data);
1636 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1637 }
1638
1639 ALWAYS_INLINE void SPUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001640 bool success = DoFieldPut<StaticObjectWrite, Primitive::kPrimNot, do_access_check,
1641 transaction_active>(self, shadow_frame, inst, inst_data);
1642 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1643 }
1644
1645 ALWAYS_INLINE void INVOKE_VIRTUAL() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001646 bool success = DoInvoke<kVirtual, false, do_access_check, /*is_mterp=*/ false>(
1647 self, shadow_frame, inst, inst_data, ResultRegister());
1648 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1649 }
1650
1651 ALWAYS_INLINE void INVOKE_VIRTUAL_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001652 bool success = DoInvoke<kVirtual, true, do_access_check, /*is_mterp=*/ false>(
1653 self, shadow_frame, inst, inst_data, ResultRegister());
1654 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1655 }
1656
1657 ALWAYS_INLINE void INVOKE_SUPER() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001658 bool success = DoInvoke<kSuper, false, do_access_check, /*is_mterp=*/ false>(
1659 self, shadow_frame, inst, inst_data, ResultRegister());
1660 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1661 }
1662
1663 ALWAYS_INLINE void INVOKE_SUPER_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001664 bool success = DoInvoke<kSuper, true, do_access_check, /*is_mterp=*/ false>(
1665 self, shadow_frame, inst, inst_data, ResultRegister());
1666 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1667 }
1668
1669 ALWAYS_INLINE void INVOKE_DIRECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001670 bool success = DoInvoke<kDirect, false, do_access_check, /*is_mterp=*/ false>(
1671 self, shadow_frame, inst, inst_data, ResultRegister());
1672 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1673 }
1674
1675 ALWAYS_INLINE void INVOKE_DIRECT_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001676 bool success = DoInvoke<kDirect, true, do_access_check, /*is_mterp=*/ false>(
1677 self, shadow_frame, inst, inst_data, ResultRegister());
1678 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1679 }
1680
1681 ALWAYS_INLINE void INVOKE_INTERFACE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001682 bool success = DoInvoke<kInterface, false, do_access_check, /*is_mterp=*/ false>(
1683 self, shadow_frame, inst, inst_data, ResultRegister());
1684 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1685 }
1686
1687 ALWAYS_INLINE void INVOKE_INTERFACE_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001688 bool success = DoInvoke<kInterface, true, do_access_check, /*is_mterp=*/ false>(
1689 self, shadow_frame, inst, inst_data, ResultRegister());
1690 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1691 }
1692
1693 ALWAYS_INLINE void INVOKE_STATIC() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001694 bool success = DoInvoke<kStatic, false, do_access_check, /*is_mterp=*/ false>(
1695 self, shadow_frame, inst, inst_data, ResultRegister());
1696 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1697 }
1698
1699 ALWAYS_INLINE void INVOKE_STATIC_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001700 bool success = DoInvoke<kStatic, true, do_access_check, /*is_mterp=*/ false>(
1701 self, shadow_frame, inst, inst_data, ResultRegister());
1702 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1703 }
1704
1705 ALWAYS_INLINE void INVOKE_VIRTUAL_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001706 bool success = DoInvoke<kVirtual, false, do_access_check, /*is_mterp=*/ false,
1707 /*is_quick=*/ true>(self, shadow_frame, inst, inst_data, ResultRegister());
1708 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1709 }
1710
1711 ALWAYS_INLINE void INVOKE_VIRTUAL_RANGE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001712 bool success = DoInvoke<kVirtual, true, do_access_check, /*is_mterp=*/ false,
1713 /*is_quick=*/ true>(self, shadow_frame, inst, inst_data, ResultRegister());
1714 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1715 }
1716
1717 ALWAYS_INLINE void INVOKE_POLYMORPHIC() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001718 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1719 bool success = DoInvokePolymorphic</* is_range= */ false>(
1720 self, shadow_frame, inst, inst_data, ResultRegister());
1721 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(!success);
1722 }
1723
1724 ALWAYS_INLINE void INVOKE_POLYMORPHIC_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001725 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1726 bool success = DoInvokePolymorphic</* is_range= */ true>(
1727 self, shadow_frame, inst, inst_data, ResultRegister());
1728 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(!success);
1729 }
1730
1731 ALWAYS_INLINE void INVOKE_CUSTOM() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001732 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1733 bool success = DoInvokeCustom</* is_range= */ false>(
1734 self, shadow_frame, inst, inst_data, ResultRegister());
1735 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1736 }
1737
1738 ALWAYS_INLINE void INVOKE_CUSTOM_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001739 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1740 bool success = DoInvokeCustom</* is_range= */ true>(
1741 self, shadow_frame, inst, inst_data, ResultRegister());
1742 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1743 }
1744
1745 ALWAYS_INLINE void NEG_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001746 shadow_frame.SetVReg(
David Srbecky436f6c12019-05-22 13:28:42 +01001747 inst->VRegA_12x(inst_data), -shadow_frame.GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001748 inst = inst->Next_1xx();
1749 }
1750
1751 ALWAYS_INLINE void NOT_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001752 shadow_frame.SetVReg(
David Srbecky436f6c12019-05-22 13:28:42 +01001753 inst->VRegA_12x(inst_data), ~shadow_frame.GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001754 inst = inst->Next_1xx();
1755 }
1756
1757 ALWAYS_INLINE void NEG_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001758 shadow_frame.SetVRegLong(
David Srbecky436f6c12019-05-22 13:28:42 +01001759 inst->VRegA_12x(inst_data), -shadow_frame.GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001760 inst = inst->Next_1xx();
1761 }
1762
1763 ALWAYS_INLINE void NOT_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001764 shadow_frame.SetVRegLong(
David Srbecky436f6c12019-05-22 13:28:42 +01001765 inst->VRegA_12x(inst_data), ~shadow_frame.GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001766 inst = inst->Next_1xx();
1767 }
1768
1769 ALWAYS_INLINE void NEG_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001770 shadow_frame.SetVRegFloat(
David Srbecky436f6c12019-05-22 13:28:42 +01001771 inst->VRegA_12x(inst_data), -shadow_frame.GetVRegFloat(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001772 inst = inst->Next_1xx();
1773 }
1774
1775 ALWAYS_INLINE void NEG_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001776 shadow_frame.SetVRegDouble(
David Srbecky436f6c12019-05-22 13:28:42 +01001777 inst->VRegA_12x(inst_data), -shadow_frame.GetVRegDouble(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001778 inst = inst->Next_1xx();
1779 }
1780
1781 ALWAYS_INLINE void INT_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001782 shadow_frame.SetVRegLong(A(),
1783 shadow_frame.GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001784 inst = inst->Next_1xx();
1785 }
1786
1787 ALWAYS_INLINE void INT_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001788 shadow_frame.SetVRegFloat(A(),
1789 shadow_frame.GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001790 inst = inst->Next_1xx();
1791 }
1792
1793 ALWAYS_INLINE void INT_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001794 shadow_frame.SetVRegDouble(A(),
1795 shadow_frame.GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001796 inst = inst->Next_1xx();
1797 }
1798
1799 ALWAYS_INLINE void LONG_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001800 shadow_frame.SetVReg(A(),
1801 shadow_frame.GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001802 inst = inst->Next_1xx();
1803 }
1804
1805 ALWAYS_INLINE void LONG_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001806 shadow_frame.SetVRegFloat(A(),
1807 shadow_frame.GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001808 inst = inst->Next_1xx();
1809 }
1810
1811 ALWAYS_INLINE void LONG_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001812 shadow_frame.SetVRegDouble(A(),
1813 shadow_frame.GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001814 inst = inst->Next_1xx();
1815 }
1816
1817 ALWAYS_INLINE void FLOAT_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001818 float val = shadow_frame.GetVRegFloat(B());
David Srbecky6da82472018-10-23 14:03:08 +01001819 int32_t result = art_float_to_integral<int32_t, float>(val);
David Srbecky436f6c12019-05-22 13:28:42 +01001820 shadow_frame.SetVReg(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +01001821 inst = inst->Next_1xx();
1822 }
1823
1824 ALWAYS_INLINE void FLOAT_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001825 float val = shadow_frame.GetVRegFloat(B());
David Srbecky6da82472018-10-23 14:03:08 +01001826 int64_t result = art_float_to_integral<int64_t, float>(val);
David Srbecky436f6c12019-05-22 13:28:42 +01001827 shadow_frame.SetVRegLong(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +01001828 inst = inst->Next_1xx();
1829 }
1830
1831 ALWAYS_INLINE void FLOAT_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001832 shadow_frame.SetVRegDouble(A(),
1833 shadow_frame.GetVRegFloat(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001834 inst = inst->Next_1xx();
1835 }
1836
1837 ALWAYS_INLINE void DOUBLE_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001838 double val = shadow_frame.GetVRegDouble(B());
David Srbecky6da82472018-10-23 14:03:08 +01001839 int32_t result = art_float_to_integral<int32_t, double>(val);
David Srbecky436f6c12019-05-22 13:28:42 +01001840 shadow_frame.SetVReg(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +01001841 inst = inst->Next_1xx();
1842 }
1843
1844 ALWAYS_INLINE void DOUBLE_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001845 double val = shadow_frame.GetVRegDouble(B());
David Srbecky6da82472018-10-23 14:03:08 +01001846 int64_t result = art_float_to_integral<int64_t, double>(val);
David Srbecky436f6c12019-05-22 13:28:42 +01001847 shadow_frame.SetVRegLong(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +01001848 inst = inst->Next_1xx();
1849 }
1850
1851 ALWAYS_INLINE void DOUBLE_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001852 shadow_frame.SetVRegFloat(A(),
1853 shadow_frame.GetVRegDouble(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001854 inst = inst->Next_1xx();
1855 }
1856
1857 ALWAYS_INLINE void INT_TO_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001858 shadow_frame.SetVReg(A(), static_cast<int8_t>(
1859 shadow_frame.GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01001860 inst = inst->Next_1xx();
1861 }
1862
1863 ALWAYS_INLINE void INT_TO_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001864 shadow_frame.SetVReg(A(), static_cast<uint16_t>(
1865 shadow_frame.GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01001866 inst = inst->Next_1xx();
1867 }
1868
1869 ALWAYS_INLINE void INT_TO_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001870 shadow_frame.SetVReg(A(), static_cast<int16_t>(
1871 shadow_frame.GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01001872 inst = inst->Next_1xx();
1873 }
1874
1875 ALWAYS_INLINE void ADD_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001876 shadow_frame.SetVReg(A(),
1877 SafeAdd(shadow_frame.GetVReg(B()),
1878 shadow_frame.GetVReg(C())));
David Srbecky6da82472018-10-23 14:03:08 +01001879 inst = inst->Next_2xx();
1880 }
1881
1882 ALWAYS_INLINE void SUB_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001883 shadow_frame.SetVReg(A(),
1884 SafeSub(shadow_frame.GetVReg(B()),
1885 shadow_frame.GetVReg(C())));
David Srbecky6da82472018-10-23 14:03:08 +01001886 inst = inst->Next_2xx();
1887 }
1888
1889 ALWAYS_INLINE void MUL_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001890 shadow_frame.SetVReg(A(),
1891 SafeMul(shadow_frame.GetVReg(B()),
1892 shadow_frame.GetVReg(C())));
David Srbecky6da82472018-10-23 14:03:08 +01001893 inst = inst->Next_2xx();
1894 }
1895
1896 ALWAYS_INLINE void DIV_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001897 bool success = DoIntDivide(shadow_frame, inst->VRegA_23x(inst_data),
David Srbecky436f6c12019-05-22 13:28:42 +01001898 shadow_frame.GetVReg(B()),
1899 shadow_frame.GetVReg(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001900 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1901 }
1902
1903 ALWAYS_INLINE void REM_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001904 bool success = DoIntRemainder(shadow_frame, inst->VRegA_23x(inst_data),
David Srbecky436f6c12019-05-22 13:28:42 +01001905 shadow_frame.GetVReg(B()),
1906 shadow_frame.GetVReg(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001907 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1908 }
1909
1910 ALWAYS_INLINE void SHL_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001911 shadow_frame.SetVReg(A(),
1912 shadow_frame.GetVReg(B()) <<
1913 (shadow_frame.GetVReg(C()) & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01001914 inst = inst->Next_2xx();
1915 }
1916
1917 ALWAYS_INLINE void SHR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001918 shadow_frame.SetVReg(A(),
1919 shadow_frame.GetVReg(B()) >>
1920 (shadow_frame.GetVReg(C()) & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01001921 inst = inst->Next_2xx();
1922 }
1923
1924 ALWAYS_INLINE void USHR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001925 shadow_frame.SetVReg(A(),
1926 static_cast<uint32_t>(shadow_frame.GetVReg(B())) >>
1927 (shadow_frame.GetVReg(C()) & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01001928 inst = inst->Next_2xx();
1929 }
1930
1931 ALWAYS_INLINE void AND_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001932 shadow_frame.SetVReg(A(),
1933 shadow_frame.GetVReg(B()) &
1934 shadow_frame.GetVReg(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001935 inst = inst->Next_2xx();
1936 }
1937
1938 ALWAYS_INLINE void OR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001939 shadow_frame.SetVReg(A(),
1940 shadow_frame.GetVReg(B()) |
1941 shadow_frame.GetVReg(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001942 inst = inst->Next_2xx();
1943 }
1944
1945 ALWAYS_INLINE void XOR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001946 shadow_frame.SetVReg(A(),
1947 shadow_frame.GetVReg(B()) ^
1948 shadow_frame.GetVReg(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001949 inst = inst->Next_2xx();
1950 }
1951
1952 ALWAYS_INLINE void ADD_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001953 shadow_frame.SetVRegLong(A(),
1954 SafeAdd(shadow_frame.GetVRegLong(B()),
1955 shadow_frame.GetVRegLong(C())));
David Srbecky6da82472018-10-23 14:03:08 +01001956 inst = inst->Next_2xx();
1957 }
1958
1959 ALWAYS_INLINE void SUB_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001960 shadow_frame.SetVRegLong(A(),
1961 SafeSub(shadow_frame.GetVRegLong(B()),
1962 shadow_frame.GetVRegLong(C())));
David Srbecky6da82472018-10-23 14:03:08 +01001963 inst = inst->Next_2xx();
1964 }
1965
1966 ALWAYS_INLINE void MUL_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001967 shadow_frame.SetVRegLong(A(),
1968 SafeMul(shadow_frame.GetVRegLong(B()),
1969 shadow_frame.GetVRegLong(C())));
David Srbecky6da82472018-10-23 14:03:08 +01001970 inst = inst->Next_2xx();
1971 }
1972
1973 ALWAYS_INLINE void DIV_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001974 DoLongDivide(shadow_frame, inst->VRegA_23x(inst_data),
David Srbecky436f6c12019-05-22 13:28:42 +01001975 shadow_frame.GetVRegLong(B()),
1976 shadow_frame.GetVRegLong(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001977 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_2xx);
1978 }
1979
1980 ALWAYS_INLINE void REM_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001981 DoLongRemainder(shadow_frame, inst->VRegA_23x(inst_data),
David Srbecky436f6c12019-05-22 13:28:42 +01001982 shadow_frame.GetVRegLong(B()),
1983 shadow_frame.GetVRegLong(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001984 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_2xx);
1985 }
1986
1987 ALWAYS_INLINE void AND_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001988 shadow_frame.SetVRegLong(A(),
1989 shadow_frame.GetVRegLong(B()) &
1990 shadow_frame.GetVRegLong(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001991 inst = inst->Next_2xx();
1992 }
1993
1994 ALWAYS_INLINE void OR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001995 shadow_frame.SetVRegLong(A(),
1996 shadow_frame.GetVRegLong(B()) |
1997 shadow_frame.GetVRegLong(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001998 inst = inst->Next_2xx();
1999 }
2000
2001 ALWAYS_INLINE void XOR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002002 shadow_frame.SetVRegLong(A(),
2003 shadow_frame.GetVRegLong(B()) ^
2004 shadow_frame.GetVRegLong(C()));
David Srbecky6da82472018-10-23 14:03:08 +01002005 inst = inst->Next_2xx();
2006 }
2007
2008 ALWAYS_INLINE void SHL_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002009 shadow_frame.SetVRegLong(A(),
2010 shadow_frame.GetVRegLong(B()) <<
2011 (shadow_frame.GetVReg(C()) & 0x3f));
David Srbecky6da82472018-10-23 14:03:08 +01002012 inst = inst->Next_2xx();
2013 }
2014
2015 ALWAYS_INLINE void SHR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002016 shadow_frame.SetVRegLong(A(),
2017 shadow_frame.GetVRegLong(B()) >>
2018 (shadow_frame.GetVReg(C()) & 0x3f));
David Srbecky6da82472018-10-23 14:03:08 +01002019 inst = inst->Next_2xx();
2020 }
2021
2022 ALWAYS_INLINE void USHR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002023 shadow_frame.SetVRegLong(A(),
2024 static_cast<uint64_t>(shadow_frame.GetVRegLong(B())) >>
2025 (shadow_frame.GetVReg(C()) & 0x3f));
David Srbecky6da82472018-10-23 14:03:08 +01002026 inst = inst->Next_2xx();
2027 }
2028
2029 ALWAYS_INLINE void ADD_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002030 shadow_frame.SetVRegFloat(A(),
2031 shadow_frame.GetVRegFloat(B()) +
2032 shadow_frame.GetVRegFloat(C()));
David Srbecky6da82472018-10-23 14:03:08 +01002033 inst = inst->Next_2xx();
2034 }
2035
2036 ALWAYS_INLINE void SUB_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002037 shadow_frame.SetVRegFloat(A(),
2038 shadow_frame.GetVRegFloat(B()) -
2039 shadow_frame.GetVRegFloat(C()));
David Srbecky6da82472018-10-23 14:03:08 +01002040 inst = inst->Next_2xx();
2041 }
2042
2043 ALWAYS_INLINE void MUL_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002044 shadow_frame.SetVRegFloat(A(),
2045 shadow_frame.GetVRegFloat(B()) *
2046 shadow_frame.GetVRegFloat(C()));
David Srbecky6da82472018-10-23 14:03:08 +01002047 inst = inst->Next_2xx();
2048 }
2049
2050 ALWAYS_INLINE void DIV_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002051 shadow_frame.SetVRegFloat(A(),
2052 shadow_frame.GetVRegFloat(B()) /
2053 shadow_frame.GetVRegFloat(C()));
David Srbecky6da82472018-10-23 14:03:08 +01002054 inst = inst->Next_2xx();
2055 }
2056
2057 ALWAYS_INLINE void REM_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002058 shadow_frame.SetVRegFloat(A(),
2059 fmodf(shadow_frame.GetVRegFloat(B()),
2060 shadow_frame.GetVRegFloat(C())));
David Srbecky6da82472018-10-23 14:03:08 +01002061 inst = inst->Next_2xx();
2062 }
2063
2064 ALWAYS_INLINE void ADD_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002065 shadow_frame.SetVRegDouble(A(),
2066 shadow_frame.GetVRegDouble(B()) +
2067 shadow_frame.GetVRegDouble(C()));
David Srbecky6da82472018-10-23 14:03:08 +01002068 inst = inst->Next_2xx();
2069 }
2070
2071 ALWAYS_INLINE void SUB_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002072 shadow_frame.SetVRegDouble(A(),
2073 shadow_frame.GetVRegDouble(B()) -
2074 shadow_frame.GetVRegDouble(C()));
David Srbecky6da82472018-10-23 14:03:08 +01002075 inst = inst->Next_2xx();
2076 }
2077
2078 ALWAYS_INLINE void MUL_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002079 shadow_frame.SetVRegDouble(A(),
2080 shadow_frame.GetVRegDouble(B()) *
2081 shadow_frame.GetVRegDouble(C()));
David Srbecky6da82472018-10-23 14:03:08 +01002082 inst = inst->Next_2xx();
2083 }
2084
2085 ALWAYS_INLINE void DIV_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002086 shadow_frame.SetVRegDouble(A(),
2087 shadow_frame.GetVRegDouble(B()) /
2088 shadow_frame.GetVRegDouble(C()));
David Srbecky6da82472018-10-23 14:03:08 +01002089 inst = inst->Next_2xx();
2090 }
2091
2092 ALWAYS_INLINE void REM_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002093 shadow_frame.SetVRegDouble(A(),
2094 fmod(shadow_frame.GetVRegDouble(B()),
2095 shadow_frame.GetVRegDouble(C())));
David Srbecky6da82472018-10-23 14:03:08 +01002096 inst = inst->Next_2xx();
2097 }
2098
2099 ALWAYS_INLINE void ADD_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002100 uint4_t vregA = inst->VRegA_12x(inst_data);
2101 shadow_frame.SetVReg(vregA, SafeAdd(shadow_frame.GetVReg(vregA),
David Srbecky436f6c12019-05-22 13:28:42 +01002102 shadow_frame.GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002103 inst = inst->Next_1xx();
2104 }
2105
2106 ALWAYS_INLINE void SUB_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002107 uint4_t vregA = inst->VRegA_12x(inst_data);
2108 shadow_frame.SetVReg(vregA,
2109 SafeSub(shadow_frame.GetVReg(vregA),
David Srbecky436f6c12019-05-22 13:28:42 +01002110 shadow_frame.GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002111 inst = inst->Next_1xx();
2112 }
2113
2114 ALWAYS_INLINE void MUL_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002115 uint4_t vregA = inst->VRegA_12x(inst_data);
2116 shadow_frame.SetVReg(vregA,
2117 SafeMul(shadow_frame.GetVReg(vregA),
David Srbecky436f6c12019-05-22 13:28:42 +01002118 shadow_frame.GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002119 inst = inst->Next_1xx();
2120 }
2121
2122 ALWAYS_INLINE void DIV_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002123 uint4_t vregA = inst->VRegA_12x(inst_data);
2124 bool success = DoIntDivide(shadow_frame, vregA, shadow_frame.GetVReg(vregA),
David Srbecky436f6c12019-05-22 13:28:42 +01002125 shadow_frame.GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002126 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_1xx);
2127 }
2128
2129 ALWAYS_INLINE void REM_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002130 uint4_t vregA = inst->VRegA_12x(inst_data);
2131 bool success = DoIntRemainder(shadow_frame, vregA, shadow_frame.GetVReg(vregA),
David Srbecky436f6c12019-05-22 13:28:42 +01002132 shadow_frame.GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002133 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_1xx);
2134 }
2135
2136 ALWAYS_INLINE void SHL_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002137 uint4_t vregA = inst->VRegA_12x(inst_data);
2138 shadow_frame.SetVReg(vregA,
2139 shadow_frame.GetVReg(vregA) <<
David Srbecky436f6c12019-05-22 13:28:42 +01002140 (shadow_frame.GetVReg(B()) & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01002141 inst = inst->Next_1xx();
2142 }
2143
2144 ALWAYS_INLINE void SHR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002145 uint4_t vregA = inst->VRegA_12x(inst_data);
2146 shadow_frame.SetVReg(vregA,
2147 shadow_frame.GetVReg(vregA) >>
David Srbecky436f6c12019-05-22 13:28:42 +01002148 (shadow_frame.GetVReg(B()) & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01002149 inst = inst->Next_1xx();
2150 }
2151
2152 ALWAYS_INLINE void USHR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002153 uint4_t vregA = inst->VRegA_12x(inst_data);
2154 shadow_frame.SetVReg(vregA,
2155 static_cast<uint32_t>(shadow_frame.GetVReg(vregA)) >>
David Srbecky436f6c12019-05-22 13:28:42 +01002156 (shadow_frame.GetVReg(B()) & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01002157 inst = inst->Next_1xx();
2158 }
2159
2160 ALWAYS_INLINE void AND_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002161 uint4_t vregA = inst->VRegA_12x(inst_data);
2162 shadow_frame.SetVReg(vregA,
2163 shadow_frame.GetVReg(vregA) &
David Srbecky436f6c12019-05-22 13:28:42 +01002164 shadow_frame.GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002165 inst = inst->Next_1xx();
2166 }
2167
2168 ALWAYS_INLINE void OR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002169 uint4_t vregA = inst->VRegA_12x(inst_data);
2170 shadow_frame.SetVReg(vregA,
2171 shadow_frame.GetVReg(vregA) |
David Srbecky436f6c12019-05-22 13:28:42 +01002172 shadow_frame.GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002173 inst = inst->Next_1xx();
2174 }
2175
2176 ALWAYS_INLINE void XOR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002177 uint4_t vregA = inst->VRegA_12x(inst_data);
2178 shadow_frame.SetVReg(vregA,
2179 shadow_frame.GetVReg(vregA) ^
David Srbecky436f6c12019-05-22 13:28:42 +01002180 shadow_frame.GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002181 inst = inst->Next_1xx();
2182 }
2183
2184 ALWAYS_INLINE void ADD_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002185 uint4_t vregA = inst->VRegA_12x(inst_data);
2186 shadow_frame.SetVRegLong(vregA,
2187 SafeAdd(shadow_frame.GetVRegLong(vregA),
David Srbecky436f6c12019-05-22 13:28:42 +01002188 shadow_frame.GetVRegLong(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002189 inst = inst->Next_1xx();
2190 }
2191
2192 ALWAYS_INLINE void SUB_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002193 uint4_t vregA = inst->VRegA_12x(inst_data);
2194 shadow_frame.SetVRegLong(vregA,
2195 SafeSub(shadow_frame.GetVRegLong(vregA),
David Srbecky436f6c12019-05-22 13:28:42 +01002196 shadow_frame.GetVRegLong(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002197 inst = inst->Next_1xx();
2198 }
2199
2200 ALWAYS_INLINE void MUL_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002201 uint4_t vregA = inst->VRegA_12x(inst_data);
2202 shadow_frame.SetVRegLong(vregA,
2203 SafeMul(shadow_frame.GetVRegLong(vregA),
David Srbecky436f6c12019-05-22 13:28:42 +01002204 shadow_frame.GetVRegLong(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002205 inst = inst->Next_1xx();
2206 }
2207
2208 ALWAYS_INLINE void DIV_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002209 uint4_t vregA = inst->VRegA_12x(inst_data);
2210 DoLongDivide(shadow_frame, vregA, shadow_frame.GetVRegLong(vregA),
David Srbecky436f6c12019-05-22 13:28:42 +01002211 shadow_frame.GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002212 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
2213 }
2214
2215 ALWAYS_INLINE void REM_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002216 uint4_t vregA = inst->VRegA_12x(inst_data);
2217 DoLongRemainder(shadow_frame, vregA, shadow_frame.GetVRegLong(vregA),
David Srbecky436f6c12019-05-22 13:28:42 +01002218 shadow_frame.GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002219 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
2220 }
2221
2222 ALWAYS_INLINE void AND_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002223 uint4_t vregA = inst->VRegA_12x(inst_data);
2224 shadow_frame.SetVRegLong(vregA,
2225 shadow_frame.GetVRegLong(vregA) &
David Srbecky436f6c12019-05-22 13:28:42 +01002226 shadow_frame.GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002227 inst = inst->Next_1xx();
2228 }
2229
2230 ALWAYS_INLINE void OR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002231 uint4_t vregA = inst->VRegA_12x(inst_data);
2232 shadow_frame.SetVRegLong(vregA,
2233 shadow_frame.GetVRegLong(vregA) |
David Srbecky436f6c12019-05-22 13:28:42 +01002234 shadow_frame.GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002235 inst = inst->Next_1xx();
2236 }
2237
2238 ALWAYS_INLINE void XOR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002239 uint4_t vregA = inst->VRegA_12x(inst_data);
2240 shadow_frame.SetVRegLong(vregA,
2241 shadow_frame.GetVRegLong(vregA) ^
David Srbecky436f6c12019-05-22 13:28:42 +01002242 shadow_frame.GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002243 inst = inst->Next_1xx();
2244 }
2245
2246 ALWAYS_INLINE void SHL_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002247 uint4_t vregA = inst->VRegA_12x(inst_data);
2248 shadow_frame.SetVRegLong(vregA,
2249 shadow_frame.GetVRegLong(vregA) <<
David Srbecky436f6c12019-05-22 13:28:42 +01002250 (shadow_frame.GetVReg(B()) & 0x3f));
David Srbecky6da82472018-10-23 14:03:08 +01002251 inst = inst->Next_1xx();
2252 }
2253
2254 ALWAYS_INLINE void SHR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002255 uint4_t vregA = inst->VRegA_12x(inst_data);
2256 shadow_frame.SetVRegLong(vregA,
2257 shadow_frame.GetVRegLong(vregA) >>
David Srbecky436f6c12019-05-22 13:28:42 +01002258 (shadow_frame.GetVReg(B()) & 0x3f));
David Srbecky6da82472018-10-23 14:03:08 +01002259 inst = inst->Next_1xx();
2260 }
2261
2262 ALWAYS_INLINE void USHR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002263 uint4_t vregA = inst->VRegA_12x(inst_data);
2264 shadow_frame.SetVRegLong(vregA,
2265 static_cast<uint64_t>(shadow_frame.GetVRegLong(vregA)) >>
David Srbecky436f6c12019-05-22 13:28:42 +01002266 (shadow_frame.GetVReg(B()) & 0x3f));
David Srbecky6da82472018-10-23 14:03:08 +01002267 inst = inst->Next_1xx();
2268 }
2269
2270 ALWAYS_INLINE void ADD_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002271 uint4_t vregA = inst->VRegA_12x(inst_data);
2272 shadow_frame.SetVRegFloat(vregA,
2273 shadow_frame.GetVRegFloat(vregA) +
David Srbecky436f6c12019-05-22 13:28:42 +01002274 shadow_frame.GetVRegFloat(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002275 inst = inst->Next_1xx();
2276 }
2277
2278 ALWAYS_INLINE void SUB_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002279 uint4_t vregA = inst->VRegA_12x(inst_data);
2280 shadow_frame.SetVRegFloat(vregA,
2281 shadow_frame.GetVRegFloat(vregA) -
David Srbecky436f6c12019-05-22 13:28:42 +01002282 shadow_frame.GetVRegFloat(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002283 inst = inst->Next_1xx();
2284 }
2285
2286 ALWAYS_INLINE void MUL_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002287 uint4_t vregA = inst->VRegA_12x(inst_data);
2288 shadow_frame.SetVRegFloat(vregA,
2289 shadow_frame.GetVRegFloat(vregA) *
David Srbecky436f6c12019-05-22 13:28:42 +01002290 shadow_frame.GetVRegFloat(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002291 inst = inst->Next_1xx();
2292 }
2293
2294 ALWAYS_INLINE void DIV_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002295 uint4_t vregA = inst->VRegA_12x(inst_data);
2296 shadow_frame.SetVRegFloat(vregA,
2297 shadow_frame.GetVRegFloat(vregA) /
David Srbecky436f6c12019-05-22 13:28:42 +01002298 shadow_frame.GetVRegFloat(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002299 inst = inst->Next_1xx();
2300 }
2301
2302 ALWAYS_INLINE void REM_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002303 uint4_t vregA = inst->VRegA_12x(inst_data);
2304 shadow_frame.SetVRegFloat(vregA,
2305 fmodf(shadow_frame.GetVRegFloat(vregA),
David Srbecky436f6c12019-05-22 13:28:42 +01002306 shadow_frame.GetVRegFloat(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002307 inst = inst->Next_1xx();
2308 }
2309
2310 ALWAYS_INLINE void ADD_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002311 uint4_t vregA = inst->VRegA_12x(inst_data);
2312 shadow_frame.SetVRegDouble(vregA,
2313 shadow_frame.GetVRegDouble(vregA) +
David Srbecky436f6c12019-05-22 13:28:42 +01002314 shadow_frame.GetVRegDouble(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002315 inst = inst->Next_1xx();
2316 }
2317
2318 ALWAYS_INLINE void SUB_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002319 uint4_t vregA = inst->VRegA_12x(inst_data);
2320 shadow_frame.SetVRegDouble(vregA,
2321 shadow_frame.GetVRegDouble(vregA) -
David Srbecky436f6c12019-05-22 13:28:42 +01002322 shadow_frame.GetVRegDouble(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002323 inst = inst->Next_1xx();
2324 }
2325
2326 ALWAYS_INLINE void MUL_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002327 uint4_t vregA = inst->VRegA_12x(inst_data);
2328 shadow_frame.SetVRegDouble(vregA,
2329 shadow_frame.GetVRegDouble(vregA) *
David Srbecky436f6c12019-05-22 13:28:42 +01002330 shadow_frame.GetVRegDouble(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002331 inst = inst->Next_1xx();
2332 }
2333
2334 ALWAYS_INLINE void DIV_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002335 uint4_t vregA = inst->VRegA_12x(inst_data);
2336 shadow_frame.SetVRegDouble(vregA,
2337 shadow_frame.GetVRegDouble(vregA) /
David Srbecky436f6c12019-05-22 13:28:42 +01002338 shadow_frame.GetVRegDouble(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002339 inst = inst->Next_1xx();
2340 }
2341
2342 ALWAYS_INLINE void REM_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002343 uint4_t vregA = inst->VRegA_12x(inst_data);
2344 shadow_frame.SetVRegDouble(vregA,
2345 fmod(shadow_frame.GetVRegDouble(vregA),
David Srbecky436f6c12019-05-22 13:28:42 +01002346 shadow_frame.GetVRegDouble(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002347 inst = inst->Next_1xx();
2348 }
2349
2350 ALWAYS_INLINE void ADD_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002351 shadow_frame.SetVReg(A(),
2352 SafeAdd(shadow_frame.GetVReg(B()),
David Srbecky6da82472018-10-23 14:03:08 +01002353 inst->VRegC_22s()));
2354 inst = inst->Next_2xx();
2355 }
2356
2357 ALWAYS_INLINE void RSUB_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002358 shadow_frame.SetVReg(A(),
David Srbecky6da82472018-10-23 14:03:08 +01002359 SafeSub(inst->VRegC_22s(),
David Srbecky436f6c12019-05-22 13:28:42 +01002360 shadow_frame.GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002361 inst = inst->Next_2xx();
2362 }
2363
2364 ALWAYS_INLINE void MUL_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002365 shadow_frame.SetVReg(A(),
2366 SafeMul(shadow_frame.GetVReg(B()),
David Srbecky6da82472018-10-23 14:03:08 +01002367 inst->VRegC_22s()));
2368 inst = inst->Next_2xx();
2369 }
2370
2371 ALWAYS_INLINE void DIV_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002372 bool success = DoIntDivide(shadow_frame, inst->VRegA_22s(inst_data),
David Srbecky436f6c12019-05-22 13:28:42 +01002373 shadow_frame.GetVReg(B()),
David Srbecky6da82472018-10-23 14:03:08 +01002374 inst->VRegC_22s());
2375 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
2376 }
2377
2378 ALWAYS_INLINE void REM_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002379 bool success = DoIntRemainder(shadow_frame, inst->VRegA_22s(inst_data),
David Srbecky436f6c12019-05-22 13:28:42 +01002380 shadow_frame.GetVReg(B()),
David Srbecky6da82472018-10-23 14:03:08 +01002381 inst->VRegC_22s());
2382 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
2383 }
2384
2385 ALWAYS_INLINE void AND_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002386 shadow_frame.SetVReg(A(),
2387 shadow_frame.GetVReg(B()) &
David Srbecky6da82472018-10-23 14:03:08 +01002388 inst->VRegC_22s());
2389 inst = inst->Next_2xx();
2390 }
2391
2392 ALWAYS_INLINE void OR_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002393 shadow_frame.SetVReg(A(),
2394 shadow_frame.GetVReg(B()) |
David Srbecky6da82472018-10-23 14:03:08 +01002395 inst->VRegC_22s());
2396 inst = inst->Next_2xx();
2397 }
2398
2399 ALWAYS_INLINE void XOR_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002400 shadow_frame.SetVReg(A(),
2401 shadow_frame.GetVReg(B()) ^
David Srbecky6da82472018-10-23 14:03:08 +01002402 inst->VRegC_22s());
2403 inst = inst->Next_2xx();
2404 }
2405
2406 ALWAYS_INLINE void ADD_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002407 shadow_frame.SetVReg(A(),
2408 SafeAdd(shadow_frame.GetVReg(B()), inst->VRegC_22b()));
David Srbecky6da82472018-10-23 14:03:08 +01002409 inst = inst->Next_2xx();
2410 }
2411
2412 ALWAYS_INLINE void RSUB_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002413 shadow_frame.SetVReg(A(),
2414 SafeSub(inst->VRegC_22b(), shadow_frame.GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002415 inst = inst->Next_2xx();
2416 }
2417
2418 ALWAYS_INLINE void MUL_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002419 shadow_frame.SetVReg(A(),
2420 SafeMul(shadow_frame.GetVReg(B()), inst->VRegC_22b()));
David Srbecky6da82472018-10-23 14:03:08 +01002421 inst = inst->Next_2xx();
2422 }
2423
2424 ALWAYS_INLINE void DIV_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002425 bool success = DoIntDivide(shadow_frame, inst->VRegA_22b(inst_data),
David Srbecky436f6c12019-05-22 13:28:42 +01002426 shadow_frame.GetVReg(B()), inst->VRegC_22b());
David Srbecky6da82472018-10-23 14:03:08 +01002427 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
2428 }
2429
2430 ALWAYS_INLINE void REM_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002431 bool success = DoIntRemainder(shadow_frame, inst->VRegA_22b(inst_data),
David Srbecky436f6c12019-05-22 13:28:42 +01002432 shadow_frame.GetVReg(B()), inst->VRegC_22b());
David Srbecky6da82472018-10-23 14:03:08 +01002433 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
2434 }
2435
2436 ALWAYS_INLINE void AND_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002437 shadow_frame.SetVReg(A(),
2438 shadow_frame.GetVReg(B()) &
David Srbecky6da82472018-10-23 14:03:08 +01002439 inst->VRegC_22b());
2440 inst = inst->Next_2xx();
2441 }
2442
2443 ALWAYS_INLINE void OR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002444 shadow_frame.SetVReg(A(),
2445 shadow_frame.GetVReg(B()) |
David Srbecky6da82472018-10-23 14:03:08 +01002446 inst->VRegC_22b());
2447 inst = inst->Next_2xx();
2448 }
2449
2450 ALWAYS_INLINE void XOR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002451 shadow_frame.SetVReg(A(),
2452 shadow_frame.GetVReg(B()) ^
David Srbecky6da82472018-10-23 14:03:08 +01002453 inst->VRegC_22b());
2454 inst = inst->Next_2xx();
2455 }
2456
2457 ALWAYS_INLINE void SHL_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002458 shadow_frame.SetVReg(A(),
2459 shadow_frame.GetVReg(B()) <<
David Srbecky6da82472018-10-23 14:03:08 +01002460 (inst->VRegC_22b() & 0x1f));
2461 inst = inst->Next_2xx();
2462 }
2463
2464 ALWAYS_INLINE void SHR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002465 shadow_frame.SetVReg(A(),
2466 shadow_frame.GetVReg(B()) >>
David Srbecky6da82472018-10-23 14:03:08 +01002467 (inst->VRegC_22b() & 0x1f));
2468 inst = inst->Next_2xx();
2469 }
2470
2471 ALWAYS_INLINE void USHR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002472 shadow_frame.SetVReg(A(),
2473 static_cast<uint32_t>(shadow_frame.GetVReg(B())) >>
David Srbecky6da82472018-10-23 14:03:08 +01002474 (inst->VRegC_22b() & 0x1f));
2475 inst = inst->Next_2xx();
2476 }
2477
2478 ALWAYS_INLINE void UNUSED_3E() REQUIRES_SHARED(Locks::mutator_lock_) {
2479 UnexpectedOpcode(inst, shadow_frame);
2480 }
2481
2482 ALWAYS_INLINE void UNUSED_3F() REQUIRES_SHARED(Locks::mutator_lock_) {
2483 UnexpectedOpcode(inst, shadow_frame);
2484 }
2485
2486 ALWAYS_INLINE void UNUSED_40() REQUIRES_SHARED(Locks::mutator_lock_) {
2487 UnexpectedOpcode(inst, shadow_frame);
2488 }
2489
2490 ALWAYS_INLINE void UNUSED_41() REQUIRES_SHARED(Locks::mutator_lock_) {
2491 UnexpectedOpcode(inst, shadow_frame);
2492 }
2493
2494 ALWAYS_INLINE void UNUSED_42() REQUIRES_SHARED(Locks::mutator_lock_) {
2495 UnexpectedOpcode(inst, shadow_frame);
2496 }
2497
2498 ALWAYS_INLINE void UNUSED_43() REQUIRES_SHARED(Locks::mutator_lock_) {
2499 UnexpectedOpcode(inst, shadow_frame);
2500 }
2501
2502 ALWAYS_INLINE void UNUSED_79() REQUIRES_SHARED(Locks::mutator_lock_) {
2503 UnexpectedOpcode(inst, shadow_frame);
2504 }
2505
2506 ALWAYS_INLINE void UNUSED_7A() REQUIRES_SHARED(Locks::mutator_lock_) {
2507 UnexpectedOpcode(inst, shadow_frame);
2508 }
2509
2510 ALWAYS_INLINE void UNUSED_F3() REQUIRES_SHARED(Locks::mutator_lock_) {
2511 UnexpectedOpcode(inst, shadow_frame);
2512 }
2513
2514 ALWAYS_INLINE void UNUSED_F4() REQUIRES_SHARED(Locks::mutator_lock_) {
2515 UnexpectedOpcode(inst, shadow_frame);
2516 }
2517
2518 ALWAYS_INLINE void UNUSED_F5() REQUIRES_SHARED(Locks::mutator_lock_) {
2519 UnexpectedOpcode(inst, shadow_frame);
2520 }
2521
2522 ALWAYS_INLINE void UNUSED_F6() REQUIRES_SHARED(Locks::mutator_lock_) {
2523 UnexpectedOpcode(inst, shadow_frame);
2524 }
2525
2526 ALWAYS_INLINE void UNUSED_F7() REQUIRES_SHARED(Locks::mutator_lock_) {
2527 UnexpectedOpcode(inst, shadow_frame);
2528 }
2529
2530 ALWAYS_INLINE void UNUSED_F8() REQUIRES_SHARED(Locks::mutator_lock_) {
2531 UnexpectedOpcode(inst, shadow_frame);
2532 }
2533
2534 ALWAYS_INLINE void UNUSED_F9() REQUIRES_SHARED(Locks::mutator_lock_) {
2535 UnexpectedOpcode(inst, shadow_frame);
2536 }
2537
2538 ALWAYS_INLINE InstructionHandler(SwitchImplContext* ctx,
2539 const instrumentation::Instrumentation* instrumentation,
2540 Thread* self,
2541 ShadowFrame& shadow_frame,
2542 uint16_t dex_pc,
2543 const Instruction*& inst,
2544 uint16_t inst_data,
2545 bool& exit_interpreter_loop)
2546 : ctx(ctx),
2547 instrumentation(instrumentation),
2548 self(self),
2549 shadow_frame(shadow_frame),
2550 dex_pc(dex_pc),
2551 inst(inst),
2552 inst_data(inst_data),
2553 exit_interpreter_loop(exit_interpreter_loop) {
2554 }
2555
2556 private:
2557 static constexpr bool do_assignability_check = do_access_check;
2558
2559 const CodeItemDataAccessor& Accessor() { return ctx->accessor; }
2560 const uint16_t* Insns() { return ctx->accessor.Insns(); }
2561 JValue* ResultRegister() { return &ctx->result_register; }
2562
David Srbecky436f6c12019-05-22 13:28:42 +01002563 ALWAYS_INLINE int32_t A() { return inst->VRegA(kFormat, inst_data); }
2564 ALWAYS_INLINE int32_t B() { return inst->VRegB(kFormat, inst_data); }
2565 ALWAYS_INLINE int32_t C() { return inst->VRegC(kFormat); }
2566
David Srbecky6da82472018-10-23 14:03:08 +01002567 SwitchImplContext* const ctx;
2568 const instrumentation::Instrumentation* const instrumentation;
2569 Thread* const self;
2570 ShadowFrame& shadow_frame;
2571 uint32_t const dex_pc;
2572 const Instruction*& inst;
2573 uint16_t const inst_data;
2574 bool& exit_interpreter_loop;
2575};
2576
David Srbecky6da82472018-10-23 14:03:08 +01002577#undef BRANCH_INSTRUMENTATION
David Srbecky6da82472018-10-23 14:03:08 +01002578#undef POSSIBLY_HANDLE_PENDING_EXCEPTION
2579#undef POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE
2580#undef POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC
David Srbecky6da82472018-10-23 14:03:08 +01002581#undef HANDLE_PENDING_EXCEPTION
David Srbecky6da82472018-10-23 14:03:08 +01002582
Alex Light6f22e062018-10-05 15:05:12 -07002583// TODO On ASAN builds this function gets a huge stack frame. Since normally we run in the mterp
2584// this shouldn't cause any problems for stack overflow detection. Remove this once b/117341496 is
2585// fixed.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +01002586template<bool do_access_check, bool transaction_active>
Alex Light6f22e062018-10-05 15:05:12 -07002587ATTRIBUTE_NO_SANITIZE_ADDRESS void ExecuteSwitchImplCpp(SwitchImplContext* ctx) {
David Srbecky946bb092018-03-09 17:23:01 +00002588 Thread* self = ctx->self;
2589 const CodeItemDataAccessor& accessor = ctx->accessor;
2590 ShadowFrame& shadow_frame = ctx->shadow_frame;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002591 if (UNLIKELY(!shadow_frame.HasReferenceArray())) {
2592 LOG(FATAL) << "Invalid shadow frame for interpreter use";
David Srbecky946bb092018-03-09 17:23:01 +00002593 ctx->result = JValue();
2594 return;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002595 }
2596 self->VerifyStack();
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002597
2598 uint32_t dex_pc = shadow_frame.GetDexPC();
Mathieu Chartier2cebb242015-04-21 16:50:40 -07002599 const auto* const instrumentation = Runtime::Current()->GetInstrumentation();
Mathieu Chartier808c7a52017-12-15 11:19:33 -08002600 const uint16_t* const insns = accessor.Insns();
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002601 const Instruction* inst = Instruction::At(insns + dex_pc);
Sebastien Hertz3b588e02013-09-11 14:33:18 +02002602 uint16_t inst_data;
Igor Murashkin6918bf12015-09-27 19:19:06 -07002603
Alex Light0aa7a5a2018-10-10 15:58:14 +00002604 DCHECK(!shadow_frame.GetForceRetryInstruction())
2605 << "Entered interpreter from invoke without retry instruction being handled!";
2606
David Srbecky6da82472018-10-23 14:03:08 +01002607 bool const interpret_one_instruction = ctx->interpret_one_instruction;
2608 while (true) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002609 dex_pc = inst->GetDexPc(insns);
2610 shadow_frame.SetDexPC(dex_pc);
Ian Rogerse94652f2014-12-02 11:13:19 -08002611 TraceExecution(shadow_frame, inst, dex_pc);
Sebastien Hertz3b588e02013-09-11 14:33:18 +02002612 inst_data = inst->Fetch16(0);
David Srbeckya4a96af2018-10-31 16:34:58 +00002613 {
2614 bool exit_loop = false;
David Srbecky436f6c12019-05-22 13:28:42 +01002615 InstructionHandler<do_access_check, transaction_active, Instruction::kInvalidFormat> handler(
David Srbeckya4a96af2018-10-31 16:34:58 +00002616 ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, exit_loop);
2617 if (!handler.Preamble()) {
2618 if (UNLIKELY(exit_loop)) {
2619 return;
2620 }
2621 if (UNLIKELY(interpret_one_instruction)) {
2622 break;
2623 }
2624 continue;
2625 }
2626 }
Sebastien Hertz3b588e02013-09-11 14:33:18 +02002627 switch (inst->Opcode(inst_data)) {
David Srbecky436f6c12019-05-22 13:28:42 +01002628#define OPCODE_CASE(OPCODE, OPCODE_NAME, pname, FORMAT, i, a, e, v) \
David Srbecky6da82472018-10-23 14:03:08 +01002629 case OPCODE: { \
2630 bool exit_loop = false; \
David Srbecky436f6c12019-05-22 13:28:42 +01002631 InstructionHandler<do_access_check, transaction_active, Instruction::FORMAT> handler( \
David Srbecky6da82472018-10-23 14:03:08 +01002632 ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, exit_loop); \
David Srbeckya4a96af2018-10-31 16:34:58 +00002633 handler.OPCODE_NAME(); \
David Srbecky6da82472018-10-23 14:03:08 +01002634 /* TODO: Advance 'inst' here, instead of explicitly in each handler */ \
2635 if (UNLIKELY(exit_loop)) { \
2636 return; \
2637 } \
2638 break; \
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002639 }
David Srbecky6da82472018-10-23 14:03:08 +01002640DEX_INSTRUCTION_LIST(OPCODE_CASE)
2641#undef OPCODE_CASE
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002642 }
David Srbecky6da82472018-10-23 14:03:08 +01002643 if (UNLIKELY(interpret_one_instruction)) {
David Srbeckya4a96af2018-10-31 16:34:58 +00002644 break;
David Srbecky6da82472018-10-23 14:03:08 +01002645 }
2646 }
David Srbeckya4a96af2018-10-31 16:34:58 +00002647 // Record where we stopped.
2648 shadow_frame.SetDexPC(inst->GetDexPc(insns));
2649 ctx->result = ctx->result_register;
2650 return;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002651} // NOLINT(readability/fn_size)
2652
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002653} // namespace interpreter
2654} // namespace art
David Srbecky2ee09ff2018-10-24 13:24:22 +01002655
2656#endif // ART_RUNTIME_INTERPRETER_INTERPRETER_SWITCH_IMPL_INL_H_