blob: 94cb3de9f852cdfb8444858af4efe46566540c75 [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
David Srbecky5f250012018-11-08 14:16:38 +000074 NO_INLINE WARN_UNUSED bool HandlePendingExceptionWithInstrumentationImpl(
David Srbecky47ad3762018-10-31 12:43:40 +000075 const instrumentation::Instrumentation* instr)
76 REQUIRES_SHARED(Locks::mutator_lock_) {
77 DCHECK(self->IsExceptionPending());
78 self->AllowThreadSuspension();
79 if (!CheckForceReturn()) {
80 return false;
81 }
82 if (!MoveToExceptionHandler(self, shadow_frame, instr)) {
83 /* Structured locking is to be enforced for abnormal termination, too. */
84 DoMonitorCheckOnExit<do_assignability_check>(self, &shadow_frame);
85 if (ctx->interpret_one_instruction) {
86 /* Signal mterp to return to caller */
87 shadow_frame.SetDexPC(dex::kDexNoIndex);
88 }
89 ctx->result = JValue(); /* Handled in caller. */
90 exit_interpreter_loop = true;
91 return false; // Return to caller.
92 }
93 if (!CheckForceReturn()) {
94 return false;
95 }
96 int32_t displacement =
97 static_cast<int32_t>(shadow_frame.GetDexPC()) - static_cast<int32_t>(dex_pc);
98 inst = inst->RelativeAt(displacement);
99 return false; // Stop executing this opcode and continue in the exception handler.
100 }
101
David Srbecky5f250012018-11-08 14:16:38 +0000102 // Forwards the call to the NO_INLINE HandlePendingExceptionWithInstrumentationImpl.
103 ALWAYS_INLINE WARN_UNUSED bool HandlePendingExceptionWithInstrumentation(
104 const instrumentation::Instrumentation* instr)
105 REQUIRES_SHARED(Locks::mutator_lock_) {
106 // We need to help the compiler a bit to make the NO_INLINE call efficient.
107 // * All handler fields should be in registers, so we do not want to take the object
108 // address (for 'this' argument). Make a copy of the handler just for the slow path.
109 // * The modifiable fields should also be in registers, so we don't want to store their
110 // address even in the handler copy. Make a copy of them just for the call as well.
111 const Instruction* inst_copy = inst;
112 bool exit_loop_copy = exit_interpreter_loop;
113 InstructionHandler<do_access_check, transaction_active> handler_copy(
114 ctx, instrumentation, self, shadow_frame, dex_pc, inst_copy, inst_data, exit_loop_copy);
115 bool result = handler_copy.HandlePendingExceptionWithInstrumentationImpl(instr);
116 inst = inst_copy;
117 exit_interpreter_loop = exit_loop_copy;
118 return result;
119 }
120
David Srbecky47ad3762018-10-31 12:43:40 +0000121 ALWAYS_INLINE WARN_UNUSED bool HandlePendingException()
122 REQUIRES_SHARED(Locks::mutator_lock_) {
123 return HandlePendingExceptionWithInstrumentation(instrumentation);
124 }
125
126 ALWAYS_INLINE WARN_UNUSED bool PossiblyHandlePendingExceptionOnInvokeImpl(
127 bool is_exception_pending,
128 const Instruction* next_inst)
129 REQUIRES_SHARED(Locks::mutator_lock_) {
130 if (UNLIKELY(shadow_frame.GetForceRetryInstruction())) {
131 /* Don't need to do anything except clear the flag and exception. We leave the */
132 /* instruction the same so it will be re-executed on the next go-around. */
133 DCHECK(inst->IsInvoke());
134 shadow_frame.SetForceRetryInstruction(false);
135 if (UNLIKELY(is_exception_pending)) {
136 DCHECK(self->IsExceptionPending());
137 if (kIsDebugBuild) {
138 LOG(WARNING) << "Suppressing exception for instruction-retry: "
139 << self->GetException()->Dump();
140 }
141 self->ClearException();
142 }
143 } else if (UNLIKELY(is_exception_pending)) {
144 /* Should have succeeded. */
145 DCHECK(!shadow_frame.GetForceRetryInstruction());
146 if (!HandlePendingException()) {
147 return false;
148 }
149 } else {
150 inst = next_inst;
151 }
152 return true;
153 }
154
155 ALWAYS_INLINE WARN_UNUSED bool PossiblyHandlePendingException(
156 bool is_exception_pending,
157 const Instruction* next_inst)
158 REQUIRES_SHARED(Locks::mutator_lock_) {
159 /* Should only be on invoke instructions. */
160 DCHECK(!shadow_frame.GetForceRetryInstruction());
161 if (UNLIKELY(is_exception_pending)) {
162 if (!HandlePendingException()) {
163 return false;
164 }
165 } else {
166 inst = next_inst;
167 }
168 return true;
169 }
170
171 ALWAYS_INLINE WARN_UNUSED bool HandleMonitorChecks()
172 REQUIRES_SHARED(Locks::mutator_lock_) {
173 if (!DoMonitorCheckOnExit<do_assignability_check>(self, &shadow_frame)) {
174 if (!HandlePendingException()) {
175 return false;
176 }
177 }
178 return true;
179 }
180
181 // Code to run before each dex instruction.
David Srbeckya4a96af2018-10-31 16:34:58 +0000182 ALWAYS_INLINE WARN_UNUSED bool Preamble()
David Srbecky47ad3762018-10-31 12:43:40 +0000183 REQUIRES_SHARED(Locks::mutator_lock_) {
184 /* We need to put this before & after the instrumentation to avoid having to put in a */
185 /* post-script macro. */
186 if (!CheckForceReturn()) {
187 return false;
188 }
189 if (UNLIKELY(instrumentation->HasDexPcListeners())) {
David Srbeckya4a96af2018-10-31 16:34:58 +0000190 uint8_t opcode = inst->Opcode(inst_data);
191 bool is_move_result_object = (opcode == Instruction::MOVE_RESULT_OBJECT);
192 JValue* save_ref = is_move_result_object ? &ctx->result_register : nullptr;
David Srbecky47ad3762018-10-31 12:43:40 +0000193 if (UNLIKELY(!DoDexPcMoveEvent(self,
194 Accessor(),
195 shadow_frame,
196 dex_pc,
197 instrumentation,
198 save_ref))) {
199 if (!HandlePendingException()) {
200 return false;
201 }
202 }
203 if (!CheckForceReturn()) {
204 return false;
205 }
206 }
207 return true;
208 }
209
210 ALWAYS_INLINE WARN_UNUSED bool BranchInstrumentation(int32_t offset)
211 REQUIRES_SHARED(Locks::mutator_lock_) {
212 if (UNLIKELY(instrumentation->HasBranchListeners())) {
213 instrumentation->Branch(self, shadow_frame.GetMethod(), dex_pc, offset);
214 }
215 JValue result;
216 if (jit::Jit::MaybeDoOnStackReplacement(self,
217 shadow_frame.GetMethod(),
218 dex_pc,
219 offset,
220 &result)) {
221 if (ctx->interpret_one_instruction) {
222 /* OSR has completed execution of the method. Signal mterp to return to caller */
223 shadow_frame.SetDexPC(dex::kDexNoIndex);
224 }
225 ctx->result = result;
226 exit_interpreter_loop = true;
227 return false;
228 }
229 return true;
230 }
231
232 ALWAYS_INLINE void HotnessUpdate()
233 REQUIRES_SHARED(Locks::mutator_lock_) {
234 jit::Jit* jit = Runtime::Current()->GetJit();
235 if (jit != nullptr) {
236 jit->AddSamples(self, shadow_frame.GetMethod(), 1, /*with_backedges=*/ true);
237 }
238 }
239
240 ALWAYS_INLINE WARN_UNUSED bool HandleAsyncException()
241 REQUIRES_SHARED(Locks::mutator_lock_) {
242 if (UNLIKELY(self->ObserveAsyncException())) {
243 if (!HandlePendingException()) {
244 return false;
245 }
246 }
247 return true;
248 }
249
250 ALWAYS_INLINE void HandleBackwardBranch(int32_t offset)
251 REQUIRES_SHARED(Locks::mutator_lock_) {
252 if (IsBackwardBranch(offset)) {
253 HotnessUpdate();
254 /* Record new dex pc early to have consistent suspend point at loop header. */
255 shadow_frame.SetDexPC(inst->GetDexPc(Insns()));
256 self->AllowThreadSuspension();
257 }
258 }
259
260 // Unlike most other events the DexPcMovedEvent can be sent when there is a pending exception (if
261 // the next instruction is MOVE_EXCEPTION). This means it needs to be handled carefully to be able
262 // to detect exceptions thrown by the DexPcMovedEvent itself. These exceptions could be thrown by
263 // jvmti-agents while handling breakpoint or single step events. We had to move this into its own
264 // function because it was making ExecuteSwitchImpl have too large a stack.
265 NO_INLINE static bool DoDexPcMoveEvent(Thread* self,
266 const CodeItemDataAccessor& accessor,
267 const ShadowFrame& shadow_frame,
268 uint32_t dex_pc,
269 const instrumentation::Instrumentation* instrumentation,
270 JValue* save_ref)
271 REQUIRES_SHARED(Locks::mutator_lock_) {
272 DCHECK(instrumentation->HasDexPcListeners());
273 StackHandleScope<2> hs(self);
274 Handle<mirror::Throwable> thr(hs.NewHandle(self->GetException()));
275 mirror::Object* null_obj = nullptr;
276 HandleWrapper<mirror::Object> h(
277 hs.NewHandleWrapper(LIKELY(save_ref == nullptr) ? &null_obj : save_ref->GetGCRoot()));
278 self->ClearException();
279 instrumentation->DexPcMovedEvent(self,
280 shadow_frame.GetThisObject(accessor.InsSize()),
281 shadow_frame.GetMethod(),
282 dex_pc);
283 if (UNLIKELY(self->IsExceptionPending())) {
284 // We got a new exception in the dex-pc-moved event.
285 // We just let this exception replace the old one.
286 // TODO It would be good to add the old exception to the
287 // suppressed exceptions of the new one if possible.
288 return false;
289 } else {
290 if (UNLIKELY(!thr.IsNull())) {
291 self->SetException(thr.Get());
292 }
293 return true;
294 }
295 }
296
297 static bool NeedsMethodExitEvent(const instrumentation::Instrumentation* ins)
298 REQUIRES_SHARED(Locks::mutator_lock_) {
299 return ins->HasMethodExitListeners() || ins->HasWatchedFramePopListeners();
300 }
301
302 // Sends the normal method exit event.
303 // Returns true if the events succeeded and false if there is a pending exception.
304 NO_INLINE static bool SendMethodExitEvents(
305 Thread* self,
306 const instrumentation::Instrumentation* instrumentation,
307 const ShadowFrame& frame,
308 ObjPtr<mirror::Object> thiz,
309 ArtMethod* method,
310 uint32_t dex_pc,
311 const JValue& result)
312 REQUIRES_SHARED(Locks::mutator_lock_) {
313 bool had_event = false;
314 // We don't send method-exit if it's a pop-frame. We still send frame_popped though.
315 if (UNLIKELY(instrumentation->HasMethodExitListeners() && !frame.GetForcePopFrame())) {
316 had_event = true;
317 instrumentation->MethodExitEvent(self, thiz.Ptr(), method, dex_pc, result);
318 }
319 if (UNLIKELY(frame.NeedsNotifyPop() && instrumentation->HasWatchedFramePopListeners())) {
320 had_event = true;
321 instrumentation->WatchedFramePopped(self, frame);
322 }
323 if (UNLIKELY(had_event)) {
324 return !self->IsExceptionPending();
325 } else {
326 return true;
327 }
328 }
329
330#define BRANCH_INSTRUMENTATION(offset) \
331 if (!BranchInstrumentation(offset)) { \
332 return; \
333 }
334
335#define HANDLE_PENDING_EXCEPTION() \
336 if (!HandlePendingException()) { \
337 return; \
338 }
339
340#define POSSIBLY_HANDLE_PENDING_EXCEPTION(is_exception_pending, next_function) \
341 if (!PossiblyHandlePendingException(is_exception_pending, inst->next_function())) { \
342 return; \
343 }
344
345#define POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(is_exception_pending) \
346 if (!PossiblyHandlePendingExceptionOnInvokeImpl(is_exception_pending, inst->Next_4xx())) { \
347 return; \
348 }
349
350#define POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(is_exception_pending) \
351 if (!PossiblyHandlePendingExceptionOnInvokeImpl(is_exception_pending, inst->Next_3xx())) { \
352 return; \
353 }
354
David Srbecky6da82472018-10-23 14:03:08 +0100355 ALWAYS_INLINE void NOP() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100356 inst = inst->Next_1xx();
357 }
358
359 ALWAYS_INLINE void MOVE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100360 shadow_frame.SetVReg(inst->VRegA_12x(inst_data),
361 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
362 inst = inst->Next_1xx();
363 }
364
365 ALWAYS_INLINE void MOVE_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100366 shadow_frame.SetVReg(inst->VRegA_22x(inst_data),
367 shadow_frame.GetVReg(inst->VRegB_22x()));
368 inst = inst->Next_2xx();
369 }
370
371 ALWAYS_INLINE void MOVE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100372 shadow_frame.SetVReg(inst->VRegA_32x(),
373 shadow_frame.GetVReg(inst->VRegB_32x()));
374 inst = inst->Next_3xx();
375 }
376
377 ALWAYS_INLINE void MOVE_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100378 shadow_frame.SetVRegLong(inst->VRegA_12x(inst_data),
379 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
380 inst = inst->Next_1xx();
381 }
382
383 ALWAYS_INLINE void MOVE_WIDE_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100384 shadow_frame.SetVRegLong(inst->VRegA_22x(inst_data),
385 shadow_frame.GetVRegLong(inst->VRegB_22x()));
386 inst = inst->Next_2xx();
387 }
388
389 ALWAYS_INLINE void MOVE_WIDE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100390 shadow_frame.SetVRegLong(inst->VRegA_32x(),
391 shadow_frame.GetVRegLong(inst->VRegB_32x()));
392 inst = inst->Next_3xx();
393 }
394
395 ALWAYS_INLINE void MOVE_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100396 shadow_frame.SetVRegReference(inst->VRegA_12x(inst_data),
397 shadow_frame.GetVRegReference(inst->VRegB_12x(inst_data)));
398 inst = inst->Next_1xx();
399 }
400
401 ALWAYS_INLINE void MOVE_OBJECT_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100402 shadow_frame.SetVRegReference(inst->VRegA_22x(inst_data),
403 shadow_frame.GetVRegReference(inst->VRegB_22x()));
404 inst = inst->Next_2xx();
405 }
406
407 ALWAYS_INLINE void MOVE_OBJECT_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100408 shadow_frame.SetVRegReference(inst->VRegA_32x(),
409 shadow_frame.GetVRegReference(inst->VRegB_32x()));
410 inst = inst->Next_3xx();
411 }
412
413 ALWAYS_INLINE void MOVE_RESULT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100414 shadow_frame.SetVReg(inst->VRegA_11x(inst_data), ResultRegister()->GetI());
415 inst = inst->Next_1xx();
416 }
417
418 ALWAYS_INLINE void MOVE_RESULT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100419 shadow_frame.SetVRegLong(inst->VRegA_11x(inst_data), ResultRegister()->GetJ());
420 inst = inst->Next_1xx();
421 }
422
423 ALWAYS_INLINE void MOVE_RESULT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100424 shadow_frame.SetVRegReference(inst->VRegA_11x(inst_data), ResultRegister()->GetL());
425 inst = inst->Next_1xx();
426 }
427
428 ALWAYS_INLINE void MOVE_EXCEPTION() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100429 ObjPtr<mirror::Throwable> exception = self->GetException();
430 DCHECK(exception != nullptr) << "No pending exception on MOVE_EXCEPTION instruction";
431 shadow_frame.SetVRegReference(inst->VRegA_11x(inst_data), exception);
432 self->ClearException();
433 inst = inst->Next_1xx();
434 }
435
436 ALWAYS_INLINE void RETURN_VOID_NO_BARRIER() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100437 JValue result;
438 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000439 if (!HandleMonitorChecks()) {
440 return;
441 }
David Srbecky6da82472018-10-23 14:03:08 +0100442 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
443 !SendMethodExitEvents(self,
444 instrumentation,
445 shadow_frame,
446 shadow_frame.GetThisObject(Accessor().InsSize()),
447 shadow_frame.GetMethod(),
448 inst->GetDexPc(Insns()),
449 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000450 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
451 return;
452 }
David Srbecky6da82472018-10-23 14:03:08 +0100453 }
454 if (ctx->interpret_one_instruction) {
455 /* Signal mterp to return to caller */
456 shadow_frame.SetDexPC(dex::kDexNoIndex);
457 }
458 ctx->result = result;
459 exit_interpreter_loop = true;
460 }
461
462 ALWAYS_INLINE void RETURN_VOID() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100463 QuasiAtomic::ThreadFenceForConstructor();
464 JValue result;
465 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000466 if (!HandleMonitorChecks()) {
467 return;
468 }
David Srbecky6da82472018-10-23 14:03:08 +0100469 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
470 !SendMethodExitEvents(self,
471 instrumentation,
472 shadow_frame,
473 shadow_frame.GetThisObject(Accessor().InsSize()),
474 shadow_frame.GetMethod(),
475 inst->GetDexPc(Insns()),
476 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000477 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
478 return;
479 }
David Srbecky6da82472018-10-23 14:03:08 +0100480 }
481 if (ctx->interpret_one_instruction) {
482 /* Signal mterp to return to caller */
483 shadow_frame.SetDexPC(dex::kDexNoIndex);
484 }
485 ctx->result = result;
486 exit_interpreter_loop = true;
487 }
488
489 ALWAYS_INLINE void RETURN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100490 JValue result;
491 result.SetJ(0);
492 result.SetI(shadow_frame.GetVReg(inst->VRegA_11x(inst_data)));
493 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000494 if (!HandleMonitorChecks()) {
495 return;
496 }
David Srbecky6da82472018-10-23 14:03:08 +0100497 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
498 !SendMethodExitEvents(self,
499 instrumentation,
500 shadow_frame,
501 shadow_frame.GetThisObject(Accessor().InsSize()),
502 shadow_frame.GetMethod(),
503 inst->GetDexPc(Insns()),
504 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000505 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
506 return;
507 }
David Srbecky6da82472018-10-23 14:03:08 +0100508 }
509 if (ctx->interpret_one_instruction) {
510 /* Signal mterp to return to caller */
511 shadow_frame.SetDexPC(dex::kDexNoIndex);
512 }
513 ctx->result = result;
514 exit_interpreter_loop = true;
515 }
516
517 ALWAYS_INLINE void RETURN_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100518 JValue result;
519 result.SetJ(shadow_frame.GetVRegLong(inst->VRegA_11x(inst_data)));
520 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000521 if (!HandleMonitorChecks()) {
522 return;
523 }
David Srbecky6da82472018-10-23 14:03:08 +0100524 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
525 !SendMethodExitEvents(self,
526 instrumentation,
527 shadow_frame,
528 shadow_frame.GetThisObject(Accessor().InsSize()),
529 shadow_frame.GetMethod(),
530 inst->GetDexPc(Insns()),
531 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000532 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
533 return;
534 }
David Srbecky6da82472018-10-23 14:03:08 +0100535 }
536 if (ctx->interpret_one_instruction) {
537 /* Signal mterp to return to caller */
538 shadow_frame.SetDexPC(dex::kDexNoIndex);
539 }
540 ctx->result = result;
541 exit_interpreter_loop = true;
542 }
543
544 ALWAYS_INLINE void RETURN_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100545 JValue result;
546 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000547 if (!HandleMonitorChecks()) {
548 return;
549 }
David Srbecky6da82472018-10-23 14:03:08 +0100550 const size_t ref_idx = inst->VRegA_11x(inst_data);
551 ObjPtr<mirror::Object> obj_result = shadow_frame.GetVRegReference(ref_idx);
552 if (do_assignability_check && obj_result != nullptr) {
553 ObjPtr<mirror::Class> return_type = shadow_frame.GetMethod()->ResolveReturnType();
554 // Re-load since it might have moved.
555 obj_result = shadow_frame.GetVRegReference(ref_idx);
556 if (return_type == nullptr) {
557 // Return the pending exception.
558 HANDLE_PENDING_EXCEPTION();
559 }
560 if (!obj_result->VerifierInstanceOf(return_type)) {
561 // This should never happen.
562 std::string temp1, temp2;
563 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
564 "Returning '%s' that is not instance of return type '%s'",
565 obj_result->GetClass()->GetDescriptor(&temp1),
566 return_type->GetDescriptor(&temp2));
567 HANDLE_PENDING_EXCEPTION();
568 }
569 }
570 result.SetL(obj_result);
571 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
572 !SendMethodExitEvents(self,
573 instrumentation,
574 shadow_frame,
575 shadow_frame.GetThisObject(Accessor().InsSize()),
576 shadow_frame.GetMethod(),
577 inst->GetDexPc(Insns()),
578 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000579 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
580 return;
581 }
David Srbecky6da82472018-10-23 14:03:08 +0100582 }
583 // Re-load since it might have moved during the MethodExitEvent.
584 result.SetL(shadow_frame.GetVRegReference(ref_idx));
585 if (ctx->interpret_one_instruction) {
586 /* Signal mterp to return to caller */
587 shadow_frame.SetDexPC(dex::kDexNoIndex);
588 }
589 ctx->result = result;
590 exit_interpreter_loop = true;
591 }
592
593 ALWAYS_INLINE void CONST_4() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100594 uint4_t dst = inst->VRegA_11n(inst_data);
595 int4_t val = inst->VRegB_11n(inst_data);
596 shadow_frame.SetVReg(dst, val);
597 if (val == 0) {
598 shadow_frame.SetVRegReference(dst, nullptr);
599 }
600 inst = inst->Next_1xx();
601 }
602
603 ALWAYS_INLINE void CONST_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100604 uint8_t dst = inst->VRegA_21s(inst_data);
605 int16_t val = inst->VRegB_21s();
606 shadow_frame.SetVReg(dst, val);
607 if (val == 0) {
608 shadow_frame.SetVRegReference(dst, nullptr);
609 }
610 inst = inst->Next_2xx();
611 }
612
613 ALWAYS_INLINE void CONST() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100614 uint8_t dst = inst->VRegA_31i(inst_data);
615 int32_t val = inst->VRegB_31i();
616 shadow_frame.SetVReg(dst, val);
617 if (val == 0) {
618 shadow_frame.SetVRegReference(dst, nullptr);
619 }
620 inst = inst->Next_3xx();
621 }
622
623 ALWAYS_INLINE void CONST_HIGH16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100624 uint8_t dst = inst->VRegA_21h(inst_data);
625 int32_t val = static_cast<int32_t>(inst->VRegB_21h() << 16);
626 shadow_frame.SetVReg(dst, val);
627 if (val == 0) {
628 shadow_frame.SetVRegReference(dst, nullptr);
629 }
630 inst = inst->Next_2xx();
631 }
632
633 ALWAYS_INLINE void CONST_WIDE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100634 shadow_frame.SetVRegLong(inst->VRegA_21s(inst_data), inst->VRegB_21s());
635 inst = inst->Next_2xx();
636 }
637
638 ALWAYS_INLINE void CONST_WIDE_32() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100639 shadow_frame.SetVRegLong(inst->VRegA_31i(inst_data), inst->VRegB_31i());
640 inst = inst->Next_3xx();
641 }
642
643 ALWAYS_INLINE void CONST_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100644 shadow_frame.SetVRegLong(inst->VRegA_51l(inst_data), inst->VRegB_51l());
645 inst = inst->Next_51l();
646 }
647
648 ALWAYS_INLINE void CONST_WIDE_HIGH16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100649 shadow_frame.SetVRegLong(inst->VRegA_21h(inst_data),
650 static_cast<uint64_t>(inst->VRegB_21h()) << 48);
651 inst = inst->Next_2xx();
652 }
653
654 ALWAYS_INLINE void CONST_STRING() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100655 ObjPtr<mirror::String> s = ResolveString(self,
656 shadow_frame,
657 dex::StringIndex(inst->VRegB_21c()));
658 if (UNLIKELY(s == nullptr)) {
659 HANDLE_PENDING_EXCEPTION();
660 } else {
661 shadow_frame.SetVRegReference(inst->VRegA_21c(inst_data), s);
662 inst = inst->Next_2xx();
663 }
664 }
665
666 ALWAYS_INLINE void CONST_STRING_JUMBO() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100667 ObjPtr<mirror::String> s = ResolveString(self,
668 shadow_frame,
669 dex::StringIndex(inst->VRegB_31c()));
670 if (UNLIKELY(s == nullptr)) {
671 HANDLE_PENDING_EXCEPTION();
672 } else {
673 shadow_frame.SetVRegReference(inst->VRegA_31c(inst_data), s);
674 inst = inst->Next_3xx();
675 }
676 }
677
678 ALWAYS_INLINE void CONST_CLASS() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100679 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(inst->VRegB_21c()),
680 shadow_frame.GetMethod(),
681 self,
682 false,
683 do_access_check);
684 if (UNLIKELY(c == nullptr)) {
685 HANDLE_PENDING_EXCEPTION();
686 } else {
687 shadow_frame.SetVRegReference(inst->VRegA_21c(inst_data), c);
688 inst = inst->Next_2xx();
689 }
690 }
691
692 ALWAYS_INLINE void CONST_METHOD_HANDLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100693 ClassLinker* cl = Runtime::Current()->GetClassLinker();
694 ObjPtr<mirror::MethodHandle> mh = cl->ResolveMethodHandle(self,
695 inst->VRegB_21c(),
696 shadow_frame.GetMethod());
697 if (UNLIKELY(mh == nullptr)) {
698 HANDLE_PENDING_EXCEPTION();
699 } else {
700 shadow_frame.SetVRegReference(inst->VRegA_21c(inst_data), mh);
701 inst = inst->Next_2xx();
702 }
703 }
704
705 ALWAYS_INLINE void CONST_METHOD_TYPE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100706 ClassLinker* cl = Runtime::Current()->GetClassLinker();
707 ObjPtr<mirror::MethodType> mt = cl->ResolveMethodType(self,
708 dex::ProtoIndex(inst->VRegB_21c()),
709 shadow_frame.GetMethod());
710 if (UNLIKELY(mt == nullptr)) {
711 HANDLE_PENDING_EXCEPTION();
712 } else {
713 shadow_frame.SetVRegReference(inst->VRegA_21c(inst_data), mt);
714 inst = inst->Next_2xx();
715 }
716 }
717
718 ALWAYS_INLINE void MONITOR_ENTER() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000719 if (!HandleAsyncException()) {
720 return;
721 }
David Srbecky6da82472018-10-23 14:03:08 +0100722 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data));
723 if (UNLIKELY(obj == nullptr)) {
724 ThrowNullPointerExceptionFromInterpreter();
725 HANDLE_PENDING_EXCEPTION();
726 } else {
727 DoMonitorEnter<do_assignability_check>(self, &shadow_frame, obj);
728 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
729 }
730 }
731
732 ALWAYS_INLINE void MONITOR_EXIT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000733 if (!HandleAsyncException()) {
734 return;
735 }
David Srbecky6da82472018-10-23 14:03:08 +0100736 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data));
737 if (UNLIKELY(obj == nullptr)) {
738 ThrowNullPointerExceptionFromInterpreter();
739 HANDLE_PENDING_EXCEPTION();
740 } else {
741 DoMonitorExit<do_assignability_check>(self, &shadow_frame, obj);
742 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
743 }
744 }
745
746 ALWAYS_INLINE void CHECK_CAST() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100747 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(inst->VRegB_21c()),
748 shadow_frame.GetMethod(),
749 self,
750 false,
751 do_access_check);
752 if (UNLIKELY(c == nullptr)) {
753 HANDLE_PENDING_EXCEPTION();
754 } else {
755 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(inst->VRegA_21c(inst_data));
756 if (UNLIKELY(obj != nullptr && !obj->InstanceOf(c))) {
757 ThrowClassCastException(c, obj->GetClass());
758 HANDLE_PENDING_EXCEPTION();
759 } else {
760 inst = inst->Next_2xx();
761 }
762 }
763 }
764
765 ALWAYS_INLINE void INSTANCE_OF() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100766 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(inst->VRegC_22c()),
767 shadow_frame.GetMethod(),
768 self,
769 false,
770 do_access_check);
771 if (UNLIKELY(c == nullptr)) {
772 HANDLE_PENDING_EXCEPTION();
773 } else {
774 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
775 shadow_frame.SetVReg(inst->VRegA_22c(inst_data),
776 (obj != nullptr && obj->InstanceOf(c)) ? 1 : 0);
777 inst = inst->Next_2xx();
778 }
779 }
780
781 ALWAYS_INLINE void ARRAY_LENGTH() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100782 ObjPtr<mirror::Object> array = shadow_frame.GetVRegReference(inst->VRegB_12x(inst_data));
783 if (UNLIKELY(array == nullptr)) {
784 ThrowNullPointerExceptionFromInterpreter();
785 HANDLE_PENDING_EXCEPTION();
786 } else {
787 shadow_frame.SetVReg(inst->VRegA_12x(inst_data), array->AsArray()->GetLength());
788 inst = inst->Next_1xx();
789 }
790 }
791
792 ALWAYS_INLINE void NEW_INSTANCE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100793 ObjPtr<mirror::Object> obj = nullptr;
794 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(inst->VRegB_21c()),
795 shadow_frame.GetMethod(),
796 self,
797 false,
798 do_access_check);
799 if (LIKELY(c != nullptr)) {
800 if (UNLIKELY(c->IsStringClass())) {
801 gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
802 obj = mirror::String::AllocEmptyString<true>(self, allocator_type);
803 } else {
804 obj = AllocObjectFromCode<true>(
805 c.Ptr(),
806 self,
807 Runtime::Current()->GetHeap()->GetCurrentAllocator());
808 }
809 }
810 if (UNLIKELY(obj == nullptr)) {
811 HANDLE_PENDING_EXCEPTION();
812 } else {
813 obj->GetClass()->AssertInitializedOrInitializingInThread(self);
814 // Don't allow finalizable objects to be allocated during a transaction since these can't
815 // be finalized without a started runtime.
816 if (transaction_active && obj->GetClass()->IsFinalizable()) {
817 AbortTransactionF(self, "Allocating finalizable object in transaction: %s",
818 obj->PrettyTypeOf().c_str());
819 HANDLE_PENDING_EXCEPTION();
820 }
821 shadow_frame.SetVRegReference(inst->VRegA_21c(inst_data), obj);
822 inst = inst->Next_2xx();
823 }
824 }
825
826 ALWAYS_INLINE void NEW_ARRAY() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100827 int32_t length = shadow_frame.GetVReg(inst->VRegB_22c(inst_data));
828 ObjPtr<mirror::Object> obj = AllocArrayFromCode<do_access_check, true>(
829 dex::TypeIndex(inst->VRegC_22c()),
830 length,
831 shadow_frame.GetMethod(),
832 self,
833 Runtime::Current()->GetHeap()->GetCurrentAllocator());
834 if (UNLIKELY(obj == nullptr)) {
835 HANDLE_PENDING_EXCEPTION();
836 } else {
837 shadow_frame.SetVRegReference(inst->VRegA_22c(inst_data), obj);
838 inst = inst->Next_2xx();
839 }
840 }
841
842 ALWAYS_INLINE void FILLED_NEW_ARRAY() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100843 bool success =
844 DoFilledNewArray<false, do_access_check, transaction_active>(inst, shadow_frame, self,
845 ResultRegister());
846 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
847 }
848
849 ALWAYS_INLINE void FILLED_NEW_ARRAY_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100850 bool success =
851 DoFilledNewArray<true, do_access_check, transaction_active>(inst, shadow_frame,
852 self, ResultRegister());
853 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
854 }
855
856 ALWAYS_INLINE void FILL_ARRAY_DATA() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100857 const uint16_t* payload_addr = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
858 const Instruction::ArrayDataPayload* payload =
859 reinterpret_cast<const Instruction::ArrayDataPayload*>(payload_addr);
860 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(inst->VRegA_31t(inst_data));
861 bool success = FillArrayData(obj, payload);
862 if (!success) {
863 HANDLE_PENDING_EXCEPTION();
864 }
865 if (transaction_active) {
866 RecordArrayElementsInTransaction(obj->AsArray(), payload->element_count);
867 }
868 inst = inst->Next_3xx();
869 }
870
871 ALWAYS_INLINE void THROW() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000872 if (!HandleAsyncException()) {
873 return;
874 }
David Srbecky6da82472018-10-23 14:03:08 +0100875 ObjPtr<mirror::Object> exception =
876 shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data));
877 if (UNLIKELY(exception == nullptr)) {
878 ThrowNullPointerException("throw with null exception");
879 } else if (do_assignability_check && !exception->GetClass()->IsThrowableClass()) {
880 // This should never happen.
881 std::string temp;
882 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
883 "Throwing '%s' that is not instance of Throwable",
884 exception->GetClass()->GetDescriptor(&temp));
885 } else {
886 self->SetException(exception->AsThrowable());
887 }
888 HANDLE_PENDING_EXCEPTION();
889 }
890
891 ALWAYS_INLINE void GOTO() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000892 if (!HandleAsyncException()) {
893 return;
894 }
David Srbecky6da82472018-10-23 14:03:08 +0100895 int8_t offset = inst->VRegA_10t(inst_data);
896 BRANCH_INSTRUMENTATION(offset);
897 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +0000898 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +0100899 }
900
901 ALWAYS_INLINE void GOTO_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000902 if (!HandleAsyncException()) {
903 return;
904 }
David Srbecky6da82472018-10-23 14:03:08 +0100905 int16_t offset = inst->VRegA_20t();
906 BRANCH_INSTRUMENTATION(offset);
907 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +0000908 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +0100909 }
910
911 ALWAYS_INLINE void GOTO_32() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000912 if (!HandleAsyncException()) {
913 return;
914 }
David Srbecky6da82472018-10-23 14:03:08 +0100915 int32_t offset = inst->VRegA_30t();
916 BRANCH_INSTRUMENTATION(offset);
917 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +0000918 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +0100919 }
920
921 ALWAYS_INLINE void PACKED_SWITCH() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100922 int32_t offset = DoPackedSwitch(inst, shadow_frame, inst_data);
923 BRANCH_INSTRUMENTATION(offset);
924 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +0000925 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +0100926 }
927
928 ALWAYS_INLINE void SPARSE_SWITCH() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100929 int32_t offset = DoSparseSwitch(inst, shadow_frame, inst_data);
930 BRANCH_INSTRUMENTATION(offset);
931 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +0000932 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +0100933 }
934
935#pragma clang diagnostic push
936#pragma clang diagnostic ignored "-Wfloat-equal"
937
938
939 ALWAYS_INLINE void CMPL_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100940 float val1 = shadow_frame.GetVRegFloat(inst->VRegB_23x());
941 float val2 = shadow_frame.GetVRegFloat(inst->VRegC_23x());
942 int32_t result;
943 if (val1 > val2) {
944 result = 1;
945 } else if (val1 == val2) {
946 result = 0;
947 } else {
948 result = -1;
949 }
950 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), result);
951 inst = inst->Next_2xx();
952 }
953
954 ALWAYS_INLINE void CMPG_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100955 float val1 = shadow_frame.GetVRegFloat(inst->VRegB_23x());
956 float val2 = shadow_frame.GetVRegFloat(inst->VRegC_23x());
957 int32_t result;
958 if (val1 < val2) {
959 result = -1;
960 } else if (val1 == val2) {
961 result = 0;
962 } else {
963 result = 1;
964 }
965 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), result);
966 inst = inst->Next_2xx();
967 }
968
969 ALWAYS_INLINE void CMPL_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100970 double val1 = shadow_frame.GetVRegDouble(inst->VRegB_23x());
971 double val2 = shadow_frame.GetVRegDouble(inst->VRegC_23x());
972 int32_t result;
973 if (val1 > val2) {
974 result = 1;
975 } else if (val1 == val2) {
976 result = 0;
977 } else {
978 result = -1;
979 }
980 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), result);
981 inst = inst->Next_2xx();
982 }
983
984
985 ALWAYS_INLINE void CMPG_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100986 double val1 = shadow_frame.GetVRegDouble(inst->VRegB_23x());
987 double val2 = shadow_frame.GetVRegDouble(inst->VRegC_23x());
988 int32_t result;
989 if (val1 < val2) {
990 result = -1;
991 } else if (val1 == val2) {
992 result = 0;
993 } else {
994 result = 1;
995 }
996 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), result);
997 inst = inst->Next_2xx();
998 }
999
1000#pragma clang diagnostic pop
1001
1002
1003 ALWAYS_INLINE void CMP_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001004 int64_t val1 = shadow_frame.GetVRegLong(inst->VRegB_23x());
1005 int64_t val2 = shadow_frame.GetVRegLong(inst->VRegC_23x());
1006 int32_t result;
1007 if (val1 > val2) {
1008 result = 1;
1009 } else if (val1 == val2) {
1010 result = 0;
1011 } else {
1012 result = -1;
1013 }
1014 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), result);
1015 inst = inst->Next_2xx();
1016 }
1017
1018 ALWAYS_INLINE void IF_EQ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001019 if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) ==
1020 shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
1021 int16_t offset = inst->VRegC_22t();
1022 BRANCH_INSTRUMENTATION(offset);
1023 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001024 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001025 } else {
1026 BRANCH_INSTRUMENTATION(2);
1027 inst = inst->Next_2xx();
1028 }
1029 }
1030
1031 ALWAYS_INLINE void IF_NE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001032 if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) !=
1033 shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
1034 int16_t offset = inst->VRegC_22t();
1035 BRANCH_INSTRUMENTATION(offset);
1036 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001037 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001038 } else {
1039 BRANCH_INSTRUMENTATION(2);
1040 inst = inst->Next_2xx();
1041 }
1042 }
1043
1044 ALWAYS_INLINE void IF_LT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001045 if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) <
1046 shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
1047 int16_t offset = inst->VRegC_22t();
1048 BRANCH_INSTRUMENTATION(offset);
1049 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001050 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001051 } else {
1052 BRANCH_INSTRUMENTATION(2);
1053 inst = inst->Next_2xx();
1054 }
1055 }
1056
1057 ALWAYS_INLINE void IF_GE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001058 if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) >=
1059 shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
1060 int16_t offset = inst->VRegC_22t();
1061 BRANCH_INSTRUMENTATION(offset);
1062 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001063 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001064 } else {
1065 BRANCH_INSTRUMENTATION(2);
1066 inst = inst->Next_2xx();
1067 }
1068 }
1069
1070 ALWAYS_INLINE void IF_GT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001071 if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) >
1072 shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
1073 int16_t offset = inst->VRegC_22t();
1074 BRANCH_INSTRUMENTATION(offset);
1075 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001076 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001077 } else {
1078 BRANCH_INSTRUMENTATION(2);
1079 inst = inst->Next_2xx();
1080 }
1081 }
1082
1083 ALWAYS_INLINE void IF_LE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001084 if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) <=
1085 shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
1086 int16_t offset = inst->VRegC_22t();
1087 BRANCH_INSTRUMENTATION(offset);
1088 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001089 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001090 } else {
1091 BRANCH_INSTRUMENTATION(2);
1092 inst = inst->Next_2xx();
1093 }
1094 }
1095
1096 ALWAYS_INLINE void IF_EQZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001097 if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) == 0) {
1098 int16_t offset = inst->VRegB_21t();
1099 BRANCH_INSTRUMENTATION(offset);
1100 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001101 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001102 } else {
1103 BRANCH_INSTRUMENTATION(2);
1104 inst = inst->Next_2xx();
1105 }
1106 }
1107
1108 ALWAYS_INLINE void IF_NEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001109 if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) != 0) {
1110 int16_t offset = inst->VRegB_21t();
1111 BRANCH_INSTRUMENTATION(offset);
1112 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001113 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001114 } else {
1115 BRANCH_INSTRUMENTATION(2);
1116 inst = inst->Next_2xx();
1117 }
1118 }
1119
1120 ALWAYS_INLINE void IF_LTZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001121 if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) < 0) {
1122 int16_t offset = inst->VRegB_21t();
1123 BRANCH_INSTRUMENTATION(offset);
1124 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001125 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001126 } else {
1127 BRANCH_INSTRUMENTATION(2);
1128 inst = inst->Next_2xx();
1129 }
1130 }
1131
1132 ALWAYS_INLINE void IF_GEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001133 if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) >= 0) {
1134 int16_t offset = inst->VRegB_21t();
1135 BRANCH_INSTRUMENTATION(offset);
1136 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001137 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001138 } else {
1139 BRANCH_INSTRUMENTATION(2);
1140 inst = inst->Next_2xx();
1141 }
1142 }
1143
1144 ALWAYS_INLINE void IF_GTZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001145 if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) > 0) {
1146 int16_t offset = inst->VRegB_21t();
1147 BRANCH_INSTRUMENTATION(offset);
1148 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001149 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001150 } else {
1151 BRANCH_INSTRUMENTATION(2);
1152 inst = inst->Next_2xx();
1153 }
1154 }
1155
1156 ALWAYS_INLINE void IF_LEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001157 if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) <= 0) {
1158 int16_t offset = inst->VRegB_21t();
1159 BRANCH_INSTRUMENTATION(offset);
1160 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001161 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001162 } else {
1163 BRANCH_INSTRUMENTATION(2);
1164 inst = inst->Next_2xx();
1165 }
1166 }
1167
1168 ALWAYS_INLINE void AGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001169 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1170 if (UNLIKELY(a == nullptr)) {
1171 ThrowNullPointerExceptionFromInterpreter();
1172 HANDLE_PENDING_EXCEPTION();
1173 }
1174 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1175 ObjPtr<mirror::BooleanArray> array = a->AsBooleanArray();
1176 if (array->CheckIsValidIndex(index)) {
1177 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
1178 inst = inst->Next_2xx();
1179 } else {
1180 HANDLE_PENDING_EXCEPTION();
1181 }
1182 }
1183
1184 ALWAYS_INLINE void AGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001185 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1186 if (UNLIKELY(a == nullptr)) {
1187 ThrowNullPointerExceptionFromInterpreter();
1188 HANDLE_PENDING_EXCEPTION();
1189 }
1190 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1191 ObjPtr<mirror::ByteArray> array = a->AsByteArray();
1192 if (array->CheckIsValidIndex(index)) {
1193 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
1194 inst = inst->Next_2xx();
1195 } else {
1196 HANDLE_PENDING_EXCEPTION();
1197 }
1198 }
1199
1200 ALWAYS_INLINE void AGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001201 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1202 if (UNLIKELY(a == nullptr)) {
1203 ThrowNullPointerExceptionFromInterpreter();
1204 HANDLE_PENDING_EXCEPTION();
1205 }
1206 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1207 ObjPtr<mirror::CharArray> array = a->AsCharArray();
1208 if (array->CheckIsValidIndex(index)) {
1209 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
1210 inst = inst->Next_2xx();
1211 } else {
1212 HANDLE_PENDING_EXCEPTION();
1213 }
1214 }
1215
1216 ALWAYS_INLINE void AGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001217 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1218 if (UNLIKELY(a == nullptr)) {
1219 ThrowNullPointerExceptionFromInterpreter();
1220 HANDLE_PENDING_EXCEPTION();
1221 }
1222 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1223 ObjPtr<mirror::ShortArray> array = a->AsShortArray();
1224 if (array->CheckIsValidIndex(index)) {
1225 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
1226 inst = inst->Next_2xx();
1227 } else {
1228 HANDLE_PENDING_EXCEPTION();
1229 }
1230 }
1231
1232 ALWAYS_INLINE void AGET() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001233 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1234 if (UNLIKELY(a == nullptr)) {
1235 ThrowNullPointerExceptionFromInterpreter();
1236 HANDLE_PENDING_EXCEPTION();
1237 }
1238 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1239 DCHECK(a->IsIntArray() || a->IsFloatArray()) << a->PrettyTypeOf();
1240 ObjPtr<mirror::IntArray> array = ObjPtr<mirror::IntArray>::DownCast(a);
1241 if (array->CheckIsValidIndex(index)) {
1242 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
1243 inst = inst->Next_2xx();
1244 } else {
1245 HANDLE_PENDING_EXCEPTION();
1246 }
1247 }
1248
1249 ALWAYS_INLINE void AGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001250 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1251 if (UNLIKELY(a == nullptr)) {
1252 ThrowNullPointerExceptionFromInterpreter();
1253 HANDLE_PENDING_EXCEPTION();
1254 }
1255 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1256 DCHECK(a->IsLongArray() || a->IsDoubleArray()) << a->PrettyTypeOf();
1257 ObjPtr<mirror::LongArray> array = ObjPtr<mirror::LongArray>::DownCast(a);
1258 if (array->CheckIsValidIndex(index)) {
1259 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
1260 inst = inst->Next_2xx();
1261 } else {
1262 HANDLE_PENDING_EXCEPTION();
1263 }
1264 }
1265
1266 ALWAYS_INLINE void AGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001267 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1268 if (UNLIKELY(a == nullptr)) {
1269 ThrowNullPointerExceptionFromInterpreter();
1270 HANDLE_PENDING_EXCEPTION();
1271 }
1272 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1273 ObjPtr<mirror::ObjectArray<mirror::Object>> array = a->AsObjectArray<mirror::Object>();
1274 if (array->CheckIsValidIndex(index)) {
1275 shadow_frame.SetVRegReference(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
1276 inst = inst->Next_2xx();
1277 } else {
1278 HANDLE_PENDING_EXCEPTION();
1279 }
1280 }
1281
1282 ALWAYS_INLINE void APUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001283 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1284 if (UNLIKELY(a == nullptr)) {
1285 ThrowNullPointerExceptionFromInterpreter();
1286 HANDLE_PENDING_EXCEPTION();
1287 }
1288 uint8_t val = shadow_frame.GetVReg(inst->VRegA_23x(inst_data));
1289 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1290 ObjPtr<mirror::BooleanArray> array = a->AsBooleanArray();
1291 if (array->CheckIsValidIndex(index)) {
1292 array->SetWithoutChecks<transaction_active>(index, val);
1293 inst = inst->Next_2xx();
1294 } else {
1295 HANDLE_PENDING_EXCEPTION();
1296 }
1297 }
1298
1299 ALWAYS_INLINE void APUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001300 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1301 if (UNLIKELY(a == nullptr)) {
1302 ThrowNullPointerExceptionFromInterpreter();
1303 HANDLE_PENDING_EXCEPTION();
1304 }
1305 int8_t val = shadow_frame.GetVReg(inst->VRegA_23x(inst_data));
1306 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1307 ObjPtr<mirror::ByteArray> array = a->AsByteArray();
1308 if (array->CheckIsValidIndex(index)) {
1309 array->SetWithoutChecks<transaction_active>(index, val);
1310 inst = inst->Next_2xx();
1311 } else {
1312 HANDLE_PENDING_EXCEPTION();
1313 }
1314 }
1315
1316 ALWAYS_INLINE void APUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001317 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1318 if (UNLIKELY(a == nullptr)) {
1319 ThrowNullPointerExceptionFromInterpreter();
1320 HANDLE_PENDING_EXCEPTION();
1321 }
1322 uint16_t val = shadow_frame.GetVReg(inst->VRegA_23x(inst_data));
1323 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1324 ObjPtr<mirror::CharArray> array = a->AsCharArray();
1325 if (array->CheckIsValidIndex(index)) {
1326 array->SetWithoutChecks<transaction_active>(index, val);
1327 inst = inst->Next_2xx();
1328 } else {
1329 HANDLE_PENDING_EXCEPTION();
1330 }
1331 }
1332
1333 ALWAYS_INLINE void APUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001334 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1335 if (UNLIKELY(a == nullptr)) {
1336 ThrowNullPointerExceptionFromInterpreter();
1337 HANDLE_PENDING_EXCEPTION();
1338 }
1339 int16_t val = shadow_frame.GetVReg(inst->VRegA_23x(inst_data));
1340 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1341 ObjPtr<mirror::ShortArray> array = a->AsShortArray();
1342 if (array->CheckIsValidIndex(index)) {
1343 array->SetWithoutChecks<transaction_active>(index, val);
1344 inst = inst->Next_2xx();
1345 } else {
1346 HANDLE_PENDING_EXCEPTION();
1347 }
1348 }
1349
1350 ALWAYS_INLINE void APUT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001351 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1352 if (UNLIKELY(a == nullptr)) {
1353 ThrowNullPointerExceptionFromInterpreter();
1354 HANDLE_PENDING_EXCEPTION();
1355 }
1356 int32_t val = shadow_frame.GetVReg(inst->VRegA_23x(inst_data));
1357 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1358 DCHECK(a->IsIntArray() || a->IsFloatArray()) << a->PrettyTypeOf();
1359 ObjPtr<mirror::IntArray> array = ObjPtr<mirror::IntArray>::DownCast(a);
1360 if (array->CheckIsValidIndex(index)) {
1361 array->SetWithoutChecks<transaction_active>(index, val);
1362 inst = inst->Next_2xx();
1363 } else {
1364 HANDLE_PENDING_EXCEPTION();
1365 }
1366 }
1367
1368 ALWAYS_INLINE void APUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001369 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1370 if (UNLIKELY(a == nullptr)) {
1371 ThrowNullPointerExceptionFromInterpreter();
1372 HANDLE_PENDING_EXCEPTION();
1373 }
1374 int64_t val = shadow_frame.GetVRegLong(inst->VRegA_23x(inst_data));
1375 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1376 DCHECK(a->IsLongArray() || a->IsDoubleArray()) << a->PrettyTypeOf();
1377 ObjPtr<mirror::LongArray> array = ObjPtr<mirror::LongArray>::DownCast(a);
1378 if (array->CheckIsValidIndex(index)) {
1379 array->SetWithoutChecks<transaction_active>(index, val);
1380 inst = inst->Next_2xx();
1381 } else {
1382 HANDLE_PENDING_EXCEPTION();
1383 }
1384 }
1385
1386 ALWAYS_INLINE void APUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001387 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1388 if (UNLIKELY(a == nullptr)) {
1389 ThrowNullPointerExceptionFromInterpreter();
1390 HANDLE_PENDING_EXCEPTION();
1391 }
1392 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1393 ObjPtr<mirror::Object> val = shadow_frame.GetVRegReference(inst->VRegA_23x(inst_data));
1394 ObjPtr<mirror::ObjectArray<mirror::Object>> array = a->AsObjectArray<mirror::Object>();
1395 if (array->CheckIsValidIndex(index) && array->CheckAssignable(val)) {
1396 array->SetWithoutChecks<transaction_active>(index, val);
1397 inst = inst->Next_2xx();
1398 } else {
1399 HANDLE_PENDING_EXCEPTION();
1400 }
1401 }
1402
1403 ALWAYS_INLINE void IGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001404 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimBoolean, do_access_check>(
1405 self, shadow_frame, inst, inst_data);
1406 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1407 }
1408
1409 ALWAYS_INLINE void IGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001410 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimByte, do_access_check>(
1411 self, shadow_frame, inst, inst_data);
1412 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1413 }
1414
1415 ALWAYS_INLINE void IGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001416 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimChar, do_access_check>(
1417 self, shadow_frame, inst, inst_data);
1418 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1419 }
1420
1421 ALWAYS_INLINE void IGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001422 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimShort, do_access_check>(
1423 self, shadow_frame, inst, inst_data);
1424 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1425 }
1426
1427 ALWAYS_INLINE void IGET() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001428 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimInt, do_access_check>(
1429 self, shadow_frame, inst, inst_data);
1430 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1431 }
1432
1433 ALWAYS_INLINE void IGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001434 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimLong, do_access_check>(
1435 self, shadow_frame, inst, inst_data);
1436 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1437 }
1438
1439 ALWAYS_INLINE void IGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001440 bool success = DoFieldGet<InstanceObjectRead, Primitive::kPrimNot, do_access_check>(
1441 self, shadow_frame, inst, inst_data);
1442 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1443 }
1444
1445 ALWAYS_INLINE void IGET_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001446 bool success = DoIGetQuick<Primitive::kPrimInt>(shadow_frame, inst, inst_data);
1447 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1448 }
1449
1450 ALWAYS_INLINE void IGET_WIDE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001451 bool success = DoIGetQuick<Primitive::kPrimLong>(shadow_frame, inst, inst_data);
1452 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1453 }
1454
1455 ALWAYS_INLINE void IGET_OBJECT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001456 bool success = DoIGetQuick<Primitive::kPrimNot>(shadow_frame, inst, inst_data);
1457 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1458 }
1459
1460 ALWAYS_INLINE void IGET_BOOLEAN_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001461 bool success = DoIGetQuick<Primitive::kPrimBoolean>(shadow_frame, inst, inst_data);
1462 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1463 }
1464
1465 ALWAYS_INLINE void IGET_BYTE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001466 bool success = DoIGetQuick<Primitive::kPrimByte>(shadow_frame, inst, inst_data);
1467 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1468 }
1469
1470 ALWAYS_INLINE void IGET_CHAR_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001471 bool success = DoIGetQuick<Primitive::kPrimChar>(shadow_frame, inst, inst_data);
1472 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1473 }
1474
1475 ALWAYS_INLINE void IGET_SHORT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001476 bool success = DoIGetQuick<Primitive::kPrimShort>(shadow_frame, inst, inst_data);
1477 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1478 }
1479
1480 ALWAYS_INLINE void SGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001481 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimBoolean, do_access_check,
1482 transaction_active>(self, shadow_frame, inst, inst_data);
1483 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1484 }
1485
1486 ALWAYS_INLINE void SGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001487 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimByte, do_access_check,
1488 transaction_active>(self, shadow_frame, inst, inst_data);
1489 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1490 }
1491
1492 ALWAYS_INLINE void SGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001493 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimChar, do_access_check,
1494 transaction_active>(self, shadow_frame, inst, inst_data);
1495 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1496 }
1497
1498 ALWAYS_INLINE void SGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001499 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimShort, do_access_check,
1500 transaction_active>(self, shadow_frame, inst, inst_data);
1501 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1502 }
1503
1504 ALWAYS_INLINE void SGET() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001505 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimInt, do_access_check,
1506 transaction_active>(self, shadow_frame, inst, inst_data);
1507 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1508 }
1509
1510 ALWAYS_INLINE void SGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001511 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimLong, do_access_check,
1512 transaction_active>(self, shadow_frame, inst, inst_data);
1513 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1514 }
1515
1516 ALWAYS_INLINE void SGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001517 bool success = DoFieldGet<StaticObjectRead, Primitive::kPrimNot, do_access_check,
1518 transaction_active>(self, shadow_frame, inst, inst_data);
1519 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1520 }
1521
1522 ALWAYS_INLINE void IPUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001523 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimBoolean, do_access_check,
1524 transaction_active>(self, shadow_frame, inst, inst_data);
1525 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1526 }
1527
1528 ALWAYS_INLINE void IPUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001529 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimByte, do_access_check,
1530 transaction_active>(self, shadow_frame, inst, inst_data);
1531 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1532 }
1533
1534 ALWAYS_INLINE void IPUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001535 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimChar, do_access_check,
1536 transaction_active>(self, shadow_frame, inst, inst_data);
1537 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1538 }
1539
1540 ALWAYS_INLINE void IPUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001541 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimShort, do_access_check,
1542 transaction_active>(self, shadow_frame, inst, inst_data);
1543 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1544 }
1545
1546 ALWAYS_INLINE void IPUT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001547 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimInt, do_access_check,
1548 transaction_active>(self, shadow_frame, inst, inst_data);
1549 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1550 }
1551
1552 ALWAYS_INLINE void IPUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001553 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimLong, do_access_check,
1554 transaction_active>(self, shadow_frame, inst, inst_data);
1555 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1556 }
1557
1558 ALWAYS_INLINE void IPUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001559 bool success = DoFieldPut<InstanceObjectWrite, Primitive::kPrimNot, do_access_check,
1560 transaction_active>(self, shadow_frame, inst, inst_data);
1561 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1562 }
1563
1564 ALWAYS_INLINE void IPUT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001565 bool success = DoIPutQuick<Primitive::kPrimInt, transaction_active>(
1566 shadow_frame, inst, inst_data);
1567 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1568 }
1569
1570 ALWAYS_INLINE void IPUT_BOOLEAN_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001571 bool success = DoIPutQuick<Primitive::kPrimBoolean, transaction_active>(
1572 shadow_frame, inst, inst_data);
1573 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1574 }
1575
1576 ALWAYS_INLINE void IPUT_BYTE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001577 bool success = DoIPutQuick<Primitive::kPrimByte, transaction_active>(
1578 shadow_frame, inst, inst_data);
1579 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1580 }
1581
1582 ALWAYS_INLINE void IPUT_CHAR_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001583 bool success = DoIPutQuick<Primitive::kPrimChar, transaction_active>(
1584 shadow_frame, inst, inst_data);
1585 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1586 }
1587
1588 ALWAYS_INLINE void IPUT_SHORT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001589 bool success = DoIPutQuick<Primitive::kPrimShort, transaction_active>(
1590 shadow_frame, inst, inst_data);
1591 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1592 }
1593
1594 ALWAYS_INLINE void IPUT_WIDE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001595 bool success = DoIPutQuick<Primitive::kPrimLong, transaction_active>(
1596 shadow_frame, inst, inst_data);
1597 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1598 }
1599
1600 ALWAYS_INLINE void IPUT_OBJECT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001601 bool success = DoIPutQuick<Primitive::kPrimNot, transaction_active>(
1602 shadow_frame, inst, inst_data);
1603 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1604 }
1605
1606 ALWAYS_INLINE void SPUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001607 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimBoolean, do_access_check,
1608 transaction_active>(self, shadow_frame, inst, inst_data);
1609 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1610 }
1611
1612 ALWAYS_INLINE void SPUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001613 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimByte, do_access_check,
1614 transaction_active>(self, shadow_frame, inst, inst_data);
1615 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1616 }
1617
1618 ALWAYS_INLINE void SPUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001619 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimChar, do_access_check,
1620 transaction_active>(self, shadow_frame, inst, inst_data);
1621 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1622 }
1623
1624 ALWAYS_INLINE void SPUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001625 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimShort, do_access_check,
1626 transaction_active>(self, shadow_frame, inst, inst_data);
1627 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1628 }
1629
1630 ALWAYS_INLINE void SPUT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001631 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimInt, do_access_check,
1632 transaction_active>(self, shadow_frame, inst, inst_data);
1633 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1634 }
1635
1636 ALWAYS_INLINE void SPUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001637 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimLong, do_access_check,
1638 transaction_active>(self, shadow_frame, inst, inst_data);
1639 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1640 }
1641
1642 ALWAYS_INLINE void SPUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001643 bool success = DoFieldPut<StaticObjectWrite, Primitive::kPrimNot, do_access_check,
1644 transaction_active>(self, shadow_frame, inst, inst_data);
1645 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1646 }
1647
1648 ALWAYS_INLINE void INVOKE_VIRTUAL() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001649 bool success = DoInvoke<kVirtual, false, do_access_check, /*is_mterp=*/ false>(
1650 self, shadow_frame, inst, inst_data, ResultRegister());
1651 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1652 }
1653
1654 ALWAYS_INLINE void INVOKE_VIRTUAL_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001655 bool success = DoInvoke<kVirtual, true, do_access_check, /*is_mterp=*/ false>(
1656 self, shadow_frame, inst, inst_data, ResultRegister());
1657 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1658 }
1659
1660 ALWAYS_INLINE void INVOKE_SUPER() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001661 bool success = DoInvoke<kSuper, false, do_access_check, /*is_mterp=*/ false>(
1662 self, shadow_frame, inst, inst_data, ResultRegister());
1663 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1664 }
1665
1666 ALWAYS_INLINE void INVOKE_SUPER_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001667 bool success = DoInvoke<kSuper, true, do_access_check, /*is_mterp=*/ false>(
1668 self, shadow_frame, inst, inst_data, ResultRegister());
1669 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1670 }
1671
1672 ALWAYS_INLINE void INVOKE_DIRECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001673 bool success = DoInvoke<kDirect, false, do_access_check, /*is_mterp=*/ false>(
1674 self, shadow_frame, inst, inst_data, ResultRegister());
1675 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1676 }
1677
1678 ALWAYS_INLINE void INVOKE_DIRECT_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001679 bool success = DoInvoke<kDirect, true, do_access_check, /*is_mterp=*/ false>(
1680 self, shadow_frame, inst, inst_data, ResultRegister());
1681 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1682 }
1683
1684 ALWAYS_INLINE void INVOKE_INTERFACE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001685 bool success = DoInvoke<kInterface, false, do_access_check, /*is_mterp=*/ false>(
1686 self, shadow_frame, inst, inst_data, ResultRegister());
1687 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1688 }
1689
1690 ALWAYS_INLINE void INVOKE_INTERFACE_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001691 bool success = DoInvoke<kInterface, true, do_access_check, /*is_mterp=*/ false>(
1692 self, shadow_frame, inst, inst_data, ResultRegister());
1693 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1694 }
1695
1696 ALWAYS_INLINE void INVOKE_STATIC() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001697 bool success = DoInvoke<kStatic, false, do_access_check, /*is_mterp=*/ false>(
1698 self, shadow_frame, inst, inst_data, ResultRegister());
1699 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1700 }
1701
1702 ALWAYS_INLINE void INVOKE_STATIC_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001703 bool success = DoInvoke<kStatic, true, do_access_check, /*is_mterp=*/ false>(
1704 self, shadow_frame, inst, inst_data, ResultRegister());
1705 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1706 }
1707
1708 ALWAYS_INLINE void INVOKE_VIRTUAL_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001709 bool success = DoInvoke<kVirtual, false, do_access_check, /*is_mterp=*/ false,
1710 /*is_quick=*/ true>(self, shadow_frame, inst, inst_data, ResultRegister());
1711 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1712 }
1713
1714 ALWAYS_INLINE void INVOKE_VIRTUAL_RANGE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001715 bool success = DoInvoke<kVirtual, true, do_access_check, /*is_mterp=*/ false,
1716 /*is_quick=*/ true>(self, shadow_frame, inst, inst_data, ResultRegister());
1717 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1718 }
1719
1720 ALWAYS_INLINE void INVOKE_POLYMORPHIC() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001721 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1722 bool success = DoInvokePolymorphic</* is_range= */ false>(
1723 self, shadow_frame, inst, inst_data, ResultRegister());
1724 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(!success);
1725 }
1726
1727 ALWAYS_INLINE void INVOKE_POLYMORPHIC_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001728 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1729 bool success = DoInvokePolymorphic</* is_range= */ true>(
1730 self, shadow_frame, inst, inst_data, ResultRegister());
1731 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(!success);
1732 }
1733
1734 ALWAYS_INLINE void INVOKE_CUSTOM() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001735 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1736 bool success = DoInvokeCustom</* is_range= */ false>(
1737 self, shadow_frame, inst, inst_data, ResultRegister());
1738 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1739 }
1740
1741 ALWAYS_INLINE void INVOKE_CUSTOM_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001742 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1743 bool success = DoInvokeCustom</* is_range= */ true>(
1744 self, shadow_frame, inst, inst_data, ResultRegister());
1745 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1746 }
1747
1748 ALWAYS_INLINE void NEG_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001749 shadow_frame.SetVReg(
1750 inst->VRegA_12x(inst_data), -shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
1751 inst = inst->Next_1xx();
1752 }
1753
1754 ALWAYS_INLINE void NOT_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001755 shadow_frame.SetVReg(
1756 inst->VRegA_12x(inst_data), ~shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
1757 inst = inst->Next_1xx();
1758 }
1759
1760 ALWAYS_INLINE void NEG_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001761 shadow_frame.SetVRegLong(
1762 inst->VRegA_12x(inst_data), -shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
1763 inst = inst->Next_1xx();
1764 }
1765
1766 ALWAYS_INLINE void NOT_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001767 shadow_frame.SetVRegLong(
1768 inst->VRegA_12x(inst_data), ~shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
1769 inst = inst->Next_1xx();
1770 }
1771
1772 ALWAYS_INLINE void NEG_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001773 shadow_frame.SetVRegFloat(
1774 inst->VRegA_12x(inst_data), -shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
1775 inst = inst->Next_1xx();
1776 }
1777
1778 ALWAYS_INLINE void NEG_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001779 shadow_frame.SetVRegDouble(
1780 inst->VRegA_12x(inst_data), -shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
1781 inst = inst->Next_1xx();
1782 }
1783
1784 ALWAYS_INLINE void INT_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001785 shadow_frame.SetVRegLong(inst->VRegA_12x(inst_data),
1786 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
1787 inst = inst->Next_1xx();
1788 }
1789
1790 ALWAYS_INLINE void INT_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001791 shadow_frame.SetVRegFloat(inst->VRegA_12x(inst_data),
1792 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
1793 inst = inst->Next_1xx();
1794 }
1795
1796 ALWAYS_INLINE void INT_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001797 shadow_frame.SetVRegDouble(inst->VRegA_12x(inst_data),
1798 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
1799 inst = inst->Next_1xx();
1800 }
1801
1802 ALWAYS_INLINE void LONG_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001803 shadow_frame.SetVReg(inst->VRegA_12x(inst_data),
1804 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
1805 inst = inst->Next_1xx();
1806 }
1807
1808 ALWAYS_INLINE void LONG_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001809 shadow_frame.SetVRegFloat(inst->VRegA_12x(inst_data),
1810 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
1811 inst = inst->Next_1xx();
1812 }
1813
1814 ALWAYS_INLINE void LONG_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001815 shadow_frame.SetVRegDouble(inst->VRegA_12x(inst_data),
1816 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
1817 inst = inst->Next_1xx();
1818 }
1819
1820 ALWAYS_INLINE void FLOAT_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001821 float val = shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data));
1822 int32_t result = art_float_to_integral<int32_t, float>(val);
1823 shadow_frame.SetVReg(inst->VRegA_12x(inst_data), result);
1824 inst = inst->Next_1xx();
1825 }
1826
1827 ALWAYS_INLINE void FLOAT_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001828 float val = shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data));
1829 int64_t result = art_float_to_integral<int64_t, float>(val);
1830 shadow_frame.SetVRegLong(inst->VRegA_12x(inst_data), result);
1831 inst = inst->Next_1xx();
1832 }
1833
1834 ALWAYS_INLINE void FLOAT_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001835 shadow_frame.SetVRegDouble(inst->VRegA_12x(inst_data),
1836 shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
1837 inst = inst->Next_1xx();
1838 }
1839
1840 ALWAYS_INLINE void DOUBLE_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001841 double val = shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data));
1842 int32_t result = art_float_to_integral<int32_t, double>(val);
1843 shadow_frame.SetVReg(inst->VRegA_12x(inst_data), result);
1844 inst = inst->Next_1xx();
1845 }
1846
1847 ALWAYS_INLINE void DOUBLE_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001848 double val = shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data));
1849 int64_t result = art_float_to_integral<int64_t, double>(val);
1850 shadow_frame.SetVRegLong(inst->VRegA_12x(inst_data), result);
1851 inst = inst->Next_1xx();
1852 }
1853
1854 ALWAYS_INLINE void DOUBLE_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001855 shadow_frame.SetVRegFloat(inst->VRegA_12x(inst_data),
1856 shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
1857 inst = inst->Next_1xx();
1858 }
1859
1860 ALWAYS_INLINE void INT_TO_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001861 shadow_frame.SetVReg(inst->VRegA_12x(inst_data), static_cast<int8_t>(
1862 shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
1863 inst = inst->Next_1xx();
1864 }
1865
1866 ALWAYS_INLINE void INT_TO_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001867 shadow_frame.SetVReg(inst->VRegA_12x(inst_data), static_cast<uint16_t>(
1868 shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
1869 inst = inst->Next_1xx();
1870 }
1871
1872 ALWAYS_INLINE void INT_TO_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001873 shadow_frame.SetVReg(inst->VRegA_12x(inst_data), static_cast<int16_t>(
1874 shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
1875 inst = inst->Next_1xx();
1876 }
1877
1878 ALWAYS_INLINE void ADD_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001879 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1880 SafeAdd(shadow_frame.GetVReg(inst->VRegB_23x()),
1881 shadow_frame.GetVReg(inst->VRegC_23x())));
1882 inst = inst->Next_2xx();
1883 }
1884
1885 ALWAYS_INLINE void SUB_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001886 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1887 SafeSub(shadow_frame.GetVReg(inst->VRegB_23x()),
1888 shadow_frame.GetVReg(inst->VRegC_23x())));
1889 inst = inst->Next_2xx();
1890 }
1891
1892 ALWAYS_INLINE void MUL_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001893 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1894 SafeMul(shadow_frame.GetVReg(inst->VRegB_23x()),
1895 shadow_frame.GetVReg(inst->VRegC_23x())));
1896 inst = inst->Next_2xx();
1897 }
1898
1899 ALWAYS_INLINE void DIV_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001900 bool success = DoIntDivide(shadow_frame, inst->VRegA_23x(inst_data),
1901 shadow_frame.GetVReg(inst->VRegB_23x()),
1902 shadow_frame.GetVReg(inst->VRegC_23x()));
1903 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1904 }
1905
1906 ALWAYS_INLINE void REM_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001907 bool success = DoIntRemainder(shadow_frame, inst->VRegA_23x(inst_data),
1908 shadow_frame.GetVReg(inst->VRegB_23x()),
1909 shadow_frame.GetVReg(inst->VRegC_23x()));
1910 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1911 }
1912
1913 ALWAYS_INLINE void SHL_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001914 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1915 shadow_frame.GetVReg(inst->VRegB_23x()) <<
1916 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x1f));
1917 inst = inst->Next_2xx();
1918 }
1919
1920 ALWAYS_INLINE void SHR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001921 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1922 shadow_frame.GetVReg(inst->VRegB_23x()) >>
1923 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x1f));
1924 inst = inst->Next_2xx();
1925 }
1926
1927 ALWAYS_INLINE void USHR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001928 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1929 static_cast<uint32_t>(shadow_frame.GetVReg(inst->VRegB_23x())) >>
1930 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x1f));
1931 inst = inst->Next_2xx();
1932 }
1933
1934 ALWAYS_INLINE void AND_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001935 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1936 shadow_frame.GetVReg(inst->VRegB_23x()) &
1937 shadow_frame.GetVReg(inst->VRegC_23x()));
1938 inst = inst->Next_2xx();
1939 }
1940
1941 ALWAYS_INLINE void OR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001942 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1943 shadow_frame.GetVReg(inst->VRegB_23x()) |
1944 shadow_frame.GetVReg(inst->VRegC_23x()));
1945 inst = inst->Next_2xx();
1946 }
1947
1948 ALWAYS_INLINE void XOR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001949 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1950 shadow_frame.GetVReg(inst->VRegB_23x()) ^
1951 shadow_frame.GetVReg(inst->VRegC_23x()));
1952 inst = inst->Next_2xx();
1953 }
1954
1955 ALWAYS_INLINE void ADD_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001956 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
1957 SafeAdd(shadow_frame.GetVRegLong(inst->VRegB_23x()),
1958 shadow_frame.GetVRegLong(inst->VRegC_23x())));
1959 inst = inst->Next_2xx();
1960 }
1961
1962 ALWAYS_INLINE void SUB_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001963 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
1964 SafeSub(shadow_frame.GetVRegLong(inst->VRegB_23x()),
1965 shadow_frame.GetVRegLong(inst->VRegC_23x())));
1966 inst = inst->Next_2xx();
1967 }
1968
1969 ALWAYS_INLINE void MUL_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001970 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
1971 SafeMul(shadow_frame.GetVRegLong(inst->VRegB_23x()),
1972 shadow_frame.GetVRegLong(inst->VRegC_23x())));
1973 inst = inst->Next_2xx();
1974 }
1975
1976 ALWAYS_INLINE void DIV_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001977 DoLongDivide(shadow_frame, inst->VRegA_23x(inst_data),
1978 shadow_frame.GetVRegLong(inst->VRegB_23x()),
1979 shadow_frame.GetVRegLong(inst->VRegC_23x()));
1980 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_2xx);
1981 }
1982
1983 ALWAYS_INLINE void REM_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001984 DoLongRemainder(shadow_frame, inst->VRegA_23x(inst_data),
1985 shadow_frame.GetVRegLong(inst->VRegB_23x()),
1986 shadow_frame.GetVRegLong(inst->VRegC_23x()));
1987 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_2xx);
1988 }
1989
1990 ALWAYS_INLINE void AND_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001991 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
1992 shadow_frame.GetVRegLong(inst->VRegB_23x()) &
1993 shadow_frame.GetVRegLong(inst->VRegC_23x()));
1994 inst = inst->Next_2xx();
1995 }
1996
1997 ALWAYS_INLINE void OR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001998 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
1999 shadow_frame.GetVRegLong(inst->VRegB_23x()) |
2000 shadow_frame.GetVRegLong(inst->VRegC_23x()));
2001 inst = inst->Next_2xx();
2002 }
2003
2004 ALWAYS_INLINE void XOR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002005 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
2006 shadow_frame.GetVRegLong(inst->VRegB_23x()) ^
2007 shadow_frame.GetVRegLong(inst->VRegC_23x()));
2008 inst = inst->Next_2xx();
2009 }
2010
2011 ALWAYS_INLINE void SHL_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002012 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
2013 shadow_frame.GetVRegLong(inst->VRegB_23x()) <<
2014 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x3f));
2015 inst = inst->Next_2xx();
2016 }
2017
2018 ALWAYS_INLINE void SHR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002019 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
2020 shadow_frame.GetVRegLong(inst->VRegB_23x()) >>
2021 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x3f));
2022 inst = inst->Next_2xx();
2023 }
2024
2025 ALWAYS_INLINE void USHR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002026 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
2027 static_cast<uint64_t>(shadow_frame.GetVRegLong(inst->VRegB_23x())) >>
2028 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x3f));
2029 inst = inst->Next_2xx();
2030 }
2031
2032 ALWAYS_INLINE void ADD_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002033 shadow_frame.SetVRegFloat(inst->VRegA_23x(inst_data),
2034 shadow_frame.GetVRegFloat(inst->VRegB_23x()) +
2035 shadow_frame.GetVRegFloat(inst->VRegC_23x()));
2036 inst = inst->Next_2xx();
2037 }
2038
2039 ALWAYS_INLINE void SUB_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002040 shadow_frame.SetVRegFloat(inst->VRegA_23x(inst_data),
2041 shadow_frame.GetVRegFloat(inst->VRegB_23x()) -
2042 shadow_frame.GetVRegFloat(inst->VRegC_23x()));
2043 inst = inst->Next_2xx();
2044 }
2045
2046 ALWAYS_INLINE void MUL_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002047 shadow_frame.SetVRegFloat(inst->VRegA_23x(inst_data),
2048 shadow_frame.GetVRegFloat(inst->VRegB_23x()) *
2049 shadow_frame.GetVRegFloat(inst->VRegC_23x()));
2050 inst = inst->Next_2xx();
2051 }
2052
2053 ALWAYS_INLINE void DIV_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002054 shadow_frame.SetVRegFloat(inst->VRegA_23x(inst_data),
2055 shadow_frame.GetVRegFloat(inst->VRegB_23x()) /
2056 shadow_frame.GetVRegFloat(inst->VRegC_23x()));
2057 inst = inst->Next_2xx();
2058 }
2059
2060 ALWAYS_INLINE void REM_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002061 shadow_frame.SetVRegFloat(inst->VRegA_23x(inst_data),
2062 fmodf(shadow_frame.GetVRegFloat(inst->VRegB_23x()),
2063 shadow_frame.GetVRegFloat(inst->VRegC_23x())));
2064 inst = inst->Next_2xx();
2065 }
2066
2067 ALWAYS_INLINE void ADD_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002068 shadow_frame.SetVRegDouble(inst->VRegA_23x(inst_data),
2069 shadow_frame.GetVRegDouble(inst->VRegB_23x()) +
2070 shadow_frame.GetVRegDouble(inst->VRegC_23x()));
2071 inst = inst->Next_2xx();
2072 }
2073
2074 ALWAYS_INLINE void SUB_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002075 shadow_frame.SetVRegDouble(inst->VRegA_23x(inst_data),
2076 shadow_frame.GetVRegDouble(inst->VRegB_23x()) -
2077 shadow_frame.GetVRegDouble(inst->VRegC_23x()));
2078 inst = inst->Next_2xx();
2079 }
2080
2081 ALWAYS_INLINE void MUL_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002082 shadow_frame.SetVRegDouble(inst->VRegA_23x(inst_data),
2083 shadow_frame.GetVRegDouble(inst->VRegB_23x()) *
2084 shadow_frame.GetVRegDouble(inst->VRegC_23x()));
2085 inst = inst->Next_2xx();
2086 }
2087
2088 ALWAYS_INLINE void DIV_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002089 shadow_frame.SetVRegDouble(inst->VRegA_23x(inst_data),
2090 shadow_frame.GetVRegDouble(inst->VRegB_23x()) /
2091 shadow_frame.GetVRegDouble(inst->VRegC_23x()));
2092 inst = inst->Next_2xx();
2093 }
2094
2095 ALWAYS_INLINE void REM_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002096 shadow_frame.SetVRegDouble(inst->VRegA_23x(inst_data),
2097 fmod(shadow_frame.GetVRegDouble(inst->VRegB_23x()),
2098 shadow_frame.GetVRegDouble(inst->VRegC_23x())));
2099 inst = inst->Next_2xx();
2100 }
2101
2102 ALWAYS_INLINE void ADD_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002103 uint4_t vregA = inst->VRegA_12x(inst_data);
2104 shadow_frame.SetVReg(vregA, SafeAdd(shadow_frame.GetVReg(vregA),
2105 shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
2106 inst = inst->Next_1xx();
2107 }
2108
2109 ALWAYS_INLINE void SUB_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002110 uint4_t vregA = inst->VRegA_12x(inst_data);
2111 shadow_frame.SetVReg(vregA,
2112 SafeSub(shadow_frame.GetVReg(vregA),
2113 shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
2114 inst = inst->Next_1xx();
2115 }
2116
2117 ALWAYS_INLINE void MUL_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002118 uint4_t vregA = inst->VRegA_12x(inst_data);
2119 shadow_frame.SetVReg(vregA,
2120 SafeMul(shadow_frame.GetVReg(vregA),
2121 shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
2122 inst = inst->Next_1xx();
2123 }
2124
2125 ALWAYS_INLINE void DIV_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002126 uint4_t vregA = inst->VRegA_12x(inst_data);
2127 bool success = DoIntDivide(shadow_frame, vregA, shadow_frame.GetVReg(vregA),
2128 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
2129 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_1xx);
2130 }
2131
2132 ALWAYS_INLINE void REM_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002133 uint4_t vregA = inst->VRegA_12x(inst_data);
2134 bool success = DoIntRemainder(shadow_frame, vregA, shadow_frame.GetVReg(vregA),
2135 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
2136 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_1xx);
2137 }
2138
2139 ALWAYS_INLINE void SHL_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002140 uint4_t vregA = inst->VRegA_12x(inst_data);
2141 shadow_frame.SetVReg(vregA,
2142 shadow_frame.GetVReg(vregA) <<
2143 (shadow_frame.GetVReg(inst->VRegB_12x(inst_data)) & 0x1f));
2144 inst = inst->Next_1xx();
2145 }
2146
2147 ALWAYS_INLINE void SHR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002148 uint4_t vregA = inst->VRegA_12x(inst_data);
2149 shadow_frame.SetVReg(vregA,
2150 shadow_frame.GetVReg(vregA) >>
2151 (shadow_frame.GetVReg(inst->VRegB_12x(inst_data)) & 0x1f));
2152 inst = inst->Next_1xx();
2153 }
2154
2155 ALWAYS_INLINE void USHR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002156 uint4_t vregA = inst->VRegA_12x(inst_data);
2157 shadow_frame.SetVReg(vregA,
2158 static_cast<uint32_t>(shadow_frame.GetVReg(vregA)) >>
2159 (shadow_frame.GetVReg(inst->VRegB_12x(inst_data)) & 0x1f));
2160 inst = inst->Next_1xx();
2161 }
2162
2163 ALWAYS_INLINE void AND_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002164 uint4_t vregA = inst->VRegA_12x(inst_data);
2165 shadow_frame.SetVReg(vregA,
2166 shadow_frame.GetVReg(vregA) &
2167 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
2168 inst = inst->Next_1xx();
2169 }
2170
2171 ALWAYS_INLINE void OR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002172 uint4_t vregA = inst->VRegA_12x(inst_data);
2173 shadow_frame.SetVReg(vregA,
2174 shadow_frame.GetVReg(vregA) |
2175 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
2176 inst = inst->Next_1xx();
2177 }
2178
2179 ALWAYS_INLINE void XOR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002180 uint4_t vregA = inst->VRegA_12x(inst_data);
2181 shadow_frame.SetVReg(vregA,
2182 shadow_frame.GetVReg(vregA) ^
2183 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
2184 inst = inst->Next_1xx();
2185 }
2186
2187 ALWAYS_INLINE void ADD_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002188 uint4_t vregA = inst->VRegA_12x(inst_data);
2189 shadow_frame.SetVRegLong(vregA,
2190 SafeAdd(shadow_frame.GetVRegLong(vregA),
2191 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data))));
2192 inst = inst->Next_1xx();
2193 }
2194
2195 ALWAYS_INLINE void SUB_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002196 uint4_t vregA = inst->VRegA_12x(inst_data);
2197 shadow_frame.SetVRegLong(vregA,
2198 SafeSub(shadow_frame.GetVRegLong(vregA),
2199 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data))));
2200 inst = inst->Next_1xx();
2201 }
2202
2203 ALWAYS_INLINE void MUL_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002204 uint4_t vregA = inst->VRegA_12x(inst_data);
2205 shadow_frame.SetVRegLong(vregA,
2206 SafeMul(shadow_frame.GetVRegLong(vregA),
2207 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data))));
2208 inst = inst->Next_1xx();
2209 }
2210
2211 ALWAYS_INLINE void DIV_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002212 uint4_t vregA = inst->VRegA_12x(inst_data);
2213 DoLongDivide(shadow_frame, vregA, shadow_frame.GetVRegLong(vregA),
2214 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
2215 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
2216 }
2217
2218 ALWAYS_INLINE void REM_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002219 uint4_t vregA = inst->VRegA_12x(inst_data);
2220 DoLongRemainder(shadow_frame, vregA, shadow_frame.GetVRegLong(vregA),
2221 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
2222 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
2223 }
2224
2225 ALWAYS_INLINE void AND_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002226 uint4_t vregA = inst->VRegA_12x(inst_data);
2227 shadow_frame.SetVRegLong(vregA,
2228 shadow_frame.GetVRegLong(vregA) &
2229 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
2230 inst = inst->Next_1xx();
2231 }
2232
2233 ALWAYS_INLINE void OR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002234 uint4_t vregA = inst->VRegA_12x(inst_data);
2235 shadow_frame.SetVRegLong(vregA,
2236 shadow_frame.GetVRegLong(vregA) |
2237 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
2238 inst = inst->Next_1xx();
2239 }
2240
2241 ALWAYS_INLINE void XOR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002242 uint4_t vregA = inst->VRegA_12x(inst_data);
2243 shadow_frame.SetVRegLong(vregA,
2244 shadow_frame.GetVRegLong(vregA) ^
2245 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
2246 inst = inst->Next_1xx();
2247 }
2248
2249 ALWAYS_INLINE void SHL_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002250 uint4_t vregA = inst->VRegA_12x(inst_data);
2251 shadow_frame.SetVRegLong(vregA,
2252 shadow_frame.GetVRegLong(vregA) <<
2253 (shadow_frame.GetVReg(inst->VRegB_12x(inst_data)) & 0x3f));
2254 inst = inst->Next_1xx();
2255 }
2256
2257 ALWAYS_INLINE void SHR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002258 uint4_t vregA = inst->VRegA_12x(inst_data);
2259 shadow_frame.SetVRegLong(vregA,
2260 shadow_frame.GetVRegLong(vregA) >>
2261 (shadow_frame.GetVReg(inst->VRegB_12x(inst_data)) & 0x3f));
2262 inst = inst->Next_1xx();
2263 }
2264
2265 ALWAYS_INLINE void USHR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002266 uint4_t vregA = inst->VRegA_12x(inst_data);
2267 shadow_frame.SetVRegLong(vregA,
2268 static_cast<uint64_t>(shadow_frame.GetVRegLong(vregA)) >>
2269 (shadow_frame.GetVReg(inst->VRegB_12x(inst_data)) & 0x3f));
2270 inst = inst->Next_1xx();
2271 }
2272
2273 ALWAYS_INLINE void ADD_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002274 uint4_t vregA = inst->VRegA_12x(inst_data);
2275 shadow_frame.SetVRegFloat(vregA,
2276 shadow_frame.GetVRegFloat(vregA) +
2277 shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
2278 inst = inst->Next_1xx();
2279 }
2280
2281 ALWAYS_INLINE void SUB_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002282 uint4_t vregA = inst->VRegA_12x(inst_data);
2283 shadow_frame.SetVRegFloat(vregA,
2284 shadow_frame.GetVRegFloat(vregA) -
2285 shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
2286 inst = inst->Next_1xx();
2287 }
2288
2289 ALWAYS_INLINE void MUL_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002290 uint4_t vregA = inst->VRegA_12x(inst_data);
2291 shadow_frame.SetVRegFloat(vregA,
2292 shadow_frame.GetVRegFloat(vregA) *
2293 shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
2294 inst = inst->Next_1xx();
2295 }
2296
2297 ALWAYS_INLINE void DIV_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002298 uint4_t vregA = inst->VRegA_12x(inst_data);
2299 shadow_frame.SetVRegFloat(vregA,
2300 shadow_frame.GetVRegFloat(vregA) /
2301 shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
2302 inst = inst->Next_1xx();
2303 }
2304
2305 ALWAYS_INLINE void REM_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002306 uint4_t vregA = inst->VRegA_12x(inst_data);
2307 shadow_frame.SetVRegFloat(vregA,
2308 fmodf(shadow_frame.GetVRegFloat(vregA),
2309 shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data))));
2310 inst = inst->Next_1xx();
2311 }
2312
2313 ALWAYS_INLINE void ADD_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002314 uint4_t vregA = inst->VRegA_12x(inst_data);
2315 shadow_frame.SetVRegDouble(vregA,
2316 shadow_frame.GetVRegDouble(vregA) +
2317 shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
2318 inst = inst->Next_1xx();
2319 }
2320
2321 ALWAYS_INLINE void SUB_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002322 uint4_t vregA = inst->VRegA_12x(inst_data);
2323 shadow_frame.SetVRegDouble(vregA,
2324 shadow_frame.GetVRegDouble(vregA) -
2325 shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
2326 inst = inst->Next_1xx();
2327 }
2328
2329 ALWAYS_INLINE void MUL_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002330 uint4_t vregA = inst->VRegA_12x(inst_data);
2331 shadow_frame.SetVRegDouble(vregA,
2332 shadow_frame.GetVRegDouble(vregA) *
2333 shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
2334 inst = inst->Next_1xx();
2335 }
2336
2337 ALWAYS_INLINE void DIV_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002338 uint4_t vregA = inst->VRegA_12x(inst_data);
2339 shadow_frame.SetVRegDouble(vregA,
2340 shadow_frame.GetVRegDouble(vregA) /
2341 shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
2342 inst = inst->Next_1xx();
2343 }
2344
2345 ALWAYS_INLINE void REM_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002346 uint4_t vregA = inst->VRegA_12x(inst_data);
2347 shadow_frame.SetVRegDouble(vregA,
2348 fmod(shadow_frame.GetVRegDouble(vregA),
2349 shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data))));
2350 inst = inst->Next_1xx();
2351 }
2352
2353 ALWAYS_INLINE void ADD_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002354 shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
2355 SafeAdd(shadow_frame.GetVReg(inst->VRegB_22s(inst_data)),
2356 inst->VRegC_22s()));
2357 inst = inst->Next_2xx();
2358 }
2359
2360 ALWAYS_INLINE void RSUB_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002361 shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
2362 SafeSub(inst->VRegC_22s(),
2363 shadow_frame.GetVReg(inst->VRegB_22s(inst_data))));
2364 inst = inst->Next_2xx();
2365 }
2366
2367 ALWAYS_INLINE void MUL_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002368 shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
2369 SafeMul(shadow_frame.GetVReg(inst->VRegB_22s(inst_data)),
2370 inst->VRegC_22s()));
2371 inst = inst->Next_2xx();
2372 }
2373
2374 ALWAYS_INLINE void DIV_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002375 bool success = DoIntDivide(shadow_frame, inst->VRegA_22s(inst_data),
2376 shadow_frame.GetVReg(inst->VRegB_22s(inst_data)),
2377 inst->VRegC_22s());
2378 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
2379 }
2380
2381 ALWAYS_INLINE void REM_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002382 bool success = DoIntRemainder(shadow_frame, inst->VRegA_22s(inst_data),
2383 shadow_frame.GetVReg(inst->VRegB_22s(inst_data)),
2384 inst->VRegC_22s());
2385 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
2386 }
2387
2388 ALWAYS_INLINE void AND_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002389 shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
2390 shadow_frame.GetVReg(inst->VRegB_22s(inst_data)) &
2391 inst->VRegC_22s());
2392 inst = inst->Next_2xx();
2393 }
2394
2395 ALWAYS_INLINE void OR_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002396 shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
2397 shadow_frame.GetVReg(inst->VRegB_22s(inst_data)) |
2398 inst->VRegC_22s());
2399 inst = inst->Next_2xx();
2400 }
2401
2402 ALWAYS_INLINE void XOR_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002403 shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
2404 shadow_frame.GetVReg(inst->VRegB_22s(inst_data)) ^
2405 inst->VRegC_22s());
2406 inst = inst->Next_2xx();
2407 }
2408
2409 ALWAYS_INLINE void ADD_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002410 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2411 SafeAdd(shadow_frame.GetVReg(inst->VRegB_22b()), inst->VRegC_22b()));
2412 inst = inst->Next_2xx();
2413 }
2414
2415 ALWAYS_INLINE void RSUB_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002416 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2417 SafeSub(inst->VRegC_22b(), shadow_frame.GetVReg(inst->VRegB_22b())));
2418 inst = inst->Next_2xx();
2419 }
2420
2421 ALWAYS_INLINE void MUL_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002422 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2423 SafeMul(shadow_frame.GetVReg(inst->VRegB_22b()), inst->VRegC_22b()));
2424 inst = inst->Next_2xx();
2425 }
2426
2427 ALWAYS_INLINE void DIV_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002428 bool success = DoIntDivide(shadow_frame, inst->VRegA_22b(inst_data),
2429 shadow_frame.GetVReg(inst->VRegB_22b()), inst->VRegC_22b());
2430 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
2431 }
2432
2433 ALWAYS_INLINE void REM_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002434 bool success = DoIntRemainder(shadow_frame, inst->VRegA_22b(inst_data),
2435 shadow_frame.GetVReg(inst->VRegB_22b()), inst->VRegC_22b());
2436 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
2437 }
2438
2439 ALWAYS_INLINE void AND_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002440 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2441 shadow_frame.GetVReg(inst->VRegB_22b()) &
2442 inst->VRegC_22b());
2443 inst = inst->Next_2xx();
2444 }
2445
2446 ALWAYS_INLINE void OR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002447 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2448 shadow_frame.GetVReg(inst->VRegB_22b()) |
2449 inst->VRegC_22b());
2450 inst = inst->Next_2xx();
2451 }
2452
2453 ALWAYS_INLINE void XOR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002454 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2455 shadow_frame.GetVReg(inst->VRegB_22b()) ^
2456 inst->VRegC_22b());
2457 inst = inst->Next_2xx();
2458 }
2459
2460 ALWAYS_INLINE void SHL_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002461 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2462 shadow_frame.GetVReg(inst->VRegB_22b()) <<
2463 (inst->VRegC_22b() & 0x1f));
2464 inst = inst->Next_2xx();
2465 }
2466
2467 ALWAYS_INLINE void SHR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002468 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2469 shadow_frame.GetVReg(inst->VRegB_22b()) >>
2470 (inst->VRegC_22b() & 0x1f));
2471 inst = inst->Next_2xx();
2472 }
2473
2474 ALWAYS_INLINE void USHR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002475 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2476 static_cast<uint32_t>(shadow_frame.GetVReg(inst->VRegB_22b())) >>
2477 (inst->VRegC_22b() & 0x1f));
2478 inst = inst->Next_2xx();
2479 }
2480
2481 ALWAYS_INLINE void UNUSED_3E() REQUIRES_SHARED(Locks::mutator_lock_) {
2482 UnexpectedOpcode(inst, shadow_frame);
2483 }
2484
2485 ALWAYS_INLINE void UNUSED_3F() REQUIRES_SHARED(Locks::mutator_lock_) {
2486 UnexpectedOpcode(inst, shadow_frame);
2487 }
2488
2489 ALWAYS_INLINE void UNUSED_40() REQUIRES_SHARED(Locks::mutator_lock_) {
2490 UnexpectedOpcode(inst, shadow_frame);
2491 }
2492
2493 ALWAYS_INLINE void UNUSED_41() REQUIRES_SHARED(Locks::mutator_lock_) {
2494 UnexpectedOpcode(inst, shadow_frame);
2495 }
2496
2497 ALWAYS_INLINE void UNUSED_42() REQUIRES_SHARED(Locks::mutator_lock_) {
2498 UnexpectedOpcode(inst, shadow_frame);
2499 }
2500
2501 ALWAYS_INLINE void UNUSED_43() REQUIRES_SHARED(Locks::mutator_lock_) {
2502 UnexpectedOpcode(inst, shadow_frame);
2503 }
2504
2505 ALWAYS_INLINE void UNUSED_79() REQUIRES_SHARED(Locks::mutator_lock_) {
2506 UnexpectedOpcode(inst, shadow_frame);
2507 }
2508
2509 ALWAYS_INLINE void UNUSED_7A() REQUIRES_SHARED(Locks::mutator_lock_) {
2510 UnexpectedOpcode(inst, shadow_frame);
2511 }
2512
2513 ALWAYS_INLINE void UNUSED_F3() REQUIRES_SHARED(Locks::mutator_lock_) {
2514 UnexpectedOpcode(inst, shadow_frame);
2515 }
2516
2517 ALWAYS_INLINE void UNUSED_F4() REQUIRES_SHARED(Locks::mutator_lock_) {
2518 UnexpectedOpcode(inst, shadow_frame);
2519 }
2520
2521 ALWAYS_INLINE void UNUSED_F5() REQUIRES_SHARED(Locks::mutator_lock_) {
2522 UnexpectedOpcode(inst, shadow_frame);
2523 }
2524
2525 ALWAYS_INLINE void UNUSED_F6() REQUIRES_SHARED(Locks::mutator_lock_) {
2526 UnexpectedOpcode(inst, shadow_frame);
2527 }
2528
2529 ALWAYS_INLINE void UNUSED_F7() REQUIRES_SHARED(Locks::mutator_lock_) {
2530 UnexpectedOpcode(inst, shadow_frame);
2531 }
2532
2533 ALWAYS_INLINE void UNUSED_F8() REQUIRES_SHARED(Locks::mutator_lock_) {
2534 UnexpectedOpcode(inst, shadow_frame);
2535 }
2536
2537 ALWAYS_INLINE void UNUSED_F9() REQUIRES_SHARED(Locks::mutator_lock_) {
2538 UnexpectedOpcode(inst, shadow_frame);
2539 }
2540
2541 ALWAYS_INLINE InstructionHandler(SwitchImplContext* ctx,
2542 const instrumentation::Instrumentation* instrumentation,
2543 Thread* self,
2544 ShadowFrame& shadow_frame,
2545 uint16_t dex_pc,
2546 const Instruction*& inst,
2547 uint16_t inst_data,
2548 bool& exit_interpreter_loop)
2549 : ctx(ctx),
2550 instrumentation(instrumentation),
2551 self(self),
2552 shadow_frame(shadow_frame),
2553 dex_pc(dex_pc),
2554 inst(inst),
2555 inst_data(inst_data),
2556 exit_interpreter_loop(exit_interpreter_loop) {
2557 }
2558
2559 private:
2560 static constexpr bool do_assignability_check = do_access_check;
2561
2562 const CodeItemDataAccessor& Accessor() { return ctx->accessor; }
2563 const uint16_t* Insns() { return ctx->accessor.Insns(); }
2564 JValue* ResultRegister() { return &ctx->result_register; }
2565
2566 SwitchImplContext* const ctx;
2567 const instrumentation::Instrumentation* const instrumentation;
2568 Thread* const self;
2569 ShadowFrame& shadow_frame;
2570 uint32_t const dex_pc;
2571 const Instruction*& inst;
2572 uint16_t const inst_data;
2573 bool& exit_interpreter_loop;
2574};
2575
David Srbecky6da82472018-10-23 14:03:08 +01002576#undef BRANCH_INSTRUMENTATION
David Srbecky6da82472018-10-23 14:03:08 +01002577#undef POSSIBLY_HANDLE_PENDING_EXCEPTION
2578#undef POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE
2579#undef POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC
David Srbecky6da82472018-10-23 14:03:08 +01002580#undef HANDLE_PENDING_EXCEPTION
David Srbecky6da82472018-10-23 14:03:08 +01002581
Alex Light6f22e062018-10-05 15:05:12 -07002582// TODO On ASAN builds this function gets a huge stack frame. Since normally we run in the mterp
2583// this shouldn't cause any problems for stack overflow detection. Remove this once b/117341496 is
2584// fixed.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +01002585template<bool do_access_check, bool transaction_active>
Alex Light6f22e062018-10-05 15:05:12 -07002586ATTRIBUTE_NO_SANITIZE_ADDRESS void ExecuteSwitchImplCpp(SwitchImplContext* ctx) {
David Srbecky946bb092018-03-09 17:23:01 +00002587 Thread* self = ctx->self;
2588 const CodeItemDataAccessor& accessor = ctx->accessor;
2589 ShadowFrame& shadow_frame = ctx->shadow_frame;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002590 if (UNLIKELY(!shadow_frame.HasReferenceArray())) {
2591 LOG(FATAL) << "Invalid shadow frame for interpreter use";
David Srbecky946bb092018-03-09 17:23:01 +00002592 ctx->result = JValue();
2593 return;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002594 }
2595 self->VerifyStack();
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002596
2597 uint32_t dex_pc = shadow_frame.GetDexPC();
Mathieu Chartier2cebb242015-04-21 16:50:40 -07002598 const auto* const instrumentation = Runtime::Current()->GetInstrumentation();
Mathieu Chartier808c7a52017-12-15 11:19:33 -08002599 const uint16_t* const insns = accessor.Insns();
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002600 const Instruction* inst = Instruction::At(insns + dex_pc);
Sebastien Hertz3b588e02013-09-11 14:33:18 +02002601 uint16_t inst_data;
Igor Murashkin6918bf12015-09-27 19:19:06 -07002602
Alex Light0aa7a5a2018-10-10 15:58:14 +00002603 DCHECK(!shadow_frame.GetForceRetryInstruction())
2604 << "Entered interpreter from invoke without retry instruction being handled!";
2605
David Srbecky6da82472018-10-23 14:03:08 +01002606 bool const interpret_one_instruction = ctx->interpret_one_instruction;
2607 while (true) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002608 dex_pc = inst->GetDexPc(insns);
2609 shadow_frame.SetDexPC(dex_pc);
Ian Rogerse94652f2014-12-02 11:13:19 -08002610 TraceExecution(shadow_frame, inst, dex_pc);
Sebastien Hertz3b588e02013-09-11 14:33:18 +02002611 inst_data = inst->Fetch16(0);
David Srbeckya4a96af2018-10-31 16:34:58 +00002612 {
2613 bool exit_loop = false;
2614 InstructionHandler<do_access_check, transaction_active> handler(
2615 ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, exit_loop);
2616 if (!handler.Preamble()) {
2617 if (UNLIKELY(exit_loop)) {
2618 return;
2619 }
2620 if (UNLIKELY(interpret_one_instruction)) {
2621 break;
2622 }
2623 continue;
2624 }
2625 }
Sebastien Hertz3b588e02013-09-11 14:33:18 +02002626 switch (inst->Opcode(inst_data)) {
David Srbecky6da82472018-10-23 14:03:08 +01002627#define OPCODE_CASE(OPCODE, OPCODE_NAME, pname, f, i, a, e, v) \
2628 case OPCODE: { \
2629 bool exit_loop = false; \
2630 InstructionHandler<do_access_check, transaction_active> handler( \
2631 ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, exit_loop); \
David Srbeckya4a96af2018-10-31 16:34:58 +00002632 handler.OPCODE_NAME(); \
David Srbecky6da82472018-10-23 14:03:08 +01002633 /* TODO: Advance 'inst' here, instead of explicitly in each handler */ \
2634 if (UNLIKELY(exit_loop)) { \
2635 return; \
2636 } \
2637 break; \
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002638 }
David Srbecky6da82472018-10-23 14:03:08 +01002639DEX_INSTRUCTION_LIST(OPCODE_CASE)
2640#undef OPCODE_CASE
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002641 }
David Srbecky6da82472018-10-23 14:03:08 +01002642 if (UNLIKELY(interpret_one_instruction)) {
David Srbeckya4a96af2018-10-31 16:34:58 +00002643 break;
David Srbecky6da82472018-10-23 14:03:08 +01002644 }
2645 }
David Srbeckya4a96af2018-10-31 16:34:58 +00002646 // Record where we stopped.
2647 shadow_frame.SetDexPC(inst->GetDexPc(insns));
2648 ctx->result = ctx->result_register;
2649 return;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002650} // NOLINT(readability/fn_size)
2651
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002652} // namespace interpreter
2653} // namespace art
David Srbecky2ee09ff2018-10-24 13:24:22 +01002654
2655#endif // ART_RUNTIME_INTERPRETER_INTERPRETER_SWITCH_IMPL_INL_H_