blob: bf12a72f9aa7bb9dcb41c649f2253a2b558fd5da [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"
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +000029#include "jit/jit.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 Srbecky6da82472018-10-23 14:03:08 +010049template<bool do_access_check, bool transaction_active>
50class 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
74 ALWAYS_INLINE WARN_UNUSED bool HandlePendingExceptionWithInstrumentation(
75 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
102 ALWAYS_INLINE WARN_UNUSED bool HandlePendingException()
103 REQUIRES_SHARED(Locks::mutator_lock_) {
104 return HandlePendingExceptionWithInstrumentation(instrumentation);
105 }
106
107 ALWAYS_INLINE WARN_UNUSED bool PossiblyHandlePendingExceptionOnInvokeImpl(
108 bool is_exception_pending,
109 const Instruction* next_inst)
110 REQUIRES_SHARED(Locks::mutator_lock_) {
111 if (UNLIKELY(shadow_frame.GetForceRetryInstruction())) {
112 /* Don't need to do anything except clear the flag and exception. We leave the */
113 /* instruction the same so it will be re-executed on the next go-around. */
114 DCHECK(inst->IsInvoke());
115 shadow_frame.SetForceRetryInstruction(false);
116 if (UNLIKELY(is_exception_pending)) {
117 DCHECK(self->IsExceptionPending());
118 if (kIsDebugBuild) {
119 LOG(WARNING) << "Suppressing exception for instruction-retry: "
120 << self->GetException()->Dump();
121 }
122 self->ClearException();
123 }
124 } else if (UNLIKELY(is_exception_pending)) {
125 /* Should have succeeded. */
126 DCHECK(!shadow_frame.GetForceRetryInstruction());
127 if (!HandlePendingException()) {
128 return false;
129 }
130 } else {
131 inst = next_inst;
132 }
133 return true;
134 }
135
136 ALWAYS_INLINE WARN_UNUSED bool PossiblyHandlePendingException(
137 bool is_exception_pending,
138 const Instruction* next_inst)
139 REQUIRES_SHARED(Locks::mutator_lock_) {
140 /* Should only be on invoke instructions. */
141 DCHECK(!shadow_frame.GetForceRetryInstruction());
142 if (UNLIKELY(is_exception_pending)) {
143 if (!HandlePendingException()) {
144 return false;
145 }
146 } else {
147 inst = next_inst;
148 }
149 return true;
150 }
151
152 ALWAYS_INLINE WARN_UNUSED bool HandleMonitorChecks()
153 REQUIRES_SHARED(Locks::mutator_lock_) {
154 if (!DoMonitorCheckOnExit<do_assignability_check>(self, &shadow_frame)) {
155 if (!HandlePendingException()) {
156 return false;
157 }
158 }
159 return true;
160 }
161
162 // Code to run before each dex instruction.
David Srbeckya4a96af2018-10-31 16:34:58 +0000163 ALWAYS_INLINE WARN_UNUSED bool Preamble()
David Srbecky47ad3762018-10-31 12:43:40 +0000164 REQUIRES_SHARED(Locks::mutator_lock_) {
165 /* We need to put this before & after the instrumentation to avoid having to put in a */
166 /* post-script macro. */
167 if (!CheckForceReturn()) {
168 return false;
169 }
170 if (UNLIKELY(instrumentation->HasDexPcListeners())) {
David Srbeckya4a96af2018-10-31 16:34:58 +0000171 uint8_t opcode = inst->Opcode(inst_data);
172 bool is_move_result_object = (opcode == Instruction::MOVE_RESULT_OBJECT);
173 JValue* save_ref = is_move_result_object ? &ctx->result_register : nullptr;
David Srbecky47ad3762018-10-31 12:43:40 +0000174 if (UNLIKELY(!DoDexPcMoveEvent(self,
175 Accessor(),
176 shadow_frame,
177 dex_pc,
178 instrumentation,
179 save_ref))) {
180 if (!HandlePendingException()) {
181 return false;
182 }
183 }
184 if (!CheckForceReturn()) {
185 return false;
186 }
187 }
188 return true;
189 }
190
191 ALWAYS_INLINE WARN_UNUSED bool BranchInstrumentation(int32_t offset)
192 REQUIRES_SHARED(Locks::mutator_lock_) {
193 if (UNLIKELY(instrumentation->HasBranchListeners())) {
194 instrumentation->Branch(self, shadow_frame.GetMethod(), dex_pc, offset);
195 }
196 JValue result;
197 if (jit::Jit::MaybeDoOnStackReplacement(self,
198 shadow_frame.GetMethod(),
199 dex_pc,
200 offset,
201 &result)) {
202 if (ctx->interpret_one_instruction) {
203 /* OSR has completed execution of the method. Signal mterp to return to caller */
204 shadow_frame.SetDexPC(dex::kDexNoIndex);
205 }
206 ctx->result = result;
207 exit_interpreter_loop = true;
208 return false;
209 }
210 return true;
211 }
212
213 ALWAYS_INLINE void HotnessUpdate()
214 REQUIRES_SHARED(Locks::mutator_lock_) {
215 jit::Jit* jit = Runtime::Current()->GetJit();
216 if (jit != nullptr) {
217 jit->AddSamples(self, shadow_frame.GetMethod(), 1, /*with_backedges=*/ true);
218 }
219 }
220
221 ALWAYS_INLINE WARN_UNUSED bool HandleAsyncException()
222 REQUIRES_SHARED(Locks::mutator_lock_) {
223 if (UNLIKELY(self->ObserveAsyncException())) {
224 if (!HandlePendingException()) {
225 return false;
226 }
227 }
228 return true;
229 }
230
231 ALWAYS_INLINE void HandleBackwardBranch(int32_t offset)
232 REQUIRES_SHARED(Locks::mutator_lock_) {
233 if (IsBackwardBranch(offset)) {
234 HotnessUpdate();
235 /* Record new dex pc early to have consistent suspend point at loop header. */
236 shadow_frame.SetDexPC(inst->GetDexPc(Insns()));
237 self->AllowThreadSuspension();
238 }
239 }
240
241 // Unlike most other events the DexPcMovedEvent can be sent when there is a pending exception (if
242 // the next instruction is MOVE_EXCEPTION). This means it needs to be handled carefully to be able
243 // to detect exceptions thrown by the DexPcMovedEvent itself. These exceptions could be thrown by
244 // jvmti-agents while handling breakpoint or single step events. We had to move this into its own
245 // function because it was making ExecuteSwitchImpl have too large a stack.
246 NO_INLINE static bool DoDexPcMoveEvent(Thread* self,
247 const CodeItemDataAccessor& accessor,
248 const ShadowFrame& shadow_frame,
249 uint32_t dex_pc,
250 const instrumentation::Instrumentation* instrumentation,
251 JValue* save_ref)
252 REQUIRES_SHARED(Locks::mutator_lock_) {
253 DCHECK(instrumentation->HasDexPcListeners());
254 StackHandleScope<2> hs(self);
255 Handle<mirror::Throwable> thr(hs.NewHandle(self->GetException()));
256 mirror::Object* null_obj = nullptr;
257 HandleWrapper<mirror::Object> h(
258 hs.NewHandleWrapper(LIKELY(save_ref == nullptr) ? &null_obj : save_ref->GetGCRoot()));
259 self->ClearException();
260 instrumentation->DexPcMovedEvent(self,
261 shadow_frame.GetThisObject(accessor.InsSize()),
262 shadow_frame.GetMethod(),
263 dex_pc);
264 if (UNLIKELY(self->IsExceptionPending())) {
265 // We got a new exception in the dex-pc-moved event.
266 // We just let this exception replace the old one.
267 // TODO It would be good to add the old exception to the
268 // suppressed exceptions of the new one if possible.
269 return false;
270 } else {
271 if (UNLIKELY(!thr.IsNull())) {
272 self->SetException(thr.Get());
273 }
274 return true;
275 }
276 }
277
278 static bool NeedsMethodExitEvent(const instrumentation::Instrumentation* ins)
279 REQUIRES_SHARED(Locks::mutator_lock_) {
280 return ins->HasMethodExitListeners() || ins->HasWatchedFramePopListeners();
281 }
282
283 // Sends the normal method exit event.
284 // Returns true if the events succeeded and false if there is a pending exception.
285 NO_INLINE static bool SendMethodExitEvents(
286 Thread* self,
287 const instrumentation::Instrumentation* instrumentation,
288 const ShadowFrame& frame,
289 ObjPtr<mirror::Object> thiz,
290 ArtMethod* method,
291 uint32_t dex_pc,
292 const JValue& result)
293 REQUIRES_SHARED(Locks::mutator_lock_) {
294 bool had_event = false;
295 // We don't send method-exit if it's a pop-frame. We still send frame_popped though.
296 if (UNLIKELY(instrumentation->HasMethodExitListeners() && !frame.GetForcePopFrame())) {
297 had_event = true;
298 instrumentation->MethodExitEvent(self, thiz.Ptr(), method, dex_pc, result);
299 }
300 if (UNLIKELY(frame.NeedsNotifyPop() && instrumentation->HasWatchedFramePopListeners())) {
301 had_event = true;
302 instrumentation->WatchedFramePopped(self, frame);
303 }
304 if (UNLIKELY(had_event)) {
305 return !self->IsExceptionPending();
306 } else {
307 return true;
308 }
309 }
310
311#define BRANCH_INSTRUMENTATION(offset) \
312 if (!BranchInstrumentation(offset)) { \
313 return; \
314 }
315
316#define HANDLE_PENDING_EXCEPTION() \
317 if (!HandlePendingException()) { \
318 return; \
319 }
320
321#define POSSIBLY_HANDLE_PENDING_EXCEPTION(is_exception_pending, next_function) \
322 if (!PossiblyHandlePendingException(is_exception_pending, inst->next_function())) { \
323 return; \
324 }
325
326#define POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(is_exception_pending) \
327 if (!PossiblyHandlePendingExceptionOnInvokeImpl(is_exception_pending, inst->Next_4xx())) { \
328 return; \
329 }
330
331#define POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(is_exception_pending) \
332 if (!PossiblyHandlePendingExceptionOnInvokeImpl(is_exception_pending, inst->Next_3xx())) { \
333 return; \
334 }
335
David Srbecky6da82472018-10-23 14:03:08 +0100336 ALWAYS_INLINE void NOP() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100337 inst = inst->Next_1xx();
338 }
339
340 ALWAYS_INLINE void MOVE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100341 shadow_frame.SetVReg(inst->VRegA_12x(inst_data),
342 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
343 inst = inst->Next_1xx();
344 }
345
346 ALWAYS_INLINE void MOVE_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100347 shadow_frame.SetVReg(inst->VRegA_22x(inst_data),
348 shadow_frame.GetVReg(inst->VRegB_22x()));
349 inst = inst->Next_2xx();
350 }
351
352 ALWAYS_INLINE void MOVE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100353 shadow_frame.SetVReg(inst->VRegA_32x(),
354 shadow_frame.GetVReg(inst->VRegB_32x()));
355 inst = inst->Next_3xx();
356 }
357
358 ALWAYS_INLINE void MOVE_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100359 shadow_frame.SetVRegLong(inst->VRegA_12x(inst_data),
360 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
361 inst = inst->Next_1xx();
362 }
363
364 ALWAYS_INLINE void MOVE_WIDE_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100365 shadow_frame.SetVRegLong(inst->VRegA_22x(inst_data),
366 shadow_frame.GetVRegLong(inst->VRegB_22x()));
367 inst = inst->Next_2xx();
368 }
369
370 ALWAYS_INLINE void MOVE_WIDE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100371 shadow_frame.SetVRegLong(inst->VRegA_32x(),
372 shadow_frame.GetVRegLong(inst->VRegB_32x()));
373 inst = inst->Next_3xx();
374 }
375
376 ALWAYS_INLINE void MOVE_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100377 shadow_frame.SetVRegReference(inst->VRegA_12x(inst_data),
378 shadow_frame.GetVRegReference(inst->VRegB_12x(inst_data)));
379 inst = inst->Next_1xx();
380 }
381
382 ALWAYS_INLINE void MOVE_OBJECT_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100383 shadow_frame.SetVRegReference(inst->VRegA_22x(inst_data),
384 shadow_frame.GetVRegReference(inst->VRegB_22x()));
385 inst = inst->Next_2xx();
386 }
387
388 ALWAYS_INLINE void MOVE_OBJECT_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100389 shadow_frame.SetVRegReference(inst->VRegA_32x(),
390 shadow_frame.GetVRegReference(inst->VRegB_32x()));
391 inst = inst->Next_3xx();
392 }
393
394 ALWAYS_INLINE void MOVE_RESULT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100395 shadow_frame.SetVReg(inst->VRegA_11x(inst_data), ResultRegister()->GetI());
396 inst = inst->Next_1xx();
397 }
398
399 ALWAYS_INLINE void MOVE_RESULT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100400 shadow_frame.SetVRegLong(inst->VRegA_11x(inst_data), ResultRegister()->GetJ());
401 inst = inst->Next_1xx();
402 }
403
404 ALWAYS_INLINE void MOVE_RESULT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100405 shadow_frame.SetVRegReference(inst->VRegA_11x(inst_data), ResultRegister()->GetL());
406 inst = inst->Next_1xx();
407 }
408
409 ALWAYS_INLINE void MOVE_EXCEPTION() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100410 ObjPtr<mirror::Throwable> exception = self->GetException();
411 DCHECK(exception != nullptr) << "No pending exception on MOVE_EXCEPTION instruction";
412 shadow_frame.SetVRegReference(inst->VRegA_11x(inst_data), exception);
413 self->ClearException();
414 inst = inst->Next_1xx();
415 }
416
417 ALWAYS_INLINE void RETURN_VOID_NO_BARRIER() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100418 JValue result;
419 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000420 if (!HandleMonitorChecks()) {
421 return;
422 }
David Srbecky6da82472018-10-23 14:03:08 +0100423 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
424 !SendMethodExitEvents(self,
425 instrumentation,
426 shadow_frame,
427 shadow_frame.GetThisObject(Accessor().InsSize()),
428 shadow_frame.GetMethod(),
429 inst->GetDexPc(Insns()),
430 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000431 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
432 return;
433 }
David Srbecky6da82472018-10-23 14:03:08 +0100434 }
435 if (ctx->interpret_one_instruction) {
436 /* Signal mterp to return to caller */
437 shadow_frame.SetDexPC(dex::kDexNoIndex);
438 }
439 ctx->result = result;
440 exit_interpreter_loop = true;
441 }
442
443 ALWAYS_INLINE void RETURN_VOID() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100444 QuasiAtomic::ThreadFenceForConstructor();
445 JValue result;
446 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000447 if (!HandleMonitorChecks()) {
448 return;
449 }
David Srbecky6da82472018-10-23 14:03:08 +0100450 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
451 !SendMethodExitEvents(self,
452 instrumentation,
453 shadow_frame,
454 shadow_frame.GetThisObject(Accessor().InsSize()),
455 shadow_frame.GetMethod(),
456 inst->GetDexPc(Insns()),
457 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000458 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
459 return;
460 }
David Srbecky6da82472018-10-23 14:03:08 +0100461 }
462 if (ctx->interpret_one_instruction) {
463 /* Signal mterp to return to caller */
464 shadow_frame.SetDexPC(dex::kDexNoIndex);
465 }
466 ctx->result = result;
467 exit_interpreter_loop = true;
468 }
469
470 ALWAYS_INLINE void RETURN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100471 JValue result;
472 result.SetJ(0);
473 result.SetI(shadow_frame.GetVReg(inst->VRegA_11x(inst_data)));
474 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000475 if (!HandleMonitorChecks()) {
476 return;
477 }
David Srbecky6da82472018-10-23 14:03:08 +0100478 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
479 !SendMethodExitEvents(self,
480 instrumentation,
481 shadow_frame,
482 shadow_frame.GetThisObject(Accessor().InsSize()),
483 shadow_frame.GetMethod(),
484 inst->GetDexPc(Insns()),
485 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000486 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
487 return;
488 }
David Srbecky6da82472018-10-23 14:03:08 +0100489 }
490 if (ctx->interpret_one_instruction) {
491 /* Signal mterp to return to caller */
492 shadow_frame.SetDexPC(dex::kDexNoIndex);
493 }
494 ctx->result = result;
495 exit_interpreter_loop = true;
496 }
497
498 ALWAYS_INLINE void RETURN_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100499 JValue result;
500 result.SetJ(shadow_frame.GetVRegLong(inst->VRegA_11x(inst_data)));
501 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000502 if (!HandleMonitorChecks()) {
503 return;
504 }
David Srbecky6da82472018-10-23 14:03:08 +0100505 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
506 !SendMethodExitEvents(self,
507 instrumentation,
508 shadow_frame,
509 shadow_frame.GetThisObject(Accessor().InsSize()),
510 shadow_frame.GetMethod(),
511 inst->GetDexPc(Insns()),
512 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000513 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
514 return;
515 }
David Srbecky6da82472018-10-23 14:03:08 +0100516 }
517 if (ctx->interpret_one_instruction) {
518 /* Signal mterp to return to caller */
519 shadow_frame.SetDexPC(dex::kDexNoIndex);
520 }
521 ctx->result = result;
522 exit_interpreter_loop = true;
523 }
524
525 ALWAYS_INLINE void RETURN_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100526 JValue result;
527 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000528 if (!HandleMonitorChecks()) {
529 return;
530 }
David Srbecky6da82472018-10-23 14:03:08 +0100531 const size_t ref_idx = inst->VRegA_11x(inst_data);
532 ObjPtr<mirror::Object> obj_result = shadow_frame.GetVRegReference(ref_idx);
533 if (do_assignability_check && obj_result != nullptr) {
534 ObjPtr<mirror::Class> return_type = shadow_frame.GetMethod()->ResolveReturnType();
535 // Re-load since it might have moved.
536 obj_result = shadow_frame.GetVRegReference(ref_idx);
537 if (return_type == nullptr) {
538 // Return the pending exception.
539 HANDLE_PENDING_EXCEPTION();
540 }
541 if (!obj_result->VerifierInstanceOf(return_type)) {
542 // This should never happen.
543 std::string temp1, temp2;
544 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
545 "Returning '%s' that is not instance of return type '%s'",
546 obj_result->GetClass()->GetDescriptor(&temp1),
547 return_type->GetDescriptor(&temp2));
548 HANDLE_PENDING_EXCEPTION();
549 }
550 }
551 result.SetL(obj_result);
552 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
553 !SendMethodExitEvents(self,
554 instrumentation,
555 shadow_frame,
556 shadow_frame.GetThisObject(Accessor().InsSize()),
557 shadow_frame.GetMethod(),
558 inst->GetDexPc(Insns()),
559 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000560 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
561 return;
562 }
David Srbecky6da82472018-10-23 14:03:08 +0100563 }
564 // Re-load since it might have moved during the MethodExitEvent.
565 result.SetL(shadow_frame.GetVRegReference(ref_idx));
566 if (ctx->interpret_one_instruction) {
567 /* Signal mterp to return to caller */
568 shadow_frame.SetDexPC(dex::kDexNoIndex);
569 }
570 ctx->result = result;
571 exit_interpreter_loop = true;
572 }
573
574 ALWAYS_INLINE void CONST_4() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100575 uint4_t dst = inst->VRegA_11n(inst_data);
576 int4_t val = inst->VRegB_11n(inst_data);
577 shadow_frame.SetVReg(dst, val);
578 if (val == 0) {
579 shadow_frame.SetVRegReference(dst, nullptr);
580 }
581 inst = inst->Next_1xx();
582 }
583
584 ALWAYS_INLINE void CONST_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100585 uint8_t dst = inst->VRegA_21s(inst_data);
586 int16_t val = inst->VRegB_21s();
587 shadow_frame.SetVReg(dst, val);
588 if (val == 0) {
589 shadow_frame.SetVRegReference(dst, nullptr);
590 }
591 inst = inst->Next_2xx();
592 }
593
594 ALWAYS_INLINE void CONST() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100595 uint8_t dst = inst->VRegA_31i(inst_data);
596 int32_t val = inst->VRegB_31i();
597 shadow_frame.SetVReg(dst, val);
598 if (val == 0) {
599 shadow_frame.SetVRegReference(dst, nullptr);
600 }
601 inst = inst->Next_3xx();
602 }
603
604 ALWAYS_INLINE void CONST_HIGH16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100605 uint8_t dst = inst->VRegA_21h(inst_data);
606 int32_t val = static_cast<int32_t>(inst->VRegB_21h() << 16);
607 shadow_frame.SetVReg(dst, val);
608 if (val == 0) {
609 shadow_frame.SetVRegReference(dst, nullptr);
610 }
611 inst = inst->Next_2xx();
612 }
613
614 ALWAYS_INLINE void CONST_WIDE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100615 shadow_frame.SetVRegLong(inst->VRegA_21s(inst_data), inst->VRegB_21s());
616 inst = inst->Next_2xx();
617 }
618
619 ALWAYS_INLINE void CONST_WIDE_32() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100620 shadow_frame.SetVRegLong(inst->VRegA_31i(inst_data), inst->VRegB_31i());
621 inst = inst->Next_3xx();
622 }
623
624 ALWAYS_INLINE void CONST_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100625 shadow_frame.SetVRegLong(inst->VRegA_51l(inst_data), inst->VRegB_51l());
626 inst = inst->Next_51l();
627 }
628
629 ALWAYS_INLINE void CONST_WIDE_HIGH16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100630 shadow_frame.SetVRegLong(inst->VRegA_21h(inst_data),
631 static_cast<uint64_t>(inst->VRegB_21h()) << 48);
632 inst = inst->Next_2xx();
633 }
634
635 ALWAYS_INLINE void CONST_STRING() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100636 ObjPtr<mirror::String> s = ResolveString(self,
637 shadow_frame,
638 dex::StringIndex(inst->VRegB_21c()));
639 if (UNLIKELY(s == nullptr)) {
640 HANDLE_PENDING_EXCEPTION();
641 } else {
642 shadow_frame.SetVRegReference(inst->VRegA_21c(inst_data), s);
643 inst = inst->Next_2xx();
644 }
645 }
646
647 ALWAYS_INLINE void CONST_STRING_JUMBO() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100648 ObjPtr<mirror::String> s = ResolveString(self,
649 shadow_frame,
650 dex::StringIndex(inst->VRegB_31c()));
651 if (UNLIKELY(s == nullptr)) {
652 HANDLE_PENDING_EXCEPTION();
653 } else {
654 shadow_frame.SetVRegReference(inst->VRegA_31c(inst_data), s);
655 inst = inst->Next_3xx();
656 }
657 }
658
659 ALWAYS_INLINE void CONST_CLASS() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100660 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(inst->VRegB_21c()),
661 shadow_frame.GetMethod(),
662 self,
663 false,
664 do_access_check);
665 if (UNLIKELY(c == nullptr)) {
666 HANDLE_PENDING_EXCEPTION();
667 } else {
668 shadow_frame.SetVRegReference(inst->VRegA_21c(inst_data), c);
669 inst = inst->Next_2xx();
670 }
671 }
672
673 ALWAYS_INLINE void CONST_METHOD_HANDLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100674 ClassLinker* cl = Runtime::Current()->GetClassLinker();
675 ObjPtr<mirror::MethodHandle> mh = cl->ResolveMethodHandle(self,
676 inst->VRegB_21c(),
677 shadow_frame.GetMethod());
678 if (UNLIKELY(mh == nullptr)) {
679 HANDLE_PENDING_EXCEPTION();
680 } else {
681 shadow_frame.SetVRegReference(inst->VRegA_21c(inst_data), mh);
682 inst = inst->Next_2xx();
683 }
684 }
685
686 ALWAYS_INLINE void CONST_METHOD_TYPE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100687 ClassLinker* cl = Runtime::Current()->GetClassLinker();
688 ObjPtr<mirror::MethodType> mt = cl->ResolveMethodType(self,
689 dex::ProtoIndex(inst->VRegB_21c()),
690 shadow_frame.GetMethod());
691 if (UNLIKELY(mt == nullptr)) {
692 HANDLE_PENDING_EXCEPTION();
693 } else {
694 shadow_frame.SetVRegReference(inst->VRegA_21c(inst_data), mt);
695 inst = inst->Next_2xx();
696 }
697 }
698
699 ALWAYS_INLINE void MONITOR_ENTER() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000700 if (!HandleAsyncException()) {
701 return;
702 }
David Srbecky6da82472018-10-23 14:03:08 +0100703 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data));
704 if (UNLIKELY(obj == nullptr)) {
705 ThrowNullPointerExceptionFromInterpreter();
706 HANDLE_PENDING_EXCEPTION();
707 } else {
708 DoMonitorEnter<do_assignability_check>(self, &shadow_frame, obj);
709 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
710 }
711 }
712
713 ALWAYS_INLINE void MONITOR_EXIT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000714 if (!HandleAsyncException()) {
715 return;
716 }
David Srbecky6da82472018-10-23 14:03:08 +0100717 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data));
718 if (UNLIKELY(obj == nullptr)) {
719 ThrowNullPointerExceptionFromInterpreter();
720 HANDLE_PENDING_EXCEPTION();
721 } else {
722 DoMonitorExit<do_assignability_check>(self, &shadow_frame, obj);
723 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
724 }
725 }
726
727 ALWAYS_INLINE void CHECK_CAST() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100728 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(inst->VRegB_21c()),
729 shadow_frame.GetMethod(),
730 self,
731 false,
732 do_access_check);
733 if (UNLIKELY(c == nullptr)) {
734 HANDLE_PENDING_EXCEPTION();
735 } else {
736 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(inst->VRegA_21c(inst_data));
737 if (UNLIKELY(obj != nullptr && !obj->InstanceOf(c))) {
738 ThrowClassCastException(c, obj->GetClass());
739 HANDLE_PENDING_EXCEPTION();
740 } else {
741 inst = inst->Next_2xx();
742 }
743 }
744 }
745
746 ALWAYS_INLINE void INSTANCE_OF() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100747 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(inst->VRegC_22c()),
748 shadow_frame.GetMethod(),
749 self,
750 false,
751 do_access_check);
752 if (UNLIKELY(c == nullptr)) {
753 HANDLE_PENDING_EXCEPTION();
754 } else {
755 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
756 shadow_frame.SetVReg(inst->VRegA_22c(inst_data),
757 (obj != nullptr && obj->InstanceOf(c)) ? 1 : 0);
758 inst = inst->Next_2xx();
759 }
760 }
761
762 ALWAYS_INLINE void ARRAY_LENGTH() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100763 ObjPtr<mirror::Object> array = shadow_frame.GetVRegReference(inst->VRegB_12x(inst_data));
764 if (UNLIKELY(array == nullptr)) {
765 ThrowNullPointerExceptionFromInterpreter();
766 HANDLE_PENDING_EXCEPTION();
767 } else {
768 shadow_frame.SetVReg(inst->VRegA_12x(inst_data), array->AsArray()->GetLength());
769 inst = inst->Next_1xx();
770 }
771 }
772
773 ALWAYS_INLINE void NEW_INSTANCE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100774 ObjPtr<mirror::Object> obj = nullptr;
775 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(inst->VRegB_21c()),
776 shadow_frame.GetMethod(),
777 self,
778 false,
779 do_access_check);
780 if (LIKELY(c != nullptr)) {
781 if (UNLIKELY(c->IsStringClass())) {
782 gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
783 obj = mirror::String::AllocEmptyString<true>(self, allocator_type);
784 } else {
785 obj = AllocObjectFromCode<true>(
786 c.Ptr(),
787 self,
788 Runtime::Current()->GetHeap()->GetCurrentAllocator());
789 }
790 }
791 if (UNLIKELY(obj == nullptr)) {
792 HANDLE_PENDING_EXCEPTION();
793 } else {
794 obj->GetClass()->AssertInitializedOrInitializingInThread(self);
795 // Don't allow finalizable objects to be allocated during a transaction since these can't
796 // be finalized without a started runtime.
797 if (transaction_active && obj->GetClass()->IsFinalizable()) {
798 AbortTransactionF(self, "Allocating finalizable object in transaction: %s",
799 obj->PrettyTypeOf().c_str());
800 HANDLE_PENDING_EXCEPTION();
801 }
802 shadow_frame.SetVRegReference(inst->VRegA_21c(inst_data), obj);
803 inst = inst->Next_2xx();
804 }
805 }
806
807 ALWAYS_INLINE void NEW_ARRAY() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100808 int32_t length = shadow_frame.GetVReg(inst->VRegB_22c(inst_data));
809 ObjPtr<mirror::Object> obj = AllocArrayFromCode<do_access_check, true>(
810 dex::TypeIndex(inst->VRegC_22c()),
811 length,
812 shadow_frame.GetMethod(),
813 self,
814 Runtime::Current()->GetHeap()->GetCurrentAllocator());
815 if (UNLIKELY(obj == nullptr)) {
816 HANDLE_PENDING_EXCEPTION();
817 } else {
818 shadow_frame.SetVRegReference(inst->VRegA_22c(inst_data), obj);
819 inst = inst->Next_2xx();
820 }
821 }
822
823 ALWAYS_INLINE void FILLED_NEW_ARRAY() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100824 bool success =
825 DoFilledNewArray<false, do_access_check, transaction_active>(inst, shadow_frame, self,
826 ResultRegister());
827 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
828 }
829
830 ALWAYS_INLINE void FILLED_NEW_ARRAY_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100831 bool success =
832 DoFilledNewArray<true, do_access_check, transaction_active>(inst, shadow_frame,
833 self, ResultRegister());
834 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
835 }
836
837 ALWAYS_INLINE void FILL_ARRAY_DATA() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100838 const uint16_t* payload_addr = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
839 const Instruction::ArrayDataPayload* payload =
840 reinterpret_cast<const Instruction::ArrayDataPayload*>(payload_addr);
841 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(inst->VRegA_31t(inst_data));
842 bool success = FillArrayData(obj, payload);
843 if (!success) {
844 HANDLE_PENDING_EXCEPTION();
845 }
846 if (transaction_active) {
847 RecordArrayElementsInTransaction(obj->AsArray(), payload->element_count);
848 }
849 inst = inst->Next_3xx();
850 }
851
852 ALWAYS_INLINE void THROW() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000853 if (!HandleAsyncException()) {
854 return;
855 }
David Srbecky6da82472018-10-23 14:03:08 +0100856 ObjPtr<mirror::Object> exception =
857 shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data));
858 if (UNLIKELY(exception == nullptr)) {
859 ThrowNullPointerException("throw with null exception");
860 } else if (do_assignability_check && !exception->GetClass()->IsThrowableClass()) {
861 // This should never happen.
862 std::string temp;
863 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
864 "Throwing '%s' that is not instance of Throwable",
865 exception->GetClass()->GetDescriptor(&temp));
866 } else {
867 self->SetException(exception->AsThrowable());
868 }
869 HANDLE_PENDING_EXCEPTION();
870 }
871
872 ALWAYS_INLINE void GOTO() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000873 if (!HandleAsyncException()) {
874 return;
875 }
David Srbecky6da82472018-10-23 14:03:08 +0100876 int8_t offset = inst->VRegA_10t(inst_data);
877 BRANCH_INSTRUMENTATION(offset);
878 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +0000879 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +0100880 }
881
882 ALWAYS_INLINE void GOTO_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000883 if (!HandleAsyncException()) {
884 return;
885 }
David Srbecky6da82472018-10-23 14:03:08 +0100886 int16_t offset = inst->VRegA_20t();
887 BRANCH_INSTRUMENTATION(offset);
888 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +0000889 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +0100890 }
891
892 ALWAYS_INLINE void GOTO_32() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000893 if (!HandleAsyncException()) {
894 return;
895 }
David Srbecky6da82472018-10-23 14:03:08 +0100896 int32_t offset = inst->VRegA_30t();
897 BRANCH_INSTRUMENTATION(offset);
898 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +0000899 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +0100900 }
901
902 ALWAYS_INLINE void PACKED_SWITCH() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100903 int32_t offset = DoPackedSwitch(inst, shadow_frame, inst_data);
904 BRANCH_INSTRUMENTATION(offset);
905 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +0000906 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +0100907 }
908
909 ALWAYS_INLINE void SPARSE_SWITCH() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100910 int32_t offset = DoSparseSwitch(inst, shadow_frame, inst_data);
911 BRANCH_INSTRUMENTATION(offset);
912 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +0000913 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +0100914 }
915
916#pragma clang diagnostic push
917#pragma clang diagnostic ignored "-Wfloat-equal"
918
919
920 ALWAYS_INLINE void CMPL_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100921 float val1 = shadow_frame.GetVRegFloat(inst->VRegB_23x());
922 float val2 = shadow_frame.GetVRegFloat(inst->VRegC_23x());
923 int32_t result;
924 if (val1 > val2) {
925 result = 1;
926 } else if (val1 == val2) {
927 result = 0;
928 } else {
929 result = -1;
930 }
931 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), result);
932 inst = inst->Next_2xx();
933 }
934
935 ALWAYS_INLINE void CMPG_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100936 float val1 = shadow_frame.GetVRegFloat(inst->VRegB_23x());
937 float val2 = shadow_frame.GetVRegFloat(inst->VRegC_23x());
938 int32_t result;
939 if (val1 < val2) {
940 result = -1;
941 } else if (val1 == val2) {
942 result = 0;
943 } else {
944 result = 1;
945 }
946 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), result);
947 inst = inst->Next_2xx();
948 }
949
950 ALWAYS_INLINE void CMPL_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100951 double val1 = shadow_frame.GetVRegDouble(inst->VRegB_23x());
952 double val2 = shadow_frame.GetVRegDouble(inst->VRegC_23x());
953 int32_t result;
954 if (val1 > val2) {
955 result = 1;
956 } else if (val1 == val2) {
957 result = 0;
958 } else {
959 result = -1;
960 }
961 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), result);
962 inst = inst->Next_2xx();
963 }
964
965
966 ALWAYS_INLINE void CMPG_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100967 double val1 = shadow_frame.GetVRegDouble(inst->VRegB_23x());
968 double val2 = shadow_frame.GetVRegDouble(inst->VRegC_23x());
969 int32_t result;
970 if (val1 < val2) {
971 result = -1;
972 } else if (val1 == val2) {
973 result = 0;
974 } else {
975 result = 1;
976 }
977 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), result);
978 inst = inst->Next_2xx();
979 }
980
981#pragma clang diagnostic pop
982
983
984 ALWAYS_INLINE void CMP_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100985 int64_t val1 = shadow_frame.GetVRegLong(inst->VRegB_23x());
986 int64_t val2 = shadow_frame.GetVRegLong(inst->VRegC_23x());
987 int32_t result;
988 if (val1 > val2) {
989 result = 1;
990 } else if (val1 == val2) {
991 result = 0;
992 } else {
993 result = -1;
994 }
995 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), result);
996 inst = inst->Next_2xx();
997 }
998
999 ALWAYS_INLINE void IF_EQ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001000 if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) ==
1001 shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
1002 int16_t offset = inst->VRegC_22t();
1003 BRANCH_INSTRUMENTATION(offset);
1004 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001005 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001006 } else {
1007 BRANCH_INSTRUMENTATION(2);
1008 inst = inst->Next_2xx();
1009 }
1010 }
1011
1012 ALWAYS_INLINE void IF_NE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001013 if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) !=
1014 shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
1015 int16_t offset = inst->VRegC_22t();
1016 BRANCH_INSTRUMENTATION(offset);
1017 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001018 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001019 } else {
1020 BRANCH_INSTRUMENTATION(2);
1021 inst = inst->Next_2xx();
1022 }
1023 }
1024
1025 ALWAYS_INLINE void IF_LT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001026 if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) <
1027 shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
1028 int16_t offset = inst->VRegC_22t();
1029 BRANCH_INSTRUMENTATION(offset);
1030 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001031 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001032 } else {
1033 BRANCH_INSTRUMENTATION(2);
1034 inst = inst->Next_2xx();
1035 }
1036 }
1037
1038 ALWAYS_INLINE void IF_GE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001039 if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) >=
1040 shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
1041 int16_t offset = inst->VRegC_22t();
1042 BRANCH_INSTRUMENTATION(offset);
1043 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001044 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001045 } else {
1046 BRANCH_INSTRUMENTATION(2);
1047 inst = inst->Next_2xx();
1048 }
1049 }
1050
1051 ALWAYS_INLINE void IF_GT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001052 if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) >
1053 shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
1054 int16_t offset = inst->VRegC_22t();
1055 BRANCH_INSTRUMENTATION(offset);
1056 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001057 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001058 } else {
1059 BRANCH_INSTRUMENTATION(2);
1060 inst = inst->Next_2xx();
1061 }
1062 }
1063
1064 ALWAYS_INLINE void IF_LE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001065 if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) <=
1066 shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
1067 int16_t offset = inst->VRegC_22t();
1068 BRANCH_INSTRUMENTATION(offset);
1069 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001070 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001071 } else {
1072 BRANCH_INSTRUMENTATION(2);
1073 inst = inst->Next_2xx();
1074 }
1075 }
1076
1077 ALWAYS_INLINE void IF_EQZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001078 if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) == 0) {
1079 int16_t offset = inst->VRegB_21t();
1080 BRANCH_INSTRUMENTATION(offset);
1081 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001082 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001083 } else {
1084 BRANCH_INSTRUMENTATION(2);
1085 inst = inst->Next_2xx();
1086 }
1087 }
1088
1089 ALWAYS_INLINE void IF_NEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001090 if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) != 0) {
1091 int16_t offset = inst->VRegB_21t();
1092 BRANCH_INSTRUMENTATION(offset);
1093 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001094 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001095 } else {
1096 BRANCH_INSTRUMENTATION(2);
1097 inst = inst->Next_2xx();
1098 }
1099 }
1100
1101 ALWAYS_INLINE void IF_LTZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001102 if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) < 0) {
1103 int16_t offset = inst->VRegB_21t();
1104 BRANCH_INSTRUMENTATION(offset);
1105 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001106 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001107 } else {
1108 BRANCH_INSTRUMENTATION(2);
1109 inst = inst->Next_2xx();
1110 }
1111 }
1112
1113 ALWAYS_INLINE void IF_GEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001114 if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) >= 0) {
1115 int16_t offset = inst->VRegB_21t();
1116 BRANCH_INSTRUMENTATION(offset);
1117 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001118 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001119 } else {
1120 BRANCH_INSTRUMENTATION(2);
1121 inst = inst->Next_2xx();
1122 }
1123 }
1124
1125 ALWAYS_INLINE void IF_GTZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001126 if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) > 0) {
1127 int16_t offset = inst->VRegB_21t();
1128 BRANCH_INSTRUMENTATION(offset);
1129 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001130 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001131 } else {
1132 BRANCH_INSTRUMENTATION(2);
1133 inst = inst->Next_2xx();
1134 }
1135 }
1136
1137 ALWAYS_INLINE void IF_LEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001138 if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) <= 0) {
1139 int16_t offset = inst->VRegB_21t();
1140 BRANCH_INSTRUMENTATION(offset);
1141 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001142 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001143 } else {
1144 BRANCH_INSTRUMENTATION(2);
1145 inst = inst->Next_2xx();
1146 }
1147 }
1148
1149 ALWAYS_INLINE void AGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001150 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1151 if (UNLIKELY(a == nullptr)) {
1152 ThrowNullPointerExceptionFromInterpreter();
1153 HANDLE_PENDING_EXCEPTION();
1154 }
1155 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1156 ObjPtr<mirror::BooleanArray> array = a->AsBooleanArray();
1157 if (array->CheckIsValidIndex(index)) {
1158 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
1159 inst = inst->Next_2xx();
1160 } else {
1161 HANDLE_PENDING_EXCEPTION();
1162 }
1163 }
1164
1165 ALWAYS_INLINE void AGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001166 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1167 if (UNLIKELY(a == nullptr)) {
1168 ThrowNullPointerExceptionFromInterpreter();
1169 HANDLE_PENDING_EXCEPTION();
1170 }
1171 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1172 ObjPtr<mirror::ByteArray> array = a->AsByteArray();
1173 if (array->CheckIsValidIndex(index)) {
1174 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
1175 inst = inst->Next_2xx();
1176 } else {
1177 HANDLE_PENDING_EXCEPTION();
1178 }
1179 }
1180
1181 ALWAYS_INLINE void AGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001182 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1183 if (UNLIKELY(a == nullptr)) {
1184 ThrowNullPointerExceptionFromInterpreter();
1185 HANDLE_PENDING_EXCEPTION();
1186 }
1187 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1188 ObjPtr<mirror::CharArray> array = a->AsCharArray();
1189 if (array->CheckIsValidIndex(index)) {
1190 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
1191 inst = inst->Next_2xx();
1192 } else {
1193 HANDLE_PENDING_EXCEPTION();
1194 }
1195 }
1196
1197 ALWAYS_INLINE void AGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001198 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1199 if (UNLIKELY(a == nullptr)) {
1200 ThrowNullPointerExceptionFromInterpreter();
1201 HANDLE_PENDING_EXCEPTION();
1202 }
1203 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1204 ObjPtr<mirror::ShortArray> array = a->AsShortArray();
1205 if (array->CheckIsValidIndex(index)) {
1206 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
1207 inst = inst->Next_2xx();
1208 } else {
1209 HANDLE_PENDING_EXCEPTION();
1210 }
1211 }
1212
1213 ALWAYS_INLINE void AGET() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001214 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1215 if (UNLIKELY(a == nullptr)) {
1216 ThrowNullPointerExceptionFromInterpreter();
1217 HANDLE_PENDING_EXCEPTION();
1218 }
1219 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1220 DCHECK(a->IsIntArray() || a->IsFloatArray()) << a->PrettyTypeOf();
1221 ObjPtr<mirror::IntArray> array = ObjPtr<mirror::IntArray>::DownCast(a);
1222 if (array->CheckIsValidIndex(index)) {
1223 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
1224 inst = inst->Next_2xx();
1225 } else {
1226 HANDLE_PENDING_EXCEPTION();
1227 }
1228 }
1229
1230 ALWAYS_INLINE void AGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001231 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1232 if (UNLIKELY(a == nullptr)) {
1233 ThrowNullPointerExceptionFromInterpreter();
1234 HANDLE_PENDING_EXCEPTION();
1235 }
1236 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1237 DCHECK(a->IsLongArray() || a->IsDoubleArray()) << a->PrettyTypeOf();
1238 ObjPtr<mirror::LongArray> array = ObjPtr<mirror::LongArray>::DownCast(a);
1239 if (array->CheckIsValidIndex(index)) {
1240 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
1241 inst = inst->Next_2xx();
1242 } else {
1243 HANDLE_PENDING_EXCEPTION();
1244 }
1245 }
1246
1247 ALWAYS_INLINE void AGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001248 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1249 if (UNLIKELY(a == nullptr)) {
1250 ThrowNullPointerExceptionFromInterpreter();
1251 HANDLE_PENDING_EXCEPTION();
1252 }
1253 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1254 ObjPtr<mirror::ObjectArray<mirror::Object>> array = a->AsObjectArray<mirror::Object>();
1255 if (array->CheckIsValidIndex(index)) {
1256 shadow_frame.SetVRegReference(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
1257 inst = inst->Next_2xx();
1258 } else {
1259 HANDLE_PENDING_EXCEPTION();
1260 }
1261 }
1262
1263 ALWAYS_INLINE void APUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001264 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1265 if (UNLIKELY(a == nullptr)) {
1266 ThrowNullPointerExceptionFromInterpreter();
1267 HANDLE_PENDING_EXCEPTION();
1268 }
1269 uint8_t val = shadow_frame.GetVReg(inst->VRegA_23x(inst_data));
1270 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1271 ObjPtr<mirror::BooleanArray> array = a->AsBooleanArray();
1272 if (array->CheckIsValidIndex(index)) {
1273 array->SetWithoutChecks<transaction_active>(index, val);
1274 inst = inst->Next_2xx();
1275 } else {
1276 HANDLE_PENDING_EXCEPTION();
1277 }
1278 }
1279
1280 ALWAYS_INLINE void APUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001281 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1282 if (UNLIKELY(a == nullptr)) {
1283 ThrowNullPointerExceptionFromInterpreter();
1284 HANDLE_PENDING_EXCEPTION();
1285 }
1286 int8_t val = shadow_frame.GetVReg(inst->VRegA_23x(inst_data));
1287 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1288 ObjPtr<mirror::ByteArray> array = a->AsByteArray();
1289 if (array->CheckIsValidIndex(index)) {
1290 array->SetWithoutChecks<transaction_active>(index, val);
1291 inst = inst->Next_2xx();
1292 } else {
1293 HANDLE_PENDING_EXCEPTION();
1294 }
1295 }
1296
1297 ALWAYS_INLINE void APUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001298 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1299 if (UNLIKELY(a == nullptr)) {
1300 ThrowNullPointerExceptionFromInterpreter();
1301 HANDLE_PENDING_EXCEPTION();
1302 }
1303 uint16_t val = shadow_frame.GetVReg(inst->VRegA_23x(inst_data));
1304 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1305 ObjPtr<mirror::CharArray> array = a->AsCharArray();
1306 if (array->CheckIsValidIndex(index)) {
1307 array->SetWithoutChecks<transaction_active>(index, val);
1308 inst = inst->Next_2xx();
1309 } else {
1310 HANDLE_PENDING_EXCEPTION();
1311 }
1312 }
1313
1314 ALWAYS_INLINE void APUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001315 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1316 if (UNLIKELY(a == nullptr)) {
1317 ThrowNullPointerExceptionFromInterpreter();
1318 HANDLE_PENDING_EXCEPTION();
1319 }
1320 int16_t val = shadow_frame.GetVReg(inst->VRegA_23x(inst_data));
1321 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1322 ObjPtr<mirror::ShortArray> array = a->AsShortArray();
1323 if (array->CheckIsValidIndex(index)) {
1324 array->SetWithoutChecks<transaction_active>(index, val);
1325 inst = inst->Next_2xx();
1326 } else {
1327 HANDLE_PENDING_EXCEPTION();
1328 }
1329 }
1330
1331 ALWAYS_INLINE void APUT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001332 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1333 if (UNLIKELY(a == nullptr)) {
1334 ThrowNullPointerExceptionFromInterpreter();
1335 HANDLE_PENDING_EXCEPTION();
1336 }
1337 int32_t val = shadow_frame.GetVReg(inst->VRegA_23x(inst_data));
1338 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1339 DCHECK(a->IsIntArray() || a->IsFloatArray()) << a->PrettyTypeOf();
1340 ObjPtr<mirror::IntArray> array = ObjPtr<mirror::IntArray>::DownCast(a);
1341 if (array->CheckIsValidIndex(index)) {
1342 array->SetWithoutChecks<transaction_active>(index, val);
1343 inst = inst->Next_2xx();
1344 } else {
1345 HANDLE_PENDING_EXCEPTION();
1346 }
1347 }
1348
1349 ALWAYS_INLINE void APUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001350 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1351 if (UNLIKELY(a == nullptr)) {
1352 ThrowNullPointerExceptionFromInterpreter();
1353 HANDLE_PENDING_EXCEPTION();
1354 }
1355 int64_t val = shadow_frame.GetVRegLong(inst->VRegA_23x(inst_data));
1356 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1357 DCHECK(a->IsLongArray() || a->IsDoubleArray()) << a->PrettyTypeOf();
1358 ObjPtr<mirror::LongArray> array = ObjPtr<mirror::LongArray>::DownCast(a);
1359 if (array->CheckIsValidIndex(index)) {
1360 array->SetWithoutChecks<transaction_active>(index, val);
1361 inst = inst->Next_2xx();
1362 } else {
1363 HANDLE_PENDING_EXCEPTION();
1364 }
1365 }
1366
1367 ALWAYS_INLINE void APUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001368 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1369 if (UNLIKELY(a == nullptr)) {
1370 ThrowNullPointerExceptionFromInterpreter();
1371 HANDLE_PENDING_EXCEPTION();
1372 }
1373 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1374 ObjPtr<mirror::Object> val = shadow_frame.GetVRegReference(inst->VRegA_23x(inst_data));
1375 ObjPtr<mirror::ObjectArray<mirror::Object>> array = a->AsObjectArray<mirror::Object>();
1376 if (array->CheckIsValidIndex(index) && array->CheckAssignable(val)) {
1377 array->SetWithoutChecks<transaction_active>(index, val);
1378 inst = inst->Next_2xx();
1379 } else {
1380 HANDLE_PENDING_EXCEPTION();
1381 }
1382 }
1383
1384 ALWAYS_INLINE void IGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001385 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimBoolean, do_access_check>(
1386 self, shadow_frame, inst, inst_data);
1387 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1388 }
1389
1390 ALWAYS_INLINE void IGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001391 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimByte, do_access_check>(
1392 self, shadow_frame, inst, inst_data);
1393 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1394 }
1395
1396 ALWAYS_INLINE void IGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001397 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimChar, do_access_check>(
1398 self, shadow_frame, inst, inst_data);
1399 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1400 }
1401
1402 ALWAYS_INLINE void IGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001403 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimShort, do_access_check>(
1404 self, shadow_frame, inst, inst_data);
1405 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1406 }
1407
1408 ALWAYS_INLINE void IGET() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001409 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimInt, do_access_check>(
1410 self, shadow_frame, inst, inst_data);
1411 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1412 }
1413
1414 ALWAYS_INLINE void IGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001415 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimLong, do_access_check>(
1416 self, shadow_frame, inst, inst_data);
1417 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1418 }
1419
1420 ALWAYS_INLINE void IGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001421 bool success = DoFieldGet<InstanceObjectRead, Primitive::kPrimNot, do_access_check>(
1422 self, shadow_frame, inst, inst_data);
1423 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1424 }
1425
1426 ALWAYS_INLINE void IGET_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001427 bool success = DoIGetQuick<Primitive::kPrimInt>(shadow_frame, inst, inst_data);
1428 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1429 }
1430
1431 ALWAYS_INLINE void IGET_WIDE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001432 bool success = DoIGetQuick<Primitive::kPrimLong>(shadow_frame, inst, inst_data);
1433 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1434 }
1435
1436 ALWAYS_INLINE void IGET_OBJECT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001437 bool success = DoIGetQuick<Primitive::kPrimNot>(shadow_frame, inst, inst_data);
1438 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1439 }
1440
1441 ALWAYS_INLINE void IGET_BOOLEAN_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001442 bool success = DoIGetQuick<Primitive::kPrimBoolean>(shadow_frame, inst, inst_data);
1443 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1444 }
1445
1446 ALWAYS_INLINE void IGET_BYTE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001447 bool success = DoIGetQuick<Primitive::kPrimByte>(shadow_frame, inst, inst_data);
1448 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1449 }
1450
1451 ALWAYS_INLINE void IGET_CHAR_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001452 bool success = DoIGetQuick<Primitive::kPrimChar>(shadow_frame, inst, inst_data);
1453 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1454 }
1455
1456 ALWAYS_INLINE void IGET_SHORT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001457 bool success = DoIGetQuick<Primitive::kPrimShort>(shadow_frame, inst, inst_data);
1458 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1459 }
1460
1461 ALWAYS_INLINE void SGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001462 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimBoolean, do_access_check,
1463 transaction_active>(self, shadow_frame, inst, inst_data);
1464 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1465 }
1466
1467 ALWAYS_INLINE void SGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001468 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimByte, do_access_check,
1469 transaction_active>(self, shadow_frame, inst, inst_data);
1470 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1471 }
1472
1473 ALWAYS_INLINE void SGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001474 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimChar, do_access_check,
1475 transaction_active>(self, shadow_frame, inst, inst_data);
1476 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1477 }
1478
1479 ALWAYS_INLINE void SGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001480 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimShort, do_access_check,
1481 transaction_active>(self, shadow_frame, inst, inst_data);
1482 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1483 }
1484
1485 ALWAYS_INLINE void SGET() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001486 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimInt, do_access_check,
1487 transaction_active>(self, shadow_frame, inst, inst_data);
1488 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1489 }
1490
1491 ALWAYS_INLINE void SGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001492 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimLong, do_access_check,
1493 transaction_active>(self, shadow_frame, inst, inst_data);
1494 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1495 }
1496
1497 ALWAYS_INLINE void SGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001498 bool success = DoFieldGet<StaticObjectRead, Primitive::kPrimNot, do_access_check,
1499 transaction_active>(self, shadow_frame, inst, inst_data);
1500 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1501 }
1502
1503 ALWAYS_INLINE void IPUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001504 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimBoolean, do_access_check,
1505 transaction_active>(self, shadow_frame, inst, inst_data);
1506 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1507 }
1508
1509 ALWAYS_INLINE void IPUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001510 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimByte, do_access_check,
1511 transaction_active>(self, shadow_frame, inst, inst_data);
1512 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1513 }
1514
1515 ALWAYS_INLINE void IPUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001516 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimChar, do_access_check,
1517 transaction_active>(self, shadow_frame, inst, inst_data);
1518 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1519 }
1520
1521 ALWAYS_INLINE void IPUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001522 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimShort, do_access_check,
1523 transaction_active>(self, shadow_frame, inst, inst_data);
1524 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1525 }
1526
1527 ALWAYS_INLINE void IPUT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001528 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimInt, do_access_check,
1529 transaction_active>(self, shadow_frame, inst, inst_data);
1530 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1531 }
1532
1533 ALWAYS_INLINE void IPUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001534 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimLong, do_access_check,
1535 transaction_active>(self, shadow_frame, inst, inst_data);
1536 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1537 }
1538
1539 ALWAYS_INLINE void IPUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001540 bool success = DoFieldPut<InstanceObjectWrite, Primitive::kPrimNot, do_access_check,
1541 transaction_active>(self, shadow_frame, inst, inst_data);
1542 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1543 }
1544
1545 ALWAYS_INLINE void IPUT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001546 bool success = DoIPutQuick<Primitive::kPrimInt, transaction_active>(
1547 shadow_frame, inst, inst_data);
1548 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1549 }
1550
1551 ALWAYS_INLINE void IPUT_BOOLEAN_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001552 bool success = DoIPutQuick<Primitive::kPrimBoolean, transaction_active>(
1553 shadow_frame, inst, inst_data);
1554 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1555 }
1556
1557 ALWAYS_INLINE void IPUT_BYTE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001558 bool success = DoIPutQuick<Primitive::kPrimByte, transaction_active>(
1559 shadow_frame, inst, inst_data);
1560 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1561 }
1562
1563 ALWAYS_INLINE void IPUT_CHAR_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001564 bool success = DoIPutQuick<Primitive::kPrimChar, transaction_active>(
1565 shadow_frame, inst, inst_data);
1566 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1567 }
1568
1569 ALWAYS_INLINE void IPUT_SHORT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001570 bool success = DoIPutQuick<Primitive::kPrimShort, transaction_active>(
1571 shadow_frame, inst, inst_data);
1572 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1573 }
1574
1575 ALWAYS_INLINE void IPUT_WIDE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001576 bool success = DoIPutQuick<Primitive::kPrimLong, transaction_active>(
1577 shadow_frame, inst, inst_data);
1578 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1579 }
1580
1581 ALWAYS_INLINE void IPUT_OBJECT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001582 bool success = DoIPutQuick<Primitive::kPrimNot, transaction_active>(
1583 shadow_frame, inst, inst_data);
1584 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1585 }
1586
1587 ALWAYS_INLINE void SPUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001588 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimBoolean, do_access_check,
1589 transaction_active>(self, shadow_frame, inst, inst_data);
1590 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1591 }
1592
1593 ALWAYS_INLINE void SPUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001594 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimByte, do_access_check,
1595 transaction_active>(self, shadow_frame, inst, inst_data);
1596 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1597 }
1598
1599 ALWAYS_INLINE void SPUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001600 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimChar, do_access_check,
1601 transaction_active>(self, shadow_frame, inst, inst_data);
1602 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1603 }
1604
1605 ALWAYS_INLINE void SPUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001606 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimShort, do_access_check,
1607 transaction_active>(self, shadow_frame, inst, inst_data);
1608 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1609 }
1610
1611 ALWAYS_INLINE void SPUT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001612 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimInt, do_access_check,
1613 transaction_active>(self, shadow_frame, inst, inst_data);
1614 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1615 }
1616
1617 ALWAYS_INLINE void SPUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001618 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimLong, do_access_check,
1619 transaction_active>(self, shadow_frame, inst, inst_data);
1620 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1621 }
1622
1623 ALWAYS_INLINE void SPUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001624 bool success = DoFieldPut<StaticObjectWrite, Primitive::kPrimNot, do_access_check,
1625 transaction_active>(self, shadow_frame, inst, inst_data);
1626 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1627 }
1628
1629 ALWAYS_INLINE void INVOKE_VIRTUAL() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001630 bool success = DoInvoke<kVirtual, false, do_access_check, /*is_mterp=*/ false>(
1631 self, shadow_frame, inst, inst_data, ResultRegister());
1632 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1633 }
1634
1635 ALWAYS_INLINE void INVOKE_VIRTUAL_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001636 bool success = DoInvoke<kVirtual, true, do_access_check, /*is_mterp=*/ false>(
1637 self, shadow_frame, inst, inst_data, ResultRegister());
1638 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1639 }
1640
1641 ALWAYS_INLINE void INVOKE_SUPER() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001642 bool success = DoInvoke<kSuper, false, do_access_check, /*is_mterp=*/ false>(
1643 self, shadow_frame, inst, inst_data, ResultRegister());
1644 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1645 }
1646
1647 ALWAYS_INLINE void INVOKE_SUPER_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001648 bool success = DoInvoke<kSuper, true, do_access_check, /*is_mterp=*/ false>(
1649 self, shadow_frame, inst, inst_data, ResultRegister());
1650 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1651 }
1652
1653 ALWAYS_INLINE void INVOKE_DIRECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001654 bool success = DoInvoke<kDirect, false, do_access_check, /*is_mterp=*/ false>(
1655 self, shadow_frame, inst, inst_data, ResultRegister());
1656 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1657 }
1658
1659 ALWAYS_INLINE void INVOKE_DIRECT_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001660 bool success = DoInvoke<kDirect, true, do_access_check, /*is_mterp=*/ false>(
1661 self, shadow_frame, inst, inst_data, ResultRegister());
1662 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1663 }
1664
1665 ALWAYS_INLINE void INVOKE_INTERFACE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001666 bool success = DoInvoke<kInterface, false, do_access_check, /*is_mterp=*/ false>(
1667 self, shadow_frame, inst, inst_data, ResultRegister());
1668 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1669 }
1670
1671 ALWAYS_INLINE void INVOKE_INTERFACE_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001672 bool success = DoInvoke<kInterface, true, do_access_check, /*is_mterp=*/ false>(
1673 self, shadow_frame, inst, inst_data, ResultRegister());
1674 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1675 }
1676
1677 ALWAYS_INLINE void INVOKE_STATIC() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001678 bool success = DoInvoke<kStatic, false, do_access_check, /*is_mterp=*/ false>(
1679 self, shadow_frame, inst, inst_data, ResultRegister());
1680 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1681 }
1682
1683 ALWAYS_INLINE void INVOKE_STATIC_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001684 bool success = DoInvoke<kStatic, true, do_access_check, /*is_mterp=*/ false>(
1685 self, shadow_frame, inst, inst_data, ResultRegister());
1686 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1687 }
1688
1689 ALWAYS_INLINE void INVOKE_VIRTUAL_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001690 bool success = DoInvoke<kVirtual, false, do_access_check, /*is_mterp=*/ false,
1691 /*is_quick=*/ true>(self, shadow_frame, inst, inst_data, ResultRegister());
1692 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1693 }
1694
1695 ALWAYS_INLINE void INVOKE_VIRTUAL_RANGE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001696 bool success = DoInvoke<kVirtual, true, do_access_check, /*is_mterp=*/ false,
1697 /*is_quick=*/ true>(self, shadow_frame, inst, inst_data, ResultRegister());
1698 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1699 }
1700
1701 ALWAYS_INLINE void INVOKE_POLYMORPHIC() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001702 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1703 bool success = DoInvokePolymorphic</* is_range= */ false>(
1704 self, shadow_frame, inst, inst_data, ResultRegister());
1705 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(!success);
1706 }
1707
1708 ALWAYS_INLINE void INVOKE_POLYMORPHIC_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001709 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1710 bool success = DoInvokePolymorphic</* is_range= */ true>(
1711 self, shadow_frame, inst, inst_data, ResultRegister());
1712 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(!success);
1713 }
1714
1715 ALWAYS_INLINE void INVOKE_CUSTOM() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001716 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1717 bool success = DoInvokeCustom</* is_range= */ false>(
1718 self, shadow_frame, inst, inst_data, ResultRegister());
1719 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1720 }
1721
1722 ALWAYS_INLINE void INVOKE_CUSTOM_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001723 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1724 bool success = DoInvokeCustom</* is_range= */ true>(
1725 self, shadow_frame, inst, inst_data, ResultRegister());
1726 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1727 }
1728
1729 ALWAYS_INLINE void NEG_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001730 shadow_frame.SetVReg(
1731 inst->VRegA_12x(inst_data), -shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
1732 inst = inst->Next_1xx();
1733 }
1734
1735 ALWAYS_INLINE void NOT_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001736 shadow_frame.SetVReg(
1737 inst->VRegA_12x(inst_data), ~shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
1738 inst = inst->Next_1xx();
1739 }
1740
1741 ALWAYS_INLINE void NEG_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001742 shadow_frame.SetVRegLong(
1743 inst->VRegA_12x(inst_data), -shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
1744 inst = inst->Next_1xx();
1745 }
1746
1747 ALWAYS_INLINE void NOT_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001748 shadow_frame.SetVRegLong(
1749 inst->VRegA_12x(inst_data), ~shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
1750 inst = inst->Next_1xx();
1751 }
1752
1753 ALWAYS_INLINE void NEG_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001754 shadow_frame.SetVRegFloat(
1755 inst->VRegA_12x(inst_data), -shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
1756 inst = inst->Next_1xx();
1757 }
1758
1759 ALWAYS_INLINE void NEG_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001760 shadow_frame.SetVRegDouble(
1761 inst->VRegA_12x(inst_data), -shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
1762 inst = inst->Next_1xx();
1763 }
1764
1765 ALWAYS_INLINE void INT_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001766 shadow_frame.SetVRegLong(inst->VRegA_12x(inst_data),
1767 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
1768 inst = inst->Next_1xx();
1769 }
1770
1771 ALWAYS_INLINE void INT_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001772 shadow_frame.SetVRegFloat(inst->VRegA_12x(inst_data),
1773 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
1774 inst = inst->Next_1xx();
1775 }
1776
1777 ALWAYS_INLINE void INT_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001778 shadow_frame.SetVRegDouble(inst->VRegA_12x(inst_data),
1779 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
1780 inst = inst->Next_1xx();
1781 }
1782
1783 ALWAYS_INLINE void LONG_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001784 shadow_frame.SetVReg(inst->VRegA_12x(inst_data),
1785 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
1786 inst = inst->Next_1xx();
1787 }
1788
1789 ALWAYS_INLINE void LONG_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001790 shadow_frame.SetVRegFloat(inst->VRegA_12x(inst_data),
1791 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
1792 inst = inst->Next_1xx();
1793 }
1794
1795 ALWAYS_INLINE void LONG_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001796 shadow_frame.SetVRegDouble(inst->VRegA_12x(inst_data),
1797 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
1798 inst = inst->Next_1xx();
1799 }
1800
1801 ALWAYS_INLINE void FLOAT_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001802 float val = shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data));
1803 int32_t result = art_float_to_integral<int32_t, float>(val);
1804 shadow_frame.SetVReg(inst->VRegA_12x(inst_data), result);
1805 inst = inst->Next_1xx();
1806 }
1807
1808 ALWAYS_INLINE void FLOAT_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001809 float val = shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data));
1810 int64_t result = art_float_to_integral<int64_t, float>(val);
1811 shadow_frame.SetVRegLong(inst->VRegA_12x(inst_data), result);
1812 inst = inst->Next_1xx();
1813 }
1814
1815 ALWAYS_INLINE void FLOAT_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001816 shadow_frame.SetVRegDouble(inst->VRegA_12x(inst_data),
1817 shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
1818 inst = inst->Next_1xx();
1819 }
1820
1821 ALWAYS_INLINE void DOUBLE_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001822 double val = shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data));
1823 int32_t result = art_float_to_integral<int32_t, double>(val);
1824 shadow_frame.SetVReg(inst->VRegA_12x(inst_data), result);
1825 inst = inst->Next_1xx();
1826 }
1827
1828 ALWAYS_INLINE void DOUBLE_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001829 double val = shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data));
1830 int64_t result = art_float_to_integral<int64_t, double>(val);
1831 shadow_frame.SetVRegLong(inst->VRegA_12x(inst_data), result);
1832 inst = inst->Next_1xx();
1833 }
1834
1835 ALWAYS_INLINE void DOUBLE_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001836 shadow_frame.SetVRegFloat(inst->VRegA_12x(inst_data),
1837 shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
1838 inst = inst->Next_1xx();
1839 }
1840
1841 ALWAYS_INLINE void INT_TO_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001842 shadow_frame.SetVReg(inst->VRegA_12x(inst_data), static_cast<int8_t>(
1843 shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
1844 inst = inst->Next_1xx();
1845 }
1846
1847 ALWAYS_INLINE void INT_TO_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001848 shadow_frame.SetVReg(inst->VRegA_12x(inst_data), static_cast<uint16_t>(
1849 shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
1850 inst = inst->Next_1xx();
1851 }
1852
1853 ALWAYS_INLINE void INT_TO_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001854 shadow_frame.SetVReg(inst->VRegA_12x(inst_data), static_cast<int16_t>(
1855 shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
1856 inst = inst->Next_1xx();
1857 }
1858
1859 ALWAYS_INLINE void ADD_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001860 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1861 SafeAdd(shadow_frame.GetVReg(inst->VRegB_23x()),
1862 shadow_frame.GetVReg(inst->VRegC_23x())));
1863 inst = inst->Next_2xx();
1864 }
1865
1866 ALWAYS_INLINE void SUB_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001867 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1868 SafeSub(shadow_frame.GetVReg(inst->VRegB_23x()),
1869 shadow_frame.GetVReg(inst->VRegC_23x())));
1870 inst = inst->Next_2xx();
1871 }
1872
1873 ALWAYS_INLINE void MUL_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001874 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1875 SafeMul(shadow_frame.GetVReg(inst->VRegB_23x()),
1876 shadow_frame.GetVReg(inst->VRegC_23x())));
1877 inst = inst->Next_2xx();
1878 }
1879
1880 ALWAYS_INLINE void DIV_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001881 bool success = DoIntDivide(shadow_frame, inst->VRegA_23x(inst_data),
1882 shadow_frame.GetVReg(inst->VRegB_23x()),
1883 shadow_frame.GetVReg(inst->VRegC_23x()));
1884 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1885 }
1886
1887 ALWAYS_INLINE void REM_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001888 bool success = DoIntRemainder(shadow_frame, inst->VRegA_23x(inst_data),
1889 shadow_frame.GetVReg(inst->VRegB_23x()),
1890 shadow_frame.GetVReg(inst->VRegC_23x()));
1891 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1892 }
1893
1894 ALWAYS_INLINE void SHL_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001895 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1896 shadow_frame.GetVReg(inst->VRegB_23x()) <<
1897 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x1f));
1898 inst = inst->Next_2xx();
1899 }
1900
1901 ALWAYS_INLINE void SHR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001902 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1903 shadow_frame.GetVReg(inst->VRegB_23x()) >>
1904 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x1f));
1905 inst = inst->Next_2xx();
1906 }
1907
1908 ALWAYS_INLINE void USHR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001909 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1910 static_cast<uint32_t>(shadow_frame.GetVReg(inst->VRegB_23x())) >>
1911 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x1f));
1912 inst = inst->Next_2xx();
1913 }
1914
1915 ALWAYS_INLINE void AND_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001916 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1917 shadow_frame.GetVReg(inst->VRegB_23x()) &
1918 shadow_frame.GetVReg(inst->VRegC_23x()));
1919 inst = inst->Next_2xx();
1920 }
1921
1922 ALWAYS_INLINE void OR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001923 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1924 shadow_frame.GetVReg(inst->VRegB_23x()) |
1925 shadow_frame.GetVReg(inst->VRegC_23x()));
1926 inst = inst->Next_2xx();
1927 }
1928
1929 ALWAYS_INLINE void XOR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001930 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1931 shadow_frame.GetVReg(inst->VRegB_23x()) ^
1932 shadow_frame.GetVReg(inst->VRegC_23x()));
1933 inst = inst->Next_2xx();
1934 }
1935
1936 ALWAYS_INLINE void ADD_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001937 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
1938 SafeAdd(shadow_frame.GetVRegLong(inst->VRegB_23x()),
1939 shadow_frame.GetVRegLong(inst->VRegC_23x())));
1940 inst = inst->Next_2xx();
1941 }
1942
1943 ALWAYS_INLINE void SUB_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001944 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
1945 SafeSub(shadow_frame.GetVRegLong(inst->VRegB_23x()),
1946 shadow_frame.GetVRegLong(inst->VRegC_23x())));
1947 inst = inst->Next_2xx();
1948 }
1949
1950 ALWAYS_INLINE void MUL_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001951 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
1952 SafeMul(shadow_frame.GetVRegLong(inst->VRegB_23x()),
1953 shadow_frame.GetVRegLong(inst->VRegC_23x())));
1954 inst = inst->Next_2xx();
1955 }
1956
1957 ALWAYS_INLINE void DIV_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001958 DoLongDivide(shadow_frame, inst->VRegA_23x(inst_data),
1959 shadow_frame.GetVRegLong(inst->VRegB_23x()),
1960 shadow_frame.GetVRegLong(inst->VRegC_23x()));
1961 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_2xx);
1962 }
1963
1964 ALWAYS_INLINE void REM_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001965 DoLongRemainder(shadow_frame, inst->VRegA_23x(inst_data),
1966 shadow_frame.GetVRegLong(inst->VRegB_23x()),
1967 shadow_frame.GetVRegLong(inst->VRegC_23x()));
1968 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_2xx);
1969 }
1970
1971 ALWAYS_INLINE void AND_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001972 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
1973 shadow_frame.GetVRegLong(inst->VRegB_23x()) &
1974 shadow_frame.GetVRegLong(inst->VRegC_23x()));
1975 inst = inst->Next_2xx();
1976 }
1977
1978 ALWAYS_INLINE void OR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001979 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
1980 shadow_frame.GetVRegLong(inst->VRegB_23x()) |
1981 shadow_frame.GetVRegLong(inst->VRegC_23x()));
1982 inst = inst->Next_2xx();
1983 }
1984
1985 ALWAYS_INLINE void XOR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001986 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
1987 shadow_frame.GetVRegLong(inst->VRegB_23x()) ^
1988 shadow_frame.GetVRegLong(inst->VRegC_23x()));
1989 inst = inst->Next_2xx();
1990 }
1991
1992 ALWAYS_INLINE void SHL_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001993 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
1994 shadow_frame.GetVRegLong(inst->VRegB_23x()) <<
1995 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x3f));
1996 inst = inst->Next_2xx();
1997 }
1998
1999 ALWAYS_INLINE void SHR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002000 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
2001 shadow_frame.GetVRegLong(inst->VRegB_23x()) >>
2002 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x3f));
2003 inst = inst->Next_2xx();
2004 }
2005
2006 ALWAYS_INLINE void USHR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002007 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
2008 static_cast<uint64_t>(shadow_frame.GetVRegLong(inst->VRegB_23x())) >>
2009 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x3f));
2010 inst = inst->Next_2xx();
2011 }
2012
2013 ALWAYS_INLINE void ADD_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002014 shadow_frame.SetVRegFloat(inst->VRegA_23x(inst_data),
2015 shadow_frame.GetVRegFloat(inst->VRegB_23x()) +
2016 shadow_frame.GetVRegFloat(inst->VRegC_23x()));
2017 inst = inst->Next_2xx();
2018 }
2019
2020 ALWAYS_INLINE void SUB_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002021 shadow_frame.SetVRegFloat(inst->VRegA_23x(inst_data),
2022 shadow_frame.GetVRegFloat(inst->VRegB_23x()) -
2023 shadow_frame.GetVRegFloat(inst->VRegC_23x()));
2024 inst = inst->Next_2xx();
2025 }
2026
2027 ALWAYS_INLINE void MUL_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002028 shadow_frame.SetVRegFloat(inst->VRegA_23x(inst_data),
2029 shadow_frame.GetVRegFloat(inst->VRegB_23x()) *
2030 shadow_frame.GetVRegFloat(inst->VRegC_23x()));
2031 inst = inst->Next_2xx();
2032 }
2033
2034 ALWAYS_INLINE void DIV_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002035 shadow_frame.SetVRegFloat(inst->VRegA_23x(inst_data),
2036 shadow_frame.GetVRegFloat(inst->VRegB_23x()) /
2037 shadow_frame.GetVRegFloat(inst->VRegC_23x()));
2038 inst = inst->Next_2xx();
2039 }
2040
2041 ALWAYS_INLINE void REM_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002042 shadow_frame.SetVRegFloat(inst->VRegA_23x(inst_data),
2043 fmodf(shadow_frame.GetVRegFloat(inst->VRegB_23x()),
2044 shadow_frame.GetVRegFloat(inst->VRegC_23x())));
2045 inst = inst->Next_2xx();
2046 }
2047
2048 ALWAYS_INLINE void ADD_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002049 shadow_frame.SetVRegDouble(inst->VRegA_23x(inst_data),
2050 shadow_frame.GetVRegDouble(inst->VRegB_23x()) +
2051 shadow_frame.GetVRegDouble(inst->VRegC_23x()));
2052 inst = inst->Next_2xx();
2053 }
2054
2055 ALWAYS_INLINE void SUB_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002056 shadow_frame.SetVRegDouble(inst->VRegA_23x(inst_data),
2057 shadow_frame.GetVRegDouble(inst->VRegB_23x()) -
2058 shadow_frame.GetVRegDouble(inst->VRegC_23x()));
2059 inst = inst->Next_2xx();
2060 }
2061
2062 ALWAYS_INLINE void MUL_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002063 shadow_frame.SetVRegDouble(inst->VRegA_23x(inst_data),
2064 shadow_frame.GetVRegDouble(inst->VRegB_23x()) *
2065 shadow_frame.GetVRegDouble(inst->VRegC_23x()));
2066 inst = inst->Next_2xx();
2067 }
2068
2069 ALWAYS_INLINE void DIV_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002070 shadow_frame.SetVRegDouble(inst->VRegA_23x(inst_data),
2071 shadow_frame.GetVRegDouble(inst->VRegB_23x()) /
2072 shadow_frame.GetVRegDouble(inst->VRegC_23x()));
2073 inst = inst->Next_2xx();
2074 }
2075
2076 ALWAYS_INLINE void REM_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002077 shadow_frame.SetVRegDouble(inst->VRegA_23x(inst_data),
2078 fmod(shadow_frame.GetVRegDouble(inst->VRegB_23x()),
2079 shadow_frame.GetVRegDouble(inst->VRegC_23x())));
2080 inst = inst->Next_2xx();
2081 }
2082
2083 ALWAYS_INLINE void ADD_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002084 uint4_t vregA = inst->VRegA_12x(inst_data);
2085 shadow_frame.SetVReg(vregA, SafeAdd(shadow_frame.GetVReg(vregA),
2086 shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
2087 inst = inst->Next_1xx();
2088 }
2089
2090 ALWAYS_INLINE void SUB_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002091 uint4_t vregA = inst->VRegA_12x(inst_data);
2092 shadow_frame.SetVReg(vregA,
2093 SafeSub(shadow_frame.GetVReg(vregA),
2094 shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
2095 inst = inst->Next_1xx();
2096 }
2097
2098 ALWAYS_INLINE void MUL_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002099 uint4_t vregA = inst->VRegA_12x(inst_data);
2100 shadow_frame.SetVReg(vregA,
2101 SafeMul(shadow_frame.GetVReg(vregA),
2102 shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
2103 inst = inst->Next_1xx();
2104 }
2105
2106 ALWAYS_INLINE void DIV_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002107 uint4_t vregA = inst->VRegA_12x(inst_data);
2108 bool success = DoIntDivide(shadow_frame, vregA, shadow_frame.GetVReg(vregA),
2109 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
2110 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_1xx);
2111 }
2112
2113 ALWAYS_INLINE void REM_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002114 uint4_t vregA = inst->VRegA_12x(inst_data);
2115 bool success = DoIntRemainder(shadow_frame, vregA, shadow_frame.GetVReg(vregA),
2116 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
2117 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_1xx);
2118 }
2119
2120 ALWAYS_INLINE void SHL_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002121 uint4_t vregA = inst->VRegA_12x(inst_data);
2122 shadow_frame.SetVReg(vregA,
2123 shadow_frame.GetVReg(vregA) <<
2124 (shadow_frame.GetVReg(inst->VRegB_12x(inst_data)) & 0x1f));
2125 inst = inst->Next_1xx();
2126 }
2127
2128 ALWAYS_INLINE void SHR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002129 uint4_t vregA = inst->VRegA_12x(inst_data);
2130 shadow_frame.SetVReg(vregA,
2131 shadow_frame.GetVReg(vregA) >>
2132 (shadow_frame.GetVReg(inst->VRegB_12x(inst_data)) & 0x1f));
2133 inst = inst->Next_1xx();
2134 }
2135
2136 ALWAYS_INLINE void USHR_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 static_cast<uint32_t>(shadow_frame.GetVReg(vregA)) >>
2140 (shadow_frame.GetVReg(inst->VRegB_12x(inst_data)) & 0x1f));
2141 inst = inst->Next_1xx();
2142 }
2143
2144 ALWAYS_INLINE void AND_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) &
2148 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
2149 inst = inst->Next_1xx();
2150 }
2151
2152 ALWAYS_INLINE void OR_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 shadow_frame.GetVReg(vregA) |
2156 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
2157 inst = inst->Next_1xx();
2158 }
2159
2160 ALWAYS_INLINE void XOR_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) ^
2164 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
2165 inst = inst->Next_1xx();
2166 }
2167
2168 ALWAYS_INLINE void ADD_LONG_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.SetVRegLong(vregA,
2171 SafeAdd(shadow_frame.GetVRegLong(vregA),
2172 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data))));
2173 inst = inst->Next_1xx();
2174 }
2175
2176 ALWAYS_INLINE void SUB_LONG_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.SetVRegLong(vregA,
2179 SafeSub(shadow_frame.GetVRegLong(vregA),
2180 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data))));
2181 inst = inst->Next_1xx();
2182 }
2183
2184 ALWAYS_INLINE void MUL_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 SafeMul(shadow_frame.GetVRegLong(vregA),
2188 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data))));
2189 inst = inst->Next_1xx();
2190 }
2191
2192 ALWAYS_INLINE void DIV_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002193 uint4_t vregA = inst->VRegA_12x(inst_data);
2194 DoLongDivide(shadow_frame, vregA, shadow_frame.GetVRegLong(vregA),
2195 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
2196 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
2197 }
2198
2199 ALWAYS_INLINE void REM_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002200 uint4_t vregA = inst->VRegA_12x(inst_data);
2201 DoLongRemainder(shadow_frame, vregA, shadow_frame.GetVRegLong(vregA),
2202 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
2203 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
2204 }
2205
2206 ALWAYS_INLINE void AND_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002207 uint4_t vregA = inst->VRegA_12x(inst_data);
2208 shadow_frame.SetVRegLong(vregA,
2209 shadow_frame.GetVRegLong(vregA) &
2210 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
2211 inst = inst->Next_1xx();
2212 }
2213
2214 ALWAYS_INLINE void OR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002215 uint4_t vregA = inst->VRegA_12x(inst_data);
2216 shadow_frame.SetVRegLong(vregA,
2217 shadow_frame.GetVRegLong(vregA) |
2218 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
2219 inst = inst->Next_1xx();
2220 }
2221
2222 ALWAYS_INLINE void XOR_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) ^
2226 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
2227 inst = inst->Next_1xx();
2228 }
2229
2230 ALWAYS_INLINE void SHL_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) <<
2234 (shadow_frame.GetVReg(inst->VRegB_12x(inst_data)) & 0x3f));
2235 inst = inst->Next_1xx();
2236 }
2237
2238 ALWAYS_INLINE void SHR_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) >>
2242 (shadow_frame.GetVReg(inst->VRegB_12x(inst_data)) & 0x3f));
2243 inst = inst->Next_1xx();
2244 }
2245
2246 ALWAYS_INLINE void USHR_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 static_cast<uint64_t>(shadow_frame.GetVRegLong(vregA)) >>
2250 (shadow_frame.GetVReg(inst->VRegB_12x(inst_data)) & 0x3f));
2251 inst = inst->Next_1xx();
2252 }
2253
2254 ALWAYS_INLINE void ADD_FLOAT_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.SetVRegFloat(vregA,
2257 shadow_frame.GetVRegFloat(vregA) +
2258 shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
2259 inst = inst->Next_1xx();
2260 }
2261
2262 ALWAYS_INLINE void SUB_FLOAT_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.SetVRegFloat(vregA,
2265 shadow_frame.GetVRegFloat(vregA) -
2266 shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
2267 inst = inst->Next_1xx();
2268 }
2269
2270 ALWAYS_INLINE void MUL_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) *
2274 shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
2275 inst = inst->Next_1xx();
2276 }
2277
2278 ALWAYS_INLINE void DIV_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) /
2282 shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
2283 inst = inst->Next_1xx();
2284 }
2285
2286 ALWAYS_INLINE void REM_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 fmodf(shadow_frame.GetVRegFloat(vregA),
2290 shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data))));
2291 inst = inst->Next_1xx();
2292 }
2293
2294 ALWAYS_INLINE void ADD_DOUBLE_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.SetVRegDouble(vregA,
2297 shadow_frame.GetVRegDouble(vregA) +
2298 shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
2299 inst = inst->Next_1xx();
2300 }
2301
2302 ALWAYS_INLINE void SUB_DOUBLE_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.SetVRegDouble(vregA,
2305 shadow_frame.GetVRegDouble(vregA) -
2306 shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
2307 inst = inst->Next_1xx();
2308 }
2309
2310 ALWAYS_INLINE void MUL_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) *
2314 shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
2315 inst = inst->Next_1xx();
2316 }
2317
2318 ALWAYS_INLINE void DIV_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) /
2322 shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
2323 inst = inst->Next_1xx();
2324 }
2325
2326 ALWAYS_INLINE void REM_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 fmod(shadow_frame.GetVRegDouble(vregA),
2330 shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data))));
2331 inst = inst->Next_1xx();
2332 }
2333
2334 ALWAYS_INLINE void ADD_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002335 shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
2336 SafeAdd(shadow_frame.GetVReg(inst->VRegB_22s(inst_data)),
2337 inst->VRegC_22s()));
2338 inst = inst->Next_2xx();
2339 }
2340
2341 ALWAYS_INLINE void RSUB_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002342 shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
2343 SafeSub(inst->VRegC_22s(),
2344 shadow_frame.GetVReg(inst->VRegB_22s(inst_data))));
2345 inst = inst->Next_2xx();
2346 }
2347
2348 ALWAYS_INLINE void MUL_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002349 shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
2350 SafeMul(shadow_frame.GetVReg(inst->VRegB_22s(inst_data)),
2351 inst->VRegC_22s()));
2352 inst = inst->Next_2xx();
2353 }
2354
2355 ALWAYS_INLINE void DIV_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002356 bool success = DoIntDivide(shadow_frame, inst->VRegA_22s(inst_data),
2357 shadow_frame.GetVReg(inst->VRegB_22s(inst_data)),
2358 inst->VRegC_22s());
2359 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
2360 }
2361
2362 ALWAYS_INLINE void REM_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002363 bool success = DoIntRemainder(shadow_frame, inst->VRegA_22s(inst_data),
2364 shadow_frame.GetVReg(inst->VRegB_22s(inst_data)),
2365 inst->VRegC_22s());
2366 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
2367 }
2368
2369 ALWAYS_INLINE void AND_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002370 shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
2371 shadow_frame.GetVReg(inst->VRegB_22s(inst_data)) &
2372 inst->VRegC_22s());
2373 inst = inst->Next_2xx();
2374 }
2375
2376 ALWAYS_INLINE void OR_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002377 shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
2378 shadow_frame.GetVReg(inst->VRegB_22s(inst_data)) |
2379 inst->VRegC_22s());
2380 inst = inst->Next_2xx();
2381 }
2382
2383 ALWAYS_INLINE void XOR_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002384 shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
2385 shadow_frame.GetVReg(inst->VRegB_22s(inst_data)) ^
2386 inst->VRegC_22s());
2387 inst = inst->Next_2xx();
2388 }
2389
2390 ALWAYS_INLINE void ADD_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002391 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2392 SafeAdd(shadow_frame.GetVReg(inst->VRegB_22b()), inst->VRegC_22b()));
2393 inst = inst->Next_2xx();
2394 }
2395
2396 ALWAYS_INLINE void RSUB_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002397 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2398 SafeSub(inst->VRegC_22b(), shadow_frame.GetVReg(inst->VRegB_22b())));
2399 inst = inst->Next_2xx();
2400 }
2401
2402 ALWAYS_INLINE void MUL_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002403 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2404 SafeMul(shadow_frame.GetVReg(inst->VRegB_22b()), inst->VRegC_22b()));
2405 inst = inst->Next_2xx();
2406 }
2407
2408 ALWAYS_INLINE void DIV_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002409 bool success = DoIntDivide(shadow_frame, inst->VRegA_22b(inst_data),
2410 shadow_frame.GetVReg(inst->VRegB_22b()), inst->VRegC_22b());
2411 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
2412 }
2413
2414 ALWAYS_INLINE void REM_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002415 bool success = DoIntRemainder(shadow_frame, inst->VRegA_22b(inst_data),
2416 shadow_frame.GetVReg(inst->VRegB_22b()), inst->VRegC_22b());
2417 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
2418 }
2419
2420 ALWAYS_INLINE void AND_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002421 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2422 shadow_frame.GetVReg(inst->VRegB_22b()) &
2423 inst->VRegC_22b());
2424 inst = inst->Next_2xx();
2425 }
2426
2427 ALWAYS_INLINE void OR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002428 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2429 shadow_frame.GetVReg(inst->VRegB_22b()) |
2430 inst->VRegC_22b());
2431 inst = inst->Next_2xx();
2432 }
2433
2434 ALWAYS_INLINE void XOR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002435 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2436 shadow_frame.GetVReg(inst->VRegB_22b()) ^
2437 inst->VRegC_22b());
2438 inst = inst->Next_2xx();
2439 }
2440
2441 ALWAYS_INLINE void SHL_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002442 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2443 shadow_frame.GetVReg(inst->VRegB_22b()) <<
2444 (inst->VRegC_22b() & 0x1f));
2445 inst = inst->Next_2xx();
2446 }
2447
2448 ALWAYS_INLINE void SHR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002449 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2450 shadow_frame.GetVReg(inst->VRegB_22b()) >>
2451 (inst->VRegC_22b() & 0x1f));
2452 inst = inst->Next_2xx();
2453 }
2454
2455 ALWAYS_INLINE void USHR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002456 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2457 static_cast<uint32_t>(shadow_frame.GetVReg(inst->VRegB_22b())) >>
2458 (inst->VRegC_22b() & 0x1f));
2459 inst = inst->Next_2xx();
2460 }
2461
2462 ALWAYS_INLINE void UNUSED_3E() REQUIRES_SHARED(Locks::mutator_lock_) {
2463 UnexpectedOpcode(inst, shadow_frame);
2464 }
2465
2466 ALWAYS_INLINE void UNUSED_3F() REQUIRES_SHARED(Locks::mutator_lock_) {
2467 UnexpectedOpcode(inst, shadow_frame);
2468 }
2469
2470 ALWAYS_INLINE void UNUSED_40() REQUIRES_SHARED(Locks::mutator_lock_) {
2471 UnexpectedOpcode(inst, shadow_frame);
2472 }
2473
2474 ALWAYS_INLINE void UNUSED_41() REQUIRES_SHARED(Locks::mutator_lock_) {
2475 UnexpectedOpcode(inst, shadow_frame);
2476 }
2477
2478 ALWAYS_INLINE void UNUSED_42() REQUIRES_SHARED(Locks::mutator_lock_) {
2479 UnexpectedOpcode(inst, shadow_frame);
2480 }
2481
2482 ALWAYS_INLINE void UNUSED_43() REQUIRES_SHARED(Locks::mutator_lock_) {
2483 UnexpectedOpcode(inst, shadow_frame);
2484 }
2485
2486 ALWAYS_INLINE void UNUSED_79() REQUIRES_SHARED(Locks::mutator_lock_) {
2487 UnexpectedOpcode(inst, shadow_frame);
2488 }
2489
2490 ALWAYS_INLINE void UNUSED_7A() REQUIRES_SHARED(Locks::mutator_lock_) {
2491 UnexpectedOpcode(inst, shadow_frame);
2492 }
2493
2494 ALWAYS_INLINE void UNUSED_F3() REQUIRES_SHARED(Locks::mutator_lock_) {
2495 UnexpectedOpcode(inst, shadow_frame);
2496 }
2497
2498 ALWAYS_INLINE void UNUSED_F4() REQUIRES_SHARED(Locks::mutator_lock_) {
2499 UnexpectedOpcode(inst, shadow_frame);
2500 }
2501
2502 ALWAYS_INLINE void UNUSED_F5() REQUIRES_SHARED(Locks::mutator_lock_) {
2503 UnexpectedOpcode(inst, shadow_frame);
2504 }
2505
2506 ALWAYS_INLINE void UNUSED_F6() REQUIRES_SHARED(Locks::mutator_lock_) {
2507 UnexpectedOpcode(inst, shadow_frame);
2508 }
2509
2510 ALWAYS_INLINE void UNUSED_F7() REQUIRES_SHARED(Locks::mutator_lock_) {
2511 UnexpectedOpcode(inst, shadow_frame);
2512 }
2513
2514 ALWAYS_INLINE void UNUSED_F8() REQUIRES_SHARED(Locks::mutator_lock_) {
2515 UnexpectedOpcode(inst, shadow_frame);
2516 }
2517
2518 ALWAYS_INLINE void UNUSED_F9() REQUIRES_SHARED(Locks::mutator_lock_) {
2519 UnexpectedOpcode(inst, shadow_frame);
2520 }
2521
2522 ALWAYS_INLINE InstructionHandler(SwitchImplContext* ctx,
2523 const instrumentation::Instrumentation* instrumentation,
2524 Thread* self,
2525 ShadowFrame& shadow_frame,
2526 uint16_t dex_pc,
2527 const Instruction*& inst,
2528 uint16_t inst_data,
2529 bool& exit_interpreter_loop)
2530 : ctx(ctx),
2531 instrumentation(instrumentation),
2532 self(self),
2533 shadow_frame(shadow_frame),
2534 dex_pc(dex_pc),
2535 inst(inst),
2536 inst_data(inst_data),
2537 exit_interpreter_loop(exit_interpreter_loop) {
2538 }
2539
2540 private:
2541 static constexpr bool do_assignability_check = do_access_check;
2542
2543 const CodeItemDataAccessor& Accessor() { return ctx->accessor; }
2544 const uint16_t* Insns() { return ctx->accessor.Insns(); }
2545 JValue* ResultRegister() { return &ctx->result_register; }
2546
2547 SwitchImplContext* const ctx;
2548 const instrumentation::Instrumentation* const instrumentation;
2549 Thread* const self;
2550 ShadowFrame& shadow_frame;
2551 uint32_t const dex_pc;
2552 const Instruction*& inst;
2553 uint16_t const inst_data;
2554 bool& exit_interpreter_loop;
2555};
2556
David Srbecky6da82472018-10-23 14:03:08 +01002557#undef BRANCH_INSTRUMENTATION
David Srbecky6da82472018-10-23 14:03:08 +01002558#undef POSSIBLY_HANDLE_PENDING_EXCEPTION
2559#undef POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE
2560#undef POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC
David Srbecky6da82472018-10-23 14:03:08 +01002561#undef HANDLE_PENDING_EXCEPTION
David Srbecky6da82472018-10-23 14:03:08 +01002562
Alex Light6f22e062018-10-05 15:05:12 -07002563// TODO On ASAN builds this function gets a huge stack frame. Since normally we run in the mterp
2564// this shouldn't cause any problems for stack overflow detection. Remove this once b/117341496 is
2565// fixed.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +01002566template<bool do_access_check, bool transaction_active>
Alex Light6f22e062018-10-05 15:05:12 -07002567ATTRIBUTE_NO_SANITIZE_ADDRESS void ExecuteSwitchImplCpp(SwitchImplContext* ctx) {
David Srbecky946bb092018-03-09 17:23:01 +00002568 Thread* self = ctx->self;
2569 const CodeItemDataAccessor& accessor = ctx->accessor;
2570 ShadowFrame& shadow_frame = ctx->shadow_frame;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002571 if (UNLIKELY(!shadow_frame.HasReferenceArray())) {
2572 LOG(FATAL) << "Invalid shadow frame for interpreter use";
David Srbecky946bb092018-03-09 17:23:01 +00002573 ctx->result = JValue();
2574 return;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002575 }
2576 self->VerifyStack();
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002577
2578 uint32_t dex_pc = shadow_frame.GetDexPC();
Mathieu Chartier2cebb242015-04-21 16:50:40 -07002579 const auto* const instrumentation = Runtime::Current()->GetInstrumentation();
Mathieu Chartier808c7a52017-12-15 11:19:33 -08002580 const uint16_t* const insns = accessor.Insns();
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002581 const Instruction* inst = Instruction::At(insns + dex_pc);
Sebastien Hertz3b588e02013-09-11 14:33:18 +02002582 uint16_t inst_data;
Igor Murashkin6918bf12015-09-27 19:19:06 -07002583
Alex Light0aa7a5a2018-10-10 15:58:14 +00002584 DCHECK(!shadow_frame.GetForceRetryInstruction())
2585 << "Entered interpreter from invoke without retry instruction being handled!";
2586
David Srbecky6da82472018-10-23 14:03:08 +01002587 bool const interpret_one_instruction = ctx->interpret_one_instruction;
2588 while (true) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002589 dex_pc = inst->GetDexPc(insns);
2590 shadow_frame.SetDexPC(dex_pc);
Ian Rogerse94652f2014-12-02 11:13:19 -08002591 TraceExecution(shadow_frame, inst, dex_pc);
Sebastien Hertz3b588e02013-09-11 14:33:18 +02002592 inst_data = inst->Fetch16(0);
David Srbeckya4a96af2018-10-31 16:34:58 +00002593 {
2594 bool exit_loop = false;
2595 InstructionHandler<do_access_check, transaction_active> handler(
2596 ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, exit_loop);
2597 if (!handler.Preamble()) {
2598 if (UNLIKELY(exit_loop)) {
2599 return;
2600 }
2601 if (UNLIKELY(interpret_one_instruction)) {
2602 break;
2603 }
2604 continue;
2605 }
2606 }
Sebastien Hertz3b588e02013-09-11 14:33:18 +02002607 switch (inst->Opcode(inst_data)) {
David Srbecky6da82472018-10-23 14:03:08 +01002608#define OPCODE_CASE(OPCODE, OPCODE_NAME, pname, f, i, a, e, v) \
2609 case OPCODE: { \
2610 bool exit_loop = false; \
2611 InstructionHandler<do_access_check, transaction_active> handler( \
2612 ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, exit_loop); \
David Srbeckya4a96af2018-10-31 16:34:58 +00002613 handler.OPCODE_NAME(); \
David Srbecky6da82472018-10-23 14:03:08 +01002614 /* TODO: Advance 'inst' here, instead of explicitly in each handler */ \
2615 if (UNLIKELY(exit_loop)) { \
2616 return; \
2617 } \
2618 break; \
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002619 }
David Srbecky6da82472018-10-23 14:03:08 +01002620DEX_INSTRUCTION_LIST(OPCODE_CASE)
2621#undef OPCODE_CASE
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002622 }
David Srbecky6da82472018-10-23 14:03:08 +01002623 if (UNLIKELY(interpret_one_instruction)) {
David Srbeckya4a96af2018-10-31 16:34:58 +00002624 break;
David Srbecky6da82472018-10-23 14:03:08 +01002625 }
2626 }
David Srbeckya4a96af2018-10-31 16:34:58 +00002627 // Record where we stopped.
2628 shadow_frame.SetDexPC(inst->GetDexPc(insns));
2629 ctx->result = ctx->result_register;
2630 return;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002631} // NOLINT(readability/fn_size)
2632
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002633} // namespace interpreter
2634} // namespace art
David Srbecky2ee09ff2018-10-24 13:24:22 +01002635
2636#endif // ART_RUNTIME_INTERPRETER_INTERPRETER_SWITCH_IMPL_INL_H_