blob: 4125a0a0436f17804b38b3476bcba7cdb23db6d2 [file] [log] [blame]
Sebastien Hertz8ece0502013-08-07 11:26:41 +02001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
David Srbecky2ee09ff2018-10-24 13:24:22 +010017#ifndef ART_RUNTIME_INTERPRETER_INTERPRETER_SWITCH_IMPL_INL_H_
18#define ART_RUNTIME_INTERPRETER_INTERPRETER_SWITCH_IMPL_INL_H_
19
Andreas Gampe5e26eb12016-08-22 17:54:17 -070020#include "interpreter_switch_impl.h"
21
Andreas Gampe542451c2016-07-26 09:02:02 -070022#include "base/enums.h"
Alex Light6f22e062018-10-05 15:05:12 -070023#include "base/memory_tool.h"
David Sehrc431b9d2018-03-02 12:01:51 -080024#include "base/quasi_atomic.h"
David Sehr9e734c72018-01-04 17:56:19 -080025#include "dex/dex_file_types.h"
David Srbecky6da82472018-10-23 14:03:08 +010026#include "dex/dex_instruction_list.h"
Alex Lighteb7c1442015-08-31 13:17:42 -070027#include "experimental_flags.h"
Sebastien Hertz8ece0502013-08-07 11:26:41 +020028#include "interpreter_common.h"
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +000029#include "jit/jit.h"
Mathieu Chartier28bd2e42016-10-04 13:54:57 -070030#include "jvalue-inl.h"
Andreas Gampefd63bbf2018-10-29 12:55:35 -070031#include "mirror/string-alloc-inl.h"
Alex Light0aa7a5a2018-10-10 15:58:14 +000032#include "nth_caller_visitor.h"
Ian Rogersf72a11d2014-10-30 15:41:08 -070033#include "safe_math.h"
Vladimir Marko6ec2a1b2018-05-22 15:33:48 +010034#include "shadow_frame-inl.h"
Alex Light0aa7a5a2018-10-10 15:58:14 +000035#include "thread.h"
Sebastien Hertz8ece0502013-08-07 11:26:41 +020036
37namespace art {
38namespace interpreter {
39
David Srbecky6da82472018-10-23 14:03:08 +010040// Short-lived helper class which executes single DEX bytecode. It is inlined by compiler.
41//
42// The function names must match the names from dex_instruction_list.h and have no arguments.
43//
44// Any relevant execution information is stored in the fields - it should be kept to minimum.
45//
David Srbecky47ad3762018-10-31 12:43:40 +000046// Helper methods may return boolean value - in which case 'false' always means
47// "stop executing current opcode" (which does not necessarily exit the interpreter loop).
48//
David Srbecky6da82472018-10-23 14:03:08 +010049template<bool do_access_check, bool transaction_active>
50class InstructionHandler {
51 public:
David Srbecky47ad3762018-10-31 12:43:40 +000052 ALWAYS_INLINE WARN_UNUSED bool CheckForceReturn()
53 REQUIRES_SHARED(Locks::mutator_lock_) {
54 if (UNLIKELY(shadow_frame.GetForcePopFrame())) {
55 DCHECK(PrevFrameWillRetry(self, shadow_frame))
56 << "Pop frame forced without previous frame ready to retry instruction!";
57 DCHECK(Runtime::Current()->AreNonStandardExitsEnabled());
58 if (UNLIKELY(NeedsMethodExitEvent(instrumentation))) {
59 SendMethodExitEvents(self,
60 instrumentation,
61 shadow_frame,
62 shadow_frame.GetThisObject(Accessor().InsSize()),
63 shadow_frame.GetMethod(),
64 inst->GetDexPc(Insns()),
65 JValue());
66 }
67 ctx->result = JValue(); /* Handled in caller. */
68 exit_interpreter_loop = true;
69 return false;
70 }
71 return true;
72 }
73
74 ALWAYS_INLINE WARN_UNUSED bool HandlePendingExceptionWithInstrumentation(
75 const instrumentation::Instrumentation* instr)
76 REQUIRES_SHARED(Locks::mutator_lock_) {
77 DCHECK(self->IsExceptionPending());
78 self->AllowThreadSuspension();
79 if (!CheckForceReturn()) {
80 return false;
81 }
82 if (!MoveToExceptionHandler(self, shadow_frame, instr)) {
83 /* Structured locking is to be enforced for abnormal termination, too. */
84 DoMonitorCheckOnExit<do_assignability_check>(self, &shadow_frame);
85 if (ctx->interpret_one_instruction) {
86 /* Signal mterp to return to caller */
87 shadow_frame.SetDexPC(dex::kDexNoIndex);
88 }
89 ctx->result = JValue(); /* Handled in caller. */
90 exit_interpreter_loop = true;
91 return false; // Return to caller.
92 }
93 if (!CheckForceReturn()) {
94 return false;
95 }
96 int32_t displacement =
97 static_cast<int32_t>(shadow_frame.GetDexPC()) - static_cast<int32_t>(dex_pc);
98 inst = inst->RelativeAt(displacement);
99 return false; // Stop executing this opcode and continue in the exception handler.
100 }
101
102 ALWAYS_INLINE WARN_UNUSED bool HandlePendingException()
103 REQUIRES_SHARED(Locks::mutator_lock_) {
104 return HandlePendingExceptionWithInstrumentation(instrumentation);
105 }
106
107 ALWAYS_INLINE WARN_UNUSED bool PossiblyHandlePendingExceptionOnInvokeImpl(
108 bool is_exception_pending,
109 const Instruction* next_inst)
110 REQUIRES_SHARED(Locks::mutator_lock_) {
111 if (UNLIKELY(shadow_frame.GetForceRetryInstruction())) {
112 /* Don't need to do anything except clear the flag and exception. We leave the */
113 /* instruction the same so it will be re-executed on the next go-around. */
114 DCHECK(inst->IsInvoke());
115 shadow_frame.SetForceRetryInstruction(false);
116 if (UNLIKELY(is_exception_pending)) {
117 DCHECK(self->IsExceptionPending());
118 if (kIsDebugBuild) {
119 LOG(WARNING) << "Suppressing exception for instruction-retry: "
120 << self->GetException()->Dump();
121 }
122 self->ClearException();
123 }
124 } else if (UNLIKELY(is_exception_pending)) {
125 /* Should have succeeded. */
126 DCHECK(!shadow_frame.GetForceRetryInstruction());
127 if (!HandlePendingException()) {
128 return false;
129 }
130 } else {
131 inst = next_inst;
132 }
133 return true;
134 }
135
136 ALWAYS_INLINE WARN_UNUSED bool PossiblyHandlePendingException(
137 bool is_exception_pending,
138 const Instruction* next_inst)
139 REQUIRES_SHARED(Locks::mutator_lock_) {
140 /* Should only be on invoke instructions. */
141 DCHECK(!shadow_frame.GetForceRetryInstruction());
142 if (UNLIKELY(is_exception_pending)) {
143 if (!HandlePendingException()) {
144 return false;
145 }
146 } else {
147 inst = next_inst;
148 }
149 return true;
150 }
151
152 ALWAYS_INLINE WARN_UNUSED bool HandleMonitorChecks()
153 REQUIRES_SHARED(Locks::mutator_lock_) {
154 if (!DoMonitorCheckOnExit<do_assignability_check>(self, &shadow_frame)) {
155 if (!HandlePendingException()) {
156 return false;
157 }
158 }
159 return true;
160 }
161
162 // Code to run before each dex instruction.
163 ALWAYS_INLINE WARN_UNUSED bool PreambleSave(JValue* save_ref)
164 REQUIRES_SHARED(Locks::mutator_lock_) {
165 /* We need to put this before & after the instrumentation to avoid having to put in a */
166 /* post-script macro. */
167 if (!CheckForceReturn()) {
168 return false;
169 }
170 if (UNLIKELY(instrumentation->HasDexPcListeners())) {
171 if (UNLIKELY(!DoDexPcMoveEvent(self,
172 Accessor(),
173 shadow_frame,
174 dex_pc,
175 instrumentation,
176 save_ref))) {
177 if (!HandlePendingException()) {
178 return false;
179 }
180 }
181 if (!CheckForceReturn()) {
182 return false;
183 }
184 }
185 return true;
186 }
187
188 ALWAYS_INLINE WARN_UNUSED bool BranchInstrumentation(int32_t offset)
189 REQUIRES_SHARED(Locks::mutator_lock_) {
190 if (UNLIKELY(instrumentation->HasBranchListeners())) {
191 instrumentation->Branch(self, shadow_frame.GetMethod(), dex_pc, offset);
192 }
193 JValue result;
194 if (jit::Jit::MaybeDoOnStackReplacement(self,
195 shadow_frame.GetMethod(),
196 dex_pc,
197 offset,
198 &result)) {
199 if (ctx->interpret_one_instruction) {
200 /* OSR has completed execution of the method. Signal mterp to return to caller */
201 shadow_frame.SetDexPC(dex::kDexNoIndex);
202 }
203 ctx->result = result;
204 exit_interpreter_loop = true;
205 return false;
206 }
207 return true;
208 }
209
210 ALWAYS_INLINE void HotnessUpdate()
211 REQUIRES_SHARED(Locks::mutator_lock_) {
212 jit::Jit* jit = Runtime::Current()->GetJit();
213 if (jit != nullptr) {
214 jit->AddSamples(self, shadow_frame.GetMethod(), 1, /*with_backedges=*/ true);
215 }
216 }
217
218 ALWAYS_INLINE WARN_UNUSED bool HandleAsyncException()
219 REQUIRES_SHARED(Locks::mutator_lock_) {
220 if (UNLIKELY(self->ObserveAsyncException())) {
221 if (!HandlePendingException()) {
222 return false;
223 }
224 }
225 return true;
226 }
227
228 ALWAYS_INLINE void HandleBackwardBranch(int32_t offset)
229 REQUIRES_SHARED(Locks::mutator_lock_) {
230 if (IsBackwardBranch(offset)) {
231 HotnessUpdate();
232 /* Record new dex pc early to have consistent suspend point at loop header. */
233 shadow_frame.SetDexPC(inst->GetDexPc(Insns()));
234 self->AllowThreadSuspension();
235 }
236 }
237
238 // Unlike most other events the DexPcMovedEvent can be sent when there is a pending exception (if
239 // the next instruction is MOVE_EXCEPTION). This means it needs to be handled carefully to be able
240 // to detect exceptions thrown by the DexPcMovedEvent itself. These exceptions could be thrown by
241 // jvmti-agents while handling breakpoint or single step events. We had to move this into its own
242 // function because it was making ExecuteSwitchImpl have too large a stack.
243 NO_INLINE static bool DoDexPcMoveEvent(Thread* self,
244 const CodeItemDataAccessor& accessor,
245 const ShadowFrame& shadow_frame,
246 uint32_t dex_pc,
247 const instrumentation::Instrumentation* instrumentation,
248 JValue* save_ref)
249 REQUIRES_SHARED(Locks::mutator_lock_) {
250 DCHECK(instrumentation->HasDexPcListeners());
251 StackHandleScope<2> hs(self);
252 Handle<mirror::Throwable> thr(hs.NewHandle(self->GetException()));
253 mirror::Object* null_obj = nullptr;
254 HandleWrapper<mirror::Object> h(
255 hs.NewHandleWrapper(LIKELY(save_ref == nullptr) ? &null_obj : save_ref->GetGCRoot()));
256 self->ClearException();
257 instrumentation->DexPcMovedEvent(self,
258 shadow_frame.GetThisObject(accessor.InsSize()),
259 shadow_frame.GetMethod(),
260 dex_pc);
261 if (UNLIKELY(self->IsExceptionPending())) {
262 // We got a new exception in the dex-pc-moved event.
263 // We just let this exception replace the old one.
264 // TODO It would be good to add the old exception to the
265 // suppressed exceptions of the new one if possible.
266 return false;
267 } else {
268 if (UNLIKELY(!thr.IsNull())) {
269 self->SetException(thr.Get());
270 }
271 return true;
272 }
273 }
274
275 static bool NeedsMethodExitEvent(const instrumentation::Instrumentation* ins)
276 REQUIRES_SHARED(Locks::mutator_lock_) {
277 return ins->HasMethodExitListeners() || ins->HasWatchedFramePopListeners();
278 }
279
280 // Sends the normal method exit event.
281 // Returns true if the events succeeded and false if there is a pending exception.
282 NO_INLINE static bool SendMethodExitEvents(
283 Thread* self,
284 const instrumentation::Instrumentation* instrumentation,
285 const ShadowFrame& frame,
286 ObjPtr<mirror::Object> thiz,
287 ArtMethod* method,
288 uint32_t dex_pc,
289 const JValue& result)
290 REQUIRES_SHARED(Locks::mutator_lock_) {
291 bool had_event = false;
292 // We don't send method-exit if it's a pop-frame. We still send frame_popped though.
293 if (UNLIKELY(instrumentation->HasMethodExitListeners() && !frame.GetForcePopFrame())) {
294 had_event = true;
295 instrumentation->MethodExitEvent(self, thiz.Ptr(), method, dex_pc, result);
296 }
297 if (UNLIKELY(frame.NeedsNotifyPop() && instrumentation->HasWatchedFramePopListeners())) {
298 had_event = true;
299 instrumentation->WatchedFramePopped(self, frame);
300 }
301 if (UNLIKELY(had_event)) {
302 return !self->IsExceptionPending();
303 } else {
304 return true;
305 }
306 }
307
308#define BRANCH_INSTRUMENTATION(offset) \
309 if (!BranchInstrumentation(offset)) { \
310 return; \
311 }
312
313#define HANDLE_PENDING_EXCEPTION() \
314 if (!HandlePendingException()) { \
315 return; \
316 }
317
318#define POSSIBLY_HANDLE_PENDING_EXCEPTION(is_exception_pending, next_function) \
319 if (!PossiblyHandlePendingException(is_exception_pending, inst->next_function())) { \
320 return; \
321 }
322
323#define POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(is_exception_pending) \
324 if (!PossiblyHandlePendingExceptionOnInvokeImpl(is_exception_pending, inst->Next_4xx())) { \
325 return; \
326 }
327
328#define POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(is_exception_pending) \
329 if (!PossiblyHandlePendingExceptionOnInvokeImpl(is_exception_pending, inst->Next_3xx())) { \
330 return; \
331 }
332
David Srbecky6da82472018-10-23 14:03:08 +0100333 ALWAYS_INLINE void NOP() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100334 inst = inst->Next_1xx();
335 }
336
337 ALWAYS_INLINE void MOVE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100338 shadow_frame.SetVReg(inst->VRegA_12x(inst_data),
339 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
340 inst = inst->Next_1xx();
341 }
342
343 ALWAYS_INLINE void MOVE_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100344 shadow_frame.SetVReg(inst->VRegA_22x(inst_data),
345 shadow_frame.GetVReg(inst->VRegB_22x()));
346 inst = inst->Next_2xx();
347 }
348
349 ALWAYS_INLINE void MOVE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100350 shadow_frame.SetVReg(inst->VRegA_32x(),
351 shadow_frame.GetVReg(inst->VRegB_32x()));
352 inst = inst->Next_3xx();
353 }
354
355 ALWAYS_INLINE void MOVE_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100356 shadow_frame.SetVRegLong(inst->VRegA_12x(inst_data),
357 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
358 inst = inst->Next_1xx();
359 }
360
361 ALWAYS_INLINE void MOVE_WIDE_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100362 shadow_frame.SetVRegLong(inst->VRegA_22x(inst_data),
363 shadow_frame.GetVRegLong(inst->VRegB_22x()));
364 inst = inst->Next_2xx();
365 }
366
367 ALWAYS_INLINE void MOVE_WIDE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100368 shadow_frame.SetVRegLong(inst->VRegA_32x(),
369 shadow_frame.GetVRegLong(inst->VRegB_32x()));
370 inst = inst->Next_3xx();
371 }
372
373 ALWAYS_INLINE void MOVE_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100374 shadow_frame.SetVRegReference(inst->VRegA_12x(inst_data),
375 shadow_frame.GetVRegReference(inst->VRegB_12x(inst_data)));
376 inst = inst->Next_1xx();
377 }
378
379 ALWAYS_INLINE void MOVE_OBJECT_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100380 shadow_frame.SetVRegReference(inst->VRegA_22x(inst_data),
381 shadow_frame.GetVRegReference(inst->VRegB_22x()));
382 inst = inst->Next_2xx();
383 }
384
385 ALWAYS_INLINE void MOVE_OBJECT_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100386 shadow_frame.SetVRegReference(inst->VRegA_32x(),
387 shadow_frame.GetVRegReference(inst->VRegB_32x()));
388 inst = inst->Next_3xx();
389 }
390
391 ALWAYS_INLINE void MOVE_RESULT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100392 shadow_frame.SetVReg(inst->VRegA_11x(inst_data), ResultRegister()->GetI());
393 inst = inst->Next_1xx();
394 }
395
396 ALWAYS_INLINE void MOVE_RESULT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100397 shadow_frame.SetVRegLong(inst->VRegA_11x(inst_data), ResultRegister()->GetJ());
398 inst = inst->Next_1xx();
399 }
400
401 ALWAYS_INLINE void MOVE_RESULT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100402 shadow_frame.SetVRegReference(inst->VRegA_11x(inst_data), ResultRegister()->GetL());
403 inst = inst->Next_1xx();
404 }
405
406 ALWAYS_INLINE void MOVE_EXCEPTION() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100407 ObjPtr<mirror::Throwable> exception = self->GetException();
408 DCHECK(exception != nullptr) << "No pending exception on MOVE_EXCEPTION instruction";
409 shadow_frame.SetVRegReference(inst->VRegA_11x(inst_data), exception);
410 self->ClearException();
411 inst = inst->Next_1xx();
412 }
413
414 ALWAYS_INLINE void RETURN_VOID_NO_BARRIER() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100415 JValue result;
416 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000417 if (!HandleMonitorChecks()) {
418 return;
419 }
David Srbecky6da82472018-10-23 14:03:08 +0100420 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
421 !SendMethodExitEvents(self,
422 instrumentation,
423 shadow_frame,
424 shadow_frame.GetThisObject(Accessor().InsSize()),
425 shadow_frame.GetMethod(),
426 inst->GetDexPc(Insns()),
427 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000428 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
429 return;
430 }
David Srbecky6da82472018-10-23 14:03:08 +0100431 }
432 if (ctx->interpret_one_instruction) {
433 /* Signal mterp to return to caller */
434 shadow_frame.SetDexPC(dex::kDexNoIndex);
435 }
436 ctx->result = result;
437 exit_interpreter_loop = true;
438 }
439
440 ALWAYS_INLINE void RETURN_VOID() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100441 QuasiAtomic::ThreadFenceForConstructor();
442 JValue result;
443 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000444 if (!HandleMonitorChecks()) {
445 return;
446 }
David Srbecky6da82472018-10-23 14:03:08 +0100447 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
448 !SendMethodExitEvents(self,
449 instrumentation,
450 shadow_frame,
451 shadow_frame.GetThisObject(Accessor().InsSize()),
452 shadow_frame.GetMethod(),
453 inst->GetDexPc(Insns()),
454 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000455 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
456 return;
457 }
David Srbecky6da82472018-10-23 14:03:08 +0100458 }
459 if (ctx->interpret_one_instruction) {
460 /* Signal mterp to return to caller */
461 shadow_frame.SetDexPC(dex::kDexNoIndex);
462 }
463 ctx->result = result;
464 exit_interpreter_loop = true;
465 }
466
467 ALWAYS_INLINE void RETURN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100468 JValue result;
469 result.SetJ(0);
470 result.SetI(shadow_frame.GetVReg(inst->VRegA_11x(inst_data)));
471 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000472 if (!HandleMonitorChecks()) {
473 return;
474 }
David Srbecky6da82472018-10-23 14:03:08 +0100475 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
476 !SendMethodExitEvents(self,
477 instrumentation,
478 shadow_frame,
479 shadow_frame.GetThisObject(Accessor().InsSize()),
480 shadow_frame.GetMethod(),
481 inst->GetDexPc(Insns()),
482 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000483 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
484 return;
485 }
David Srbecky6da82472018-10-23 14:03:08 +0100486 }
487 if (ctx->interpret_one_instruction) {
488 /* Signal mterp to return to caller */
489 shadow_frame.SetDexPC(dex::kDexNoIndex);
490 }
491 ctx->result = result;
492 exit_interpreter_loop = true;
493 }
494
495 ALWAYS_INLINE void RETURN_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100496 JValue result;
497 result.SetJ(shadow_frame.GetVRegLong(inst->VRegA_11x(inst_data)));
498 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000499 if (!HandleMonitorChecks()) {
500 return;
501 }
David Srbecky6da82472018-10-23 14:03:08 +0100502 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
503 !SendMethodExitEvents(self,
504 instrumentation,
505 shadow_frame,
506 shadow_frame.GetThisObject(Accessor().InsSize()),
507 shadow_frame.GetMethod(),
508 inst->GetDexPc(Insns()),
509 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000510 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
511 return;
512 }
David Srbecky6da82472018-10-23 14:03:08 +0100513 }
514 if (ctx->interpret_one_instruction) {
515 /* Signal mterp to return to caller */
516 shadow_frame.SetDexPC(dex::kDexNoIndex);
517 }
518 ctx->result = result;
519 exit_interpreter_loop = true;
520 }
521
522 ALWAYS_INLINE void RETURN_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100523 JValue result;
524 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000525 if (!HandleMonitorChecks()) {
526 return;
527 }
David Srbecky6da82472018-10-23 14:03:08 +0100528 const size_t ref_idx = inst->VRegA_11x(inst_data);
529 ObjPtr<mirror::Object> obj_result = shadow_frame.GetVRegReference(ref_idx);
530 if (do_assignability_check && obj_result != nullptr) {
531 ObjPtr<mirror::Class> return_type = shadow_frame.GetMethod()->ResolveReturnType();
532 // Re-load since it might have moved.
533 obj_result = shadow_frame.GetVRegReference(ref_idx);
534 if (return_type == nullptr) {
535 // Return the pending exception.
536 HANDLE_PENDING_EXCEPTION();
537 }
538 if (!obj_result->VerifierInstanceOf(return_type)) {
539 // This should never happen.
540 std::string temp1, temp2;
541 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
542 "Returning '%s' that is not instance of return type '%s'",
543 obj_result->GetClass()->GetDescriptor(&temp1),
544 return_type->GetDescriptor(&temp2));
545 HANDLE_PENDING_EXCEPTION();
546 }
547 }
548 result.SetL(obj_result);
549 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
550 !SendMethodExitEvents(self,
551 instrumentation,
552 shadow_frame,
553 shadow_frame.GetThisObject(Accessor().InsSize()),
554 shadow_frame.GetMethod(),
555 inst->GetDexPc(Insns()),
556 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000557 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
558 return;
559 }
David Srbecky6da82472018-10-23 14:03:08 +0100560 }
561 // Re-load since it might have moved during the MethodExitEvent.
562 result.SetL(shadow_frame.GetVRegReference(ref_idx));
563 if (ctx->interpret_one_instruction) {
564 /* Signal mterp to return to caller */
565 shadow_frame.SetDexPC(dex::kDexNoIndex);
566 }
567 ctx->result = result;
568 exit_interpreter_loop = true;
569 }
570
571 ALWAYS_INLINE void CONST_4() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100572 uint4_t dst = inst->VRegA_11n(inst_data);
573 int4_t val = inst->VRegB_11n(inst_data);
574 shadow_frame.SetVReg(dst, val);
575 if (val == 0) {
576 shadow_frame.SetVRegReference(dst, nullptr);
577 }
578 inst = inst->Next_1xx();
579 }
580
581 ALWAYS_INLINE void CONST_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100582 uint8_t dst = inst->VRegA_21s(inst_data);
583 int16_t val = inst->VRegB_21s();
584 shadow_frame.SetVReg(dst, val);
585 if (val == 0) {
586 shadow_frame.SetVRegReference(dst, nullptr);
587 }
588 inst = inst->Next_2xx();
589 }
590
591 ALWAYS_INLINE void CONST() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100592 uint8_t dst = inst->VRegA_31i(inst_data);
593 int32_t val = inst->VRegB_31i();
594 shadow_frame.SetVReg(dst, val);
595 if (val == 0) {
596 shadow_frame.SetVRegReference(dst, nullptr);
597 }
598 inst = inst->Next_3xx();
599 }
600
601 ALWAYS_INLINE void CONST_HIGH16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100602 uint8_t dst = inst->VRegA_21h(inst_data);
603 int32_t val = static_cast<int32_t>(inst->VRegB_21h() << 16);
604 shadow_frame.SetVReg(dst, val);
605 if (val == 0) {
606 shadow_frame.SetVRegReference(dst, nullptr);
607 }
608 inst = inst->Next_2xx();
609 }
610
611 ALWAYS_INLINE void CONST_WIDE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100612 shadow_frame.SetVRegLong(inst->VRegA_21s(inst_data), inst->VRegB_21s());
613 inst = inst->Next_2xx();
614 }
615
616 ALWAYS_INLINE void CONST_WIDE_32() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100617 shadow_frame.SetVRegLong(inst->VRegA_31i(inst_data), inst->VRegB_31i());
618 inst = inst->Next_3xx();
619 }
620
621 ALWAYS_INLINE void CONST_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100622 shadow_frame.SetVRegLong(inst->VRegA_51l(inst_data), inst->VRegB_51l());
623 inst = inst->Next_51l();
624 }
625
626 ALWAYS_INLINE void CONST_WIDE_HIGH16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100627 shadow_frame.SetVRegLong(inst->VRegA_21h(inst_data),
628 static_cast<uint64_t>(inst->VRegB_21h()) << 48);
629 inst = inst->Next_2xx();
630 }
631
632 ALWAYS_INLINE void CONST_STRING() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100633 ObjPtr<mirror::String> s = ResolveString(self,
634 shadow_frame,
635 dex::StringIndex(inst->VRegB_21c()));
636 if (UNLIKELY(s == nullptr)) {
637 HANDLE_PENDING_EXCEPTION();
638 } else {
639 shadow_frame.SetVRegReference(inst->VRegA_21c(inst_data), s);
640 inst = inst->Next_2xx();
641 }
642 }
643
644 ALWAYS_INLINE void CONST_STRING_JUMBO() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100645 ObjPtr<mirror::String> s = ResolveString(self,
646 shadow_frame,
647 dex::StringIndex(inst->VRegB_31c()));
648 if (UNLIKELY(s == nullptr)) {
649 HANDLE_PENDING_EXCEPTION();
650 } else {
651 shadow_frame.SetVRegReference(inst->VRegA_31c(inst_data), s);
652 inst = inst->Next_3xx();
653 }
654 }
655
656 ALWAYS_INLINE void CONST_CLASS() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100657 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(inst->VRegB_21c()),
658 shadow_frame.GetMethod(),
659 self,
660 false,
661 do_access_check);
662 if (UNLIKELY(c == nullptr)) {
663 HANDLE_PENDING_EXCEPTION();
664 } else {
665 shadow_frame.SetVRegReference(inst->VRegA_21c(inst_data), c);
666 inst = inst->Next_2xx();
667 }
668 }
669
670 ALWAYS_INLINE void CONST_METHOD_HANDLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100671 ClassLinker* cl = Runtime::Current()->GetClassLinker();
672 ObjPtr<mirror::MethodHandle> mh = cl->ResolveMethodHandle(self,
673 inst->VRegB_21c(),
674 shadow_frame.GetMethod());
675 if (UNLIKELY(mh == nullptr)) {
676 HANDLE_PENDING_EXCEPTION();
677 } else {
678 shadow_frame.SetVRegReference(inst->VRegA_21c(inst_data), mh);
679 inst = inst->Next_2xx();
680 }
681 }
682
683 ALWAYS_INLINE void CONST_METHOD_TYPE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100684 ClassLinker* cl = Runtime::Current()->GetClassLinker();
685 ObjPtr<mirror::MethodType> mt = cl->ResolveMethodType(self,
686 dex::ProtoIndex(inst->VRegB_21c()),
687 shadow_frame.GetMethod());
688 if (UNLIKELY(mt == nullptr)) {
689 HANDLE_PENDING_EXCEPTION();
690 } else {
691 shadow_frame.SetVRegReference(inst->VRegA_21c(inst_data), mt);
692 inst = inst->Next_2xx();
693 }
694 }
695
696 ALWAYS_INLINE void MONITOR_ENTER() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000697 if (!HandleAsyncException()) {
698 return;
699 }
David Srbecky6da82472018-10-23 14:03:08 +0100700 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data));
701 if (UNLIKELY(obj == nullptr)) {
702 ThrowNullPointerExceptionFromInterpreter();
703 HANDLE_PENDING_EXCEPTION();
704 } else {
705 DoMonitorEnter<do_assignability_check>(self, &shadow_frame, obj);
706 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
707 }
708 }
709
710 ALWAYS_INLINE void MONITOR_EXIT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000711 if (!HandleAsyncException()) {
712 return;
713 }
David Srbecky6da82472018-10-23 14:03:08 +0100714 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data));
715 if (UNLIKELY(obj == nullptr)) {
716 ThrowNullPointerExceptionFromInterpreter();
717 HANDLE_PENDING_EXCEPTION();
718 } else {
719 DoMonitorExit<do_assignability_check>(self, &shadow_frame, obj);
720 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
721 }
722 }
723
724 ALWAYS_INLINE void CHECK_CAST() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100725 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(inst->VRegB_21c()),
726 shadow_frame.GetMethod(),
727 self,
728 false,
729 do_access_check);
730 if (UNLIKELY(c == nullptr)) {
731 HANDLE_PENDING_EXCEPTION();
732 } else {
733 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(inst->VRegA_21c(inst_data));
734 if (UNLIKELY(obj != nullptr && !obj->InstanceOf(c))) {
735 ThrowClassCastException(c, obj->GetClass());
736 HANDLE_PENDING_EXCEPTION();
737 } else {
738 inst = inst->Next_2xx();
739 }
740 }
741 }
742
743 ALWAYS_INLINE void INSTANCE_OF() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100744 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(inst->VRegC_22c()),
745 shadow_frame.GetMethod(),
746 self,
747 false,
748 do_access_check);
749 if (UNLIKELY(c == nullptr)) {
750 HANDLE_PENDING_EXCEPTION();
751 } else {
752 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
753 shadow_frame.SetVReg(inst->VRegA_22c(inst_data),
754 (obj != nullptr && obj->InstanceOf(c)) ? 1 : 0);
755 inst = inst->Next_2xx();
756 }
757 }
758
759 ALWAYS_INLINE void ARRAY_LENGTH() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100760 ObjPtr<mirror::Object> array = shadow_frame.GetVRegReference(inst->VRegB_12x(inst_data));
761 if (UNLIKELY(array == nullptr)) {
762 ThrowNullPointerExceptionFromInterpreter();
763 HANDLE_PENDING_EXCEPTION();
764 } else {
765 shadow_frame.SetVReg(inst->VRegA_12x(inst_data), array->AsArray()->GetLength());
766 inst = inst->Next_1xx();
767 }
768 }
769
770 ALWAYS_INLINE void NEW_INSTANCE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100771 ObjPtr<mirror::Object> obj = nullptr;
772 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(inst->VRegB_21c()),
773 shadow_frame.GetMethod(),
774 self,
775 false,
776 do_access_check);
777 if (LIKELY(c != nullptr)) {
778 if (UNLIKELY(c->IsStringClass())) {
779 gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
780 obj = mirror::String::AllocEmptyString<true>(self, allocator_type);
781 } else {
782 obj = AllocObjectFromCode<true>(
783 c.Ptr(),
784 self,
785 Runtime::Current()->GetHeap()->GetCurrentAllocator());
786 }
787 }
788 if (UNLIKELY(obj == nullptr)) {
789 HANDLE_PENDING_EXCEPTION();
790 } else {
791 obj->GetClass()->AssertInitializedOrInitializingInThread(self);
792 // Don't allow finalizable objects to be allocated during a transaction since these can't
793 // be finalized without a started runtime.
794 if (transaction_active && obj->GetClass()->IsFinalizable()) {
795 AbortTransactionF(self, "Allocating finalizable object in transaction: %s",
796 obj->PrettyTypeOf().c_str());
797 HANDLE_PENDING_EXCEPTION();
798 }
799 shadow_frame.SetVRegReference(inst->VRegA_21c(inst_data), obj);
800 inst = inst->Next_2xx();
801 }
802 }
803
804 ALWAYS_INLINE void NEW_ARRAY() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100805 int32_t length = shadow_frame.GetVReg(inst->VRegB_22c(inst_data));
806 ObjPtr<mirror::Object> obj = AllocArrayFromCode<do_access_check, true>(
807 dex::TypeIndex(inst->VRegC_22c()),
808 length,
809 shadow_frame.GetMethod(),
810 self,
811 Runtime::Current()->GetHeap()->GetCurrentAllocator());
812 if (UNLIKELY(obj == nullptr)) {
813 HANDLE_PENDING_EXCEPTION();
814 } else {
815 shadow_frame.SetVRegReference(inst->VRegA_22c(inst_data), obj);
816 inst = inst->Next_2xx();
817 }
818 }
819
820 ALWAYS_INLINE void FILLED_NEW_ARRAY() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100821 bool success =
822 DoFilledNewArray<false, do_access_check, transaction_active>(inst, shadow_frame, self,
823 ResultRegister());
824 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
825 }
826
827 ALWAYS_INLINE void FILLED_NEW_ARRAY_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100828 bool success =
829 DoFilledNewArray<true, do_access_check, transaction_active>(inst, shadow_frame,
830 self, ResultRegister());
831 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
832 }
833
834 ALWAYS_INLINE void FILL_ARRAY_DATA() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100835 const uint16_t* payload_addr = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
836 const Instruction::ArrayDataPayload* payload =
837 reinterpret_cast<const Instruction::ArrayDataPayload*>(payload_addr);
838 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(inst->VRegA_31t(inst_data));
839 bool success = FillArrayData(obj, payload);
840 if (!success) {
841 HANDLE_PENDING_EXCEPTION();
842 }
843 if (transaction_active) {
844 RecordArrayElementsInTransaction(obj->AsArray(), payload->element_count);
845 }
846 inst = inst->Next_3xx();
847 }
848
849 ALWAYS_INLINE void THROW() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000850 if (!HandleAsyncException()) {
851 return;
852 }
David Srbecky6da82472018-10-23 14:03:08 +0100853 ObjPtr<mirror::Object> exception =
854 shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data));
855 if (UNLIKELY(exception == nullptr)) {
856 ThrowNullPointerException("throw with null exception");
857 } else if (do_assignability_check && !exception->GetClass()->IsThrowableClass()) {
858 // This should never happen.
859 std::string temp;
860 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
861 "Throwing '%s' that is not instance of Throwable",
862 exception->GetClass()->GetDescriptor(&temp));
863 } else {
864 self->SetException(exception->AsThrowable());
865 }
866 HANDLE_PENDING_EXCEPTION();
867 }
868
869 ALWAYS_INLINE void GOTO() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000870 if (!HandleAsyncException()) {
871 return;
872 }
David Srbecky6da82472018-10-23 14:03:08 +0100873 int8_t offset = inst->VRegA_10t(inst_data);
874 BRANCH_INSTRUMENTATION(offset);
875 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +0000876 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +0100877 }
878
879 ALWAYS_INLINE void GOTO_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000880 if (!HandleAsyncException()) {
881 return;
882 }
David Srbecky6da82472018-10-23 14:03:08 +0100883 int16_t offset = inst->VRegA_20t();
884 BRANCH_INSTRUMENTATION(offset);
885 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +0000886 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +0100887 }
888
889 ALWAYS_INLINE void GOTO_32() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000890 if (!HandleAsyncException()) {
891 return;
892 }
David Srbecky6da82472018-10-23 14:03:08 +0100893 int32_t offset = inst->VRegA_30t();
894 BRANCH_INSTRUMENTATION(offset);
895 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +0000896 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +0100897 }
898
899 ALWAYS_INLINE void PACKED_SWITCH() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100900 int32_t offset = DoPackedSwitch(inst, shadow_frame, inst_data);
901 BRANCH_INSTRUMENTATION(offset);
902 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +0000903 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +0100904 }
905
906 ALWAYS_INLINE void SPARSE_SWITCH() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100907 int32_t offset = DoSparseSwitch(inst, shadow_frame, inst_data);
908 BRANCH_INSTRUMENTATION(offset);
909 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +0000910 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +0100911 }
912
913#pragma clang diagnostic push
914#pragma clang diagnostic ignored "-Wfloat-equal"
915
916
917 ALWAYS_INLINE void CMPL_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100918 float val1 = shadow_frame.GetVRegFloat(inst->VRegB_23x());
919 float val2 = shadow_frame.GetVRegFloat(inst->VRegC_23x());
920 int32_t result;
921 if (val1 > val2) {
922 result = 1;
923 } else if (val1 == val2) {
924 result = 0;
925 } else {
926 result = -1;
927 }
928 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), result);
929 inst = inst->Next_2xx();
930 }
931
932 ALWAYS_INLINE void CMPG_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100933 float val1 = shadow_frame.GetVRegFloat(inst->VRegB_23x());
934 float val2 = shadow_frame.GetVRegFloat(inst->VRegC_23x());
935 int32_t result;
936 if (val1 < val2) {
937 result = -1;
938 } else if (val1 == val2) {
939 result = 0;
940 } else {
941 result = 1;
942 }
943 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), result);
944 inst = inst->Next_2xx();
945 }
946
947 ALWAYS_INLINE void CMPL_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100948 double val1 = shadow_frame.GetVRegDouble(inst->VRegB_23x());
949 double val2 = shadow_frame.GetVRegDouble(inst->VRegC_23x());
950 int32_t result;
951 if (val1 > val2) {
952 result = 1;
953 } else if (val1 == val2) {
954 result = 0;
955 } else {
956 result = -1;
957 }
958 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), result);
959 inst = inst->Next_2xx();
960 }
961
962
963 ALWAYS_INLINE void CMPG_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100964 double val1 = shadow_frame.GetVRegDouble(inst->VRegB_23x());
965 double val2 = shadow_frame.GetVRegDouble(inst->VRegC_23x());
966 int32_t result;
967 if (val1 < val2) {
968 result = -1;
969 } else if (val1 == val2) {
970 result = 0;
971 } else {
972 result = 1;
973 }
974 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), result);
975 inst = inst->Next_2xx();
976 }
977
978#pragma clang diagnostic pop
979
980
981 ALWAYS_INLINE void CMP_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100982 int64_t val1 = shadow_frame.GetVRegLong(inst->VRegB_23x());
983 int64_t val2 = shadow_frame.GetVRegLong(inst->VRegC_23x());
984 int32_t result;
985 if (val1 > val2) {
986 result = 1;
987 } else if (val1 == val2) {
988 result = 0;
989 } else {
990 result = -1;
991 }
992 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), result);
993 inst = inst->Next_2xx();
994 }
995
996 ALWAYS_INLINE void IF_EQ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100997 if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) ==
998 shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
999 int16_t offset = inst->VRegC_22t();
1000 BRANCH_INSTRUMENTATION(offset);
1001 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001002 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001003 } else {
1004 BRANCH_INSTRUMENTATION(2);
1005 inst = inst->Next_2xx();
1006 }
1007 }
1008
1009 ALWAYS_INLINE void IF_NE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001010 if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) !=
1011 shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
1012 int16_t offset = inst->VRegC_22t();
1013 BRANCH_INSTRUMENTATION(offset);
1014 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001015 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001016 } else {
1017 BRANCH_INSTRUMENTATION(2);
1018 inst = inst->Next_2xx();
1019 }
1020 }
1021
1022 ALWAYS_INLINE void IF_LT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001023 if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) <
1024 shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
1025 int16_t offset = inst->VRegC_22t();
1026 BRANCH_INSTRUMENTATION(offset);
1027 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001028 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001029 } else {
1030 BRANCH_INSTRUMENTATION(2);
1031 inst = inst->Next_2xx();
1032 }
1033 }
1034
1035 ALWAYS_INLINE void IF_GE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001036 if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) >=
1037 shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
1038 int16_t offset = inst->VRegC_22t();
1039 BRANCH_INSTRUMENTATION(offset);
1040 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001041 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001042 } else {
1043 BRANCH_INSTRUMENTATION(2);
1044 inst = inst->Next_2xx();
1045 }
1046 }
1047
1048 ALWAYS_INLINE void IF_GT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001049 if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) >
1050 shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
1051 int16_t offset = inst->VRegC_22t();
1052 BRANCH_INSTRUMENTATION(offset);
1053 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001054 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001055 } else {
1056 BRANCH_INSTRUMENTATION(2);
1057 inst = inst->Next_2xx();
1058 }
1059 }
1060
1061 ALWAYS_INLINE void IF_LE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001062 if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) <=
1063 shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
1064 int16_t offset = inst->VRegC_22t();
1065 BRANCH_INSTRUMENTATION(offset);
1066 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001067 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001068 } else {
1069 BRANCH_INSTRUMENTATION(2);
1070 inst = inst->Next_2xx();
1071 }
1072 }
1073
1074 ALWAYS_INLINE void IF_EQZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001075 if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) == 0) {
1076 int16_t offset = inst->VRegB_21t();
1077 BRANCH_INSTRUMENTATION(offset);
1078 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001079 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001080 } else {
1081 BRANCH_INSTRUMENTATION(2);
1082 inst = inst->Next_2xx();
1083 }
1084 }
1085
1086 ALWAYS_INLINE void IF_NEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001087 if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) != 0) {
1088 int16_t offset = inst->VRegB_21t();
1089 BRANCH_INSTRUMENTATION(offset);
1090 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001091 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001092 } else {
1093 BRANCH_INSTRUMENTATION(2);
1094 inst = inst->Next_2xx();
1095 }
1096 }
1097
1098 ALWAYS_INLINE void IF_LTZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001099 if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) < 0) {
1100 int16_t offset = inst->VRegB_21t();
1101 BRANCH_INSTRUMENTATION(offset);
1102 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001103 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001104 } else {
1105 BRANCH_INSTRUMENTATION(2);
1106 inst = inst->Next_2xx();
1107 }
1108 }
1109
1110 ALWAYS_INLINE void IF_GEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001111 if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) >= 0) {
1112 int16_t offset = inst->VRegB_21t();
1113 BRANCH_INSTRUMENTATION(offset);
1114 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001115 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001116 } else {
1117 BRANCH_INSTRUMENTATION(2);
1118 inst = inst->Next_2xx();
1119 }
1120 }
1121
1122 ALWAYS_INLINE void IF_GTZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001123 if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) > 0) {
1124 int16_t offset = inst->VRegB_21t();
1125 BRANCH_INSTRUMENTATION(offset);
1126 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001127 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001128 } else {
1129 BRANCH_INSTRUMENTATION(2);
1130 inst = inst->Next_2xx();
1131 }
1132 }
1133
1134 ALWAYS_INLINE void IF_LEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001135 if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) <= 0) {
1136 int16_t offset = inst->VRegB_21t();
1137 BRANCH_INSTRUMENTATION(offset);
1138 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001139 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001140 } else {
1141 BRANCH_INSTRUMENTATION(2);
1142 inst = inst->Next_2xx();
1143 }
1144 }
1145
1146 ALWAYS_INLINE void AGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001147 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1148 if (UNLIKELY(a == nullptr)) {
1149 ThrowNullPointerExceptionFromInterpreter();
1150 HANDLE_PENDING_EXCEPTION();
1151 }
1152 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1153 ObjPtr<mirror::BooleanArray> array = a->AsBooleanArray();
1154 if (array->CheckIsValidIndex(index)) {
1155 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
1156 inst = inst->Next_2xx();
1157 } else {
1158 HANDLE_PENDING_EXCEPTION();
1159 }
1160 }
1161
1162 ALWAYS_INLINE void AGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001163 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1164 if (UNLIKELY(a == nullptr)) {
1165 ThrowNullPointerExceptionFromInterpreter();
1166 HANDLE_PENDING_EXCEPTION();
1167 }
1168 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1169 ObjPtr<mirror::ByteArray> array = a->AsByteArray();
1170 if (array->CheckIsValidIndex(index)) {
1171 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
1172 inst = inst->Next_2xx();
1173 } else {
1174 HANDLE_PENDING_EXCEPTION();
1175 }
1176 }
1177
1178 ALWAYS_INLINE void AGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001179 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1180 if (UNLIKELY(a == nullptr)) {
1181 ThrowNullPointerExceptionFromInterpreter();
1182 HANDLE_PENDING_EXCEPTION();
1183 }
1184 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1185 ObjPtr<mirror::CharArray> array = a->AsCharArray();
1186 if (array->CheckIsValidIndex(index)) {
1187 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
1188 inst = inst->Next_2xx();
1189 } else {
1190 HANDLE_PENDING_EXCEPTION();
1191 }
1192 }
1193
1194 ALWAYS_INLINE void AGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001195 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1196 if (UNLIKELY(a == nullptr)) {
1197 ThrowNullPointerExceptionFromInterpreter();
1198 HANDLE_PENDING_EXCEPTION();
1199 }
1200 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1201 ObjPtr<mirror::ShortArray> array = a->AsShortArray();
1202 if (array->CheckIsValidIndex(index)) {
1203 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
1204 inst = inst->Next_2xx();
1205 } else {
1206 HANDLE_PENDING_EXCEPTION();
1207 }
1208 }
1209
1210 ALWAYS_INLINE void AGET() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001211 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1212 if (UNLIKELY(a == nullptr)) {
1213 ThrowNullPointerExceptionFromInterpreter();
1214 HANDLE_PENDING_EXCEPTION();
1215 }
1216 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1217 DCHECK(a->IsIntArray() || a->IsFloatArray()) << a->PrettyTypeOf();
1218 ObjPtr<mirror::IntArray> array = ObjPtr<mirror::IntArray>::DownCast(a);
1219 if (array->CheckIsValidIndex(index)) {
1220 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
1221 inst = inst->Next_2xx();
1222 } else {
1223 HANDLE_PENDING_EXCEPTION();
1224 }
1225 }
1226
1227 ALWAYS_INLINE void AGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001228 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1229 if (UNLIKELY(a == nullptr)) {
1230 ThrowNullPointerExceptionFromInterpreter();
1231 HANDLE_PENDING_EXCEPTION();
1232 }
1233 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1234 DCHECK(a->IsLongArray() || a->IsDoubleArray()) << a->PrettyTypeOf();
1235 ObjPtr<mirror::LongArray> array = ObjPtr<mirror::LongArray>::DownCast(a);
1236 if (array->CheckIsValidIndex(index)) {
1237 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
1238 inst = inst->Next_2xx();
1239 } else {
1240 HANDLE_PENDING_EXCEPTION();
1241 }
1242 }
1243
1244 ALWAYS_INLINE void AGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001245 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1246 if (UNLIKELY(a == nullptr)) {
1247 ThrowNullPointerExceptionFromInterpreter();
1248 HANDLE_PENDING_EXCEPTION();
1249 }
1250 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1251 ObjPtr<mirror::ObjectArray<mirror::Object>> array = a->AsObjectArray<mirror::Object>();
1252 if (array->CheckIsValidIndex(index)) {
1253 shadow_frame.SetVRegReference(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
1254 inst = inst->Next_2xx();
1255 } else {
1256 HANDLE_PENDING_EXCEPTION();
1257 }
1258 }
1259
1260 ALWAYS_INLINE void APUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001261 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1262 if (UNLIKELY(a == nullptr)) {
1263 ThrowNullPointerExceptionFromInterpreter();
1264 HANDLE_PENDING_EXCEPTION();
1265 }
1266 uint8_t val = shadow_frame.GetVReg(inst->VRegA_23x(inst_data));
1267 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1268 ObjPtr<mirror::BooleanArray> array = a->AsBooleanArray();
1269 if (array->CheckIsValidIndex(index)) {
1270 array->SetWithoutChecks<transaction_active>(index, val);
1271 inst = inst->Next_2xx();
1272 } else {
1273 HANDLE_PENDING_EXCEPTION();
1274 }
1275 }
1276
1277 ALWAYS_INLINE void APUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001278 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1279 if (UNLIKELY(a == nullptr)) {
1280 ThrowNullPointerExceptionFromInterpreter();
1281 HANDLE_PENDING_EXCEPTION();
1282 }
1283 int8_t val = shadow_frame.GetVReg(inst->VRegA_23x(inst_data));
1284 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1285 ObjPtr<mirror::ByteArray> array = a->AsByteArray();
1286 if (array->CheckIsValidIndex(index)) {
1287 array->SetWithoutChecks<transaction_active>(index, val);
1288 inst = inst->Next_2xx();
1289 } else {
1290 HANDLE_PENDING_EXCEPTION();
1291 }
1292 }
1293
1294 ALWAYS_INLINE void APUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001295 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1296 if (UNLIKELY(a == nullptr)) {
1297 ThrowNullPointerExceptionFromInterpreter();
1298 HANDLE_PENDING_EXCEPTION();
1299 }
1300 uint16_t val = shadow_frame.GetVReg(inst->VRegA_23x(inst_data));
1301 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1302 ObjPtr<mirror::CharArray> array = a->AsCharArray();
1303 if (array->CheckIsValidIndex(index)) {
1304 array->SetWithoutChecks<transaction_active>(index, val);
1305 inst = inst->Next_2xx();
1306 } else {
1307 HANDLE_PENDING_EXCEPTION();
1308 }
1309 }
1310
1311 ALWAYS_INLINE void APUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001312 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1313 if (UNLIKELY(a == nullptr)) {
1314 ThrowNullPointerExceptionFromInterpreter();
1315 HANDLE_PENDING_EXCEPTION();
1316 }
1317 int16_t val = shadow_frame.GetVReg(inst->VRegA_23x(inst_data));
1318 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1319 ObjPtr<mirror::ShortArray> array = a->AsShortArray();
1320 if (array->CheckIsValidIndex(index)) {
1321 array->SetWithoutChecks<transaction_active>(index, val);
1322 inst = inst->Next_2xx();
1323 } else {
1324 HANDLE_PENDING_EXCEPTION();
1325 }
1326 }
1327
1328 ALWAYS_INLINE void APUT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001329 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1330 if (UNLIKELY(a == nullptr)) {
1331 ThrowNullPointerExceptionFromInterpreter();
1332 HANDLE_PENDING_EXCEPTION();
1333 }
1334 int32_t val = shadow_frame.GetVReg(inst->VRegA_23x(inst_data));
1335 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1336 DCHECK(a->IsIntArray() || a->IsFloatArray()) << a->PrettyTypeOf();
1337 ObjPtr<mirror::IntArray> array = ObjPtr<mirror::IntArray>::DownCast(a);
1338 if (array->CheckIsValidIndex(index)) {
1339 array->SetWithoutChecks<transaction_active>(index, val);
1340 inst = inst->Next_2xx();
1341 } else {
1342 HANDLE_PENDING_EXCEPTION();
1343 }
1344 }
1345
1346 ALWAYS_INLINE void APUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001347 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1348 if (UNLIKELY(a == nullptr)) {
1349 ThrowNullPointerExceptionFromInterpreter();
1350 HANDLE_PENDING_EXCEPTION();
1351 }
1352 int64_t val = shadow_frame.GetVRegLong(inst->VRegA_23x(inst_data));
1353 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1354 DCHECK(a->IsLongArray() || a->IsDoubleArray()) << a->PrettyTypeOf();
1355 ObjPtr<mirror::LongArray> array = ObjPtr<mirror::LongArray>::DownCast(a);
1356 if (array->CheckIsValidIndex(index)) {
1357 array->SetWithoutChecks<transaction_active>(index, val);
1358 inst = inst->Next_2xx();
1359 } else {
1360 HANDLE_PENDING_EXCEPTION();
1361 }
1362 }
1363
1364 ALWAYS_INLINE void APUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001365 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1366 if (UNLIKELY(a == nullptr)) {
1367 ThrowNullPointerExceptionFromInterpreter();
1368 HANDLE_PENDING_EXCEPTION();
1369 }
1370 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1371 ObjPtr<mirror::Object> val = shadow_frame.GetVRegReference(inst->VRegA_23x(inst_data));
1372 ObjPtr<mirror::ObjectArray<mirror::Object>> array = a->AsObjectArray<mirror::Object>();
1373 if (array->CheckIsValidIndex(index) && array->CheckAssignable(val)) {
1374 array->SetWithoutChecks<transaction_active>(index, val);
1375 inst = inst->Next_2xx();
1376 } else {
1377 HANDLE_PENDING_EXCEPTION();
1378 }
1379 }
1380
1381 ALWAYS_INLINE void IGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001382 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimBoolean, do_access_check>(
1383 self, shadow_frame, inst, inst_data);
1384 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1385 }
1386
1387 ALWAYS_INLINE void IGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001388 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimByte, do_access_check>(
1389 self, shadow_frame, inst, inst_data);
1390 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1391 }
1392
1393 ALWAYS_INLINE void IGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001394 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimChar, do_access_check>(
1395 self, shadow_frame, inst, inst_data);
1396 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1397 }
1398
1399 ALWAYS_INLINE void IGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001400 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimShort, do_access_check>(
1401 self, shadow_frame, inst, inst_data);
1402 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1403 }
1404
1405 ALWAYS_INLINE void IGET() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001406 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimInt, do_access_check>(
1407 self, shadow_frame, inst, inst_data);
1408 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1409 }
1410
1411 ALWAYS_INLINE void IGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001412 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimLong, do_access_check>(
1413 self, shadow_frame, inst, inst_data);
1414 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1415 }
1416
1417 ALWAYS_INLINE void IGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001418 bool success = DoFieldGet<InstanceObjectRead, Primitive::kPrimNot, do_access_check>(
1419 self, shadow_frame, inst, inst_data);
1420 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1421 }
1422
1423 ALWAYS_INLINE void IGET_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001424 bool success = DoIGetQuick<Primitive::kPrimInt>(shadow_frame, inst, inst_data);
1425 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1426 }
1427
1428 ALWAYS_INLINE void IGET_WIDE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001429 bool success = DoIGetQuick<Primitive::kPrimLong>(shadow_frame, inst, inst_data);
1430 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1431 }
1432
1433 ALWAYS_INLINE void IGET_OBJECT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001434 bool success = DoIGetQuick<Primitive::kPrimNot>(shadow_frame, inst, inst_data);
1435 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1436 }
1437
1438 ALWAYS_INLINE void IGET_BOOLEAN_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001439 bool success = DoIGetQuick<Primitive::kPrimBoolean>(shadow_frame, inst, inst_data);
1440 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1441 }
1442
1443 ALWAYS_INLINE void IGET_BYTE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001444 bool success = DoIGetQuick<Primitive::kPrimByte>(shadow_frame, inst, inst_data);
1445 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1446 }
1447
1448 ALWAYS_INLINE void IGET_CHAR_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001449 bool success = DoIGetQuick<Primitive::kPrimChar>(shadow_frame, inst, inst_data);
1450 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1451 }
1452
1453 ALWAYS_INLINE void IGET_SHORT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001454 bool success = DoIGetQuick<Primitive::kPrimShort>(shadow_frame, inst, inst_data);
1455 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1456 }
1457
1458 ALWAYS_INLINE void SGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001459 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimBoolean, do_access_check,
1460 transaction_active>(self, shadow_frame, inst, inst_data);
1461 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1462 }
1463
1464 ALWAYS_INLINE void SGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001465 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimByte, do_access_check,
1466 transaction_active>(self, shadow_frame, inst, inst_data);
1467 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1468 }
1469
1470 ALWAYS_INLINE void SGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001471 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimChar, do_access_check,
1472 transaction_active>(self, shadow_frame, inst, inst_data);
1473 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1474 }
1475
1476 ALWAYS_INLINE void SGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001477 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimShort, do_access_check,
1478 transaction_active>(self, shadow_frame, inst, inst_data);
1479 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1480 }
1481
1482 ALWAYS_INLINE void SGET() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001483 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimInt, do_access_check,
1484 transaction_active>(self, shadow_frame, inst, inst_data);
1485 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1486 }
1487
1488 ALWAYS_INLINE void SGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001489 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimLong, do_access_check,
1490 transaction_active>(self, shadow_frame, inst, inst_data);
1491 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1492 }
1493
1494 ALWAYS_INLINE void SGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001495 bool success = DoFieldGet<StaticObjectRead, Primitive::kPrimNot, do_access_check,
1496 transaction_active>(self, shadow_frame, inst, inst_data);
1497 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1498 }
1499
1500 ALWAYS_INLINE void IPUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001501 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimBoolean, do_access_check,
1502 transaction_active>(self, shadow_frame, inst, inst_data);
1503 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1504 }
1505
1506 ALWAYS_INLINE void IPUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001507 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimByte, do_access_check,
1508 transaction_active>(self, shadow_frame, inst, inst_data);
1509 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1510 }
1511
1512 ALWAYS_INLINE void IPUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001513 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimChar, do_access_check,
1514 transaction_active>(self, shadow_frame, inst, inst_data);
1515 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1516 }
1517
1518 ALWAYS_INLINE void IPUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001519 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimShort, do_access_check,
1520 transaction_active>(self, shadow_frame, inst, inst_data);
1521 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1522 }
1523
1524 ALWAYS_INLINE void IPUT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001525 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimInt, do_access_check,
1526 transaction_active>(self, shadow_frame, inst, inst_data);
1527 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1528 }
1529
1530 ALWAYS_INLINE void IPUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001531 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimLong, do_access_check,
1532 transaction_active>(self, shadow_frame, inst, inst_data);
1533 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1534 }
1535
1536 ALWAYS_INLINE void IPUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001537 bool success = DoFieldPut<InstanceObjectWrite, Primitive::kPrimNot, do_access_check,
1538 transaction_active>(self, shadow_frame, inst, inst_data);
1539 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1540 }
1541
1542 ALWAYS_INLINE void IPUT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001543 bool success = DoIPutQuick<Primitive::kPrimInt, transaction_active>(
1544 shadow_frame, inst, inst_data);
1545 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1546 }
1547
1548 ALWAYS_INLINE void IPUT_BOOLEAN_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001549 bool success = DoIPutQuick<Primitive::kPrimBoolean, transaction_active>(
1550 shadow_frame, inst, inst_data);
1551 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1552 }
1553
1554 ALWAYS_INLINE void IPUT_BYTE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001555 bool success = DoIPutQuick<Primitive::kPrimByte, transaction_active>(
1556 shadow_frame, inst, inst_data);
1557 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1558 }
1559
1560 ALWAYS_INLINE void IPUT_CHAR_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001561 bool success = DoIPutQuick<Primitive::kPrimChar, transaction_active>(
1562 shadow_frame, inst, inst_data);
1563 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1564 }
1565
1566 ALWAYS_INLINE void IPUT_SHORT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001567 bool success = DoIPutQuick<Primitive::kPrimShort, transaction_active>(
1568 shadow_frame, inst, inst_data);
1569 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1570 }
1571
1572 ALWAYS_INLINE void IPUT_WIDE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001573 bool success = DoIPutQuick<Primitive::kPrimLong, transaction_active>(
1574 shadow_frame, inst, inst_data);
1575 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1576 }
1577
1578 ALWAYS_INLINE void IPUT_OBJECT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001579 bool success = DoIPutQuick<Primitive::kPrimNot, transaction_active>(
1580 shadow_frame, inst, inst_data);
1581 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1582 }
1583
1584 ALWAYS_INLINE void SPUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001585 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimBoolean, do_access_check,
1586 transaction_active>(self, shadow_frame, inst, inst_data);
1587 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1588 }
1589
1590 ALWAYS_INLINE void SPUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001591 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimByte, do_access_check,
1592 transaction_active>(self, shadow_frame, inst, inst_data);
1593 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1594 }
1595
1596 ALWAYS_INLINE void SPUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001597 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimChar, do_access_check,
1598 transaction_active>(self, shadow_frame, inst, inst_data);
1599 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1600 }
1601
1602 ALWAYS_INLINE void SPUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001603 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimShort, do_access_check,
1604 transaction_active>(self, shadow_frame, inst, inst_data);
1605 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1606 }
1607
1608 ALWAYS_INLINE void SPUT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001609 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimInt, do_access_check,
1610 transaction_active>(self, shadow_frame, inst, inst_data);
1611 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1612 }
1613
1614 ALWAYS_INLINE void SPUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001615 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimLong, do_access_check,
1616 transaction_active>(self, shadow_frame, inst, inst_data);
1617 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1618 }
1619
1620 ALWAYS_INLINE void SPUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001621 bool success = DoFieldPut<StaticObjectWrite, Primitive::kPrimNot, do_access_check,
1622 transaction_active>(self, shadow_frame, inst, inst_data);
1623 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1624 }
1625
1626 ALWAYS_INLINE void INVOKE_VIRTUAL() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001627 bool success = DoInvoke<kVirtual, false, do_access_check, /*is_mterp=*/ false>(
1628 self, shadow_frame, inst, inst_data, ResultRegister());
1629 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1630 }
1631
1632 ALWAYS_INLINE void INVOKE_VIRTUAL_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001633 bool success = DoInvoke<kVirtual, true, do_access_check, /*is_mterp=*/ false>(
1634 self, shadow_frame, inst, inst_data, ResultRegister());
1635 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1636 }
1637
1638 ALWAYS_INLINE void INVOKE_SUPER() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001639 bool success = DoInvoke<kSuper, false, do_access_check, /*is_mterp=*/ false>(
1640 self, shadow_frame, inst, inst_data, ResultRegister());
1641 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1642 }
1643
1644 ALWAYS_INLINE void INVOKE_SUPER_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001645 bool success = DoInvoke<kSuper, true, do_access_check, /*is_mterp=*/ false>(
1646 self, shadow_frame, inst, inst_data, ResultRegister());
1647 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1648 }
1649
1650 ALWAYS_INLINE void INVOKE_DIRECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001651 bool success = DoInvoke<kDirect, false, do_access_check, /*is_mterp=*/ false>(
1652 self, shadow_frame, inst, inst_data, ResultRegister());
1653 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1654 }
1655
1656 ALWAYS_INLINE void INVOKE_DIRECT_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001657 bool success = DoInvoke<kDirect, true, do_access_check, /*is_mterp=*/ false>(
1658 self, shadow_frame, inst, inst_data, ResultRegister());
1659 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1660 }
1661
1662 ALWAYS_INLINE void INVOKE_INTERFACE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001663 bool success = DoInvoke<kInterface, false, do_access_check, /*is_mterp=*/ false>(
1664 self, shadow_frame, inst, inst_data, ResultRegister());
1665 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1666 }
1667
1668 ALWAYS_INLINE void INVOKE_INTERFACE_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001669 bool success = DoInvoke<kInterface, true, do_access_check, /*is_mterp=*/ false>(
1670 self, shadow_frame, inst, inst_data, ResultRegister());
1671 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1672 }
1673
1674 ALWAYS_INLINE void INVOKE_STATIC() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001675 bool success = DoInvoke<kStatic, false, do_access_check, /*is_mterp=*/ false>(
1676 self, shadow_frame, inst, inst_data, ResultRegister());
1677 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1678 }
1679
1680 ALWAYS_INLINE void INVOKE_STATIC_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001681 bool success = DoInvoke<kStatic, true, do_access_check, /*is_mterp=*/ false>(
1682 self, shadow_frame, inst, inst_data, ResultRegister());
1683 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1684 }
1685
1686 ALWAYS_INLINE void INVOKE_VIRTUAL_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001687 bool success = DoInvoke<kVirtual, false, do_access_check, /*is_mterp=*/ false,
1688 /*is_quick=*/ true>(self, shadow_frame, inst, inst_data, ResultRegister());
1689 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1690 }
1691
1692 ALWAYS_INLINE void INVOKE_VIRTUAL_RANGE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001693 bool success = DoInvoke<kVirtual, true, do_access_check, /*is_mterp=*/ false,
1694 /*is_quick=*/ true>(self, shadow_frame, inst, inst_data, ResultRegister());
1695 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1696 }
1697
1698 ALWAYS_INLINE void INVOKE_POLYMORPHIC() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001699 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1700 bool success = DoInvokePolymorphic</* is_range= */ false>(
1701 self, shadow_frame, inst, inst_data, ResultRegister());
1702 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(!success);
1703 }
1704
1705 ALWAYS_INLINE void INVOKE_POLYMORPHIC_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001706 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1707 bool success = DoInvokePolymorphic</* is_range= */ true>(
1708 self, shadow_frame, inst, inst_data, ResultRegister());
1709 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(!success);
1710 }
1711
1712 ALWAYS_INLINE void INVOKE_CUSTOM() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001713 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1714 bool success = DoInvokeCustom</* is_range= */ false>(
1715 self, shadow_frame, inst, inst_data, ResultRegister());
1716 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1717 }
1718
1719 ALWAYS_INLINE void INVOKE_CUSTOM_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001720 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1721 bool success = DoInvokeCustom</* is_range= */ true>(
1722 self, shadow_frame, inst, inst_data, ResultRegister());
1723 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1724 }
1725
1726 ALWAYS_INLINE void NEG_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001727 shadow_frame.SetVReg(
1728 inst->VRegA_12x(inst_data), -shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
1729 inst = inst->Next_1xx();
1730 }
1731
1732 ALWAYS_INLINE void NOT_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001733 shadow_frame.SetVReg(
1734 inst->VRegA_12x(inst_data), ~shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
1735 inst = inst->Next_1xx();
1736 }
1737
1738 ALWAYS_INLINE void NEG_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001739 shadow_frame.SetVRegLong(
1740 inst->VRegA_12x(inst_data), -shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
1741 inst = inst->Next_1xx();
1742 }
1743
1744 ALWAYS_INLINE void NOT_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001745 shadow_frame.SetVRegLong(
1746 inst->VRegA_12x(inst_data), ~shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
1747 inst = inst->Next_1xx();
1748 }
1749
1750 ALWAYS_INLINE void NEG_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001751 shadow_frame.SetVRegFloat(
1752 inst->VRegA_12x(inst_data), -shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
1753 inst = inst->Next_1xx();
1754 }
1755
1756 ALWAYS_INLINE void NEG_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001757 shadow_frame.SetVRegDouble(
1758 inst->VRegA_12x(inst_data), -shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
1759 inst = inst->Next_1xx();
1760 }
1761
1762 ALWAYS_INLINE void INT_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001763 shadow_frame.SetVRegLong(inst->VRegA_12x(inst_data),
1764 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
1765 inst = inst->Next_1xx();
1766 }
1767
1768 ALWAYS_INLINE void INT_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001769 shadow_frame.SetVRegFloat(inst->VRegA_12x(inst_data),
1770 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
1771 inst = inst->Next_1xx();
1772 }
1773
1774 ALWAYS_INLINE void INT_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001775 shadow_frame.SetVRegDouble(inst->VRegA_12x(inst_data),
1776 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
1777 inst = inst->Next_1xx();
1778 }
1779
1780 ALWAYS_INLINE void LONG_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001781 shadow_frame.SetVReg(inst->VRegA_12x(inst_data),
1782 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
1783 inst = inst->Next_1xx();
1784 }
1785
1786 ALWAYS_INLINE void LONG_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001787 shadow_frame.SetVRegFloat(inst->VRegA_12x(inst_data),
1788 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
1789 inst = inst->Next_1xx();
1790 }
1791
1792 ALWAYS_INLINE void LONG_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001793 shadow_frame.SetVRegDouble(inst->VRegA_12x(inst_data),
1794 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
1795 inst = inst->Next_1xx();
1796 }
1797
1798 ALWAYS_INLINE void FLOAT_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001799 float val = shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data));
1800 int32_t result = art_float_to_integral<int32_t, float>(val);
1801 shadow_frame.SetVReg(inst->VRegA_12x(inst_data), result);
1802 inst = inst->Next_1xx();
1803 }
1804
1805 ALWAYS_INLINE void FLOAT_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001806 float val = shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data));
1807 int64_t result = art_float_to_integral<int64_t, float>(val);
1808 shadow_frame.SetVRegLong(inst->VRegA_12x(inst_data), result);
1809 inst = inst->Next_1xx();
1810 }
1811
1812 ALWAYS_INLINE void FLOAT_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001813 shadow_frame.SetVRegDouble(inst->VRegA_12x(inst_data),
1814 shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
1815 inst = inst->Next_1xx();
1816 }
1817
1818 ALWAYS_INLINE void DOUBLE_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001819 double val = shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data));
1820 int32_t result = art_float_to_integral<int32_t, double>(val);
1821 shadow_frame.SetVReg(inst->VRegA_12x(inst_data), result);
1822 inst = inst->Next_1xx();
1823 }
1824
1825 ALWAYS_INLINE void DOUBLE_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001826 double val = shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data));
1827 int64_t result = art_float_to_integral<int64_t, double>(val);
1828 shadow_frame.SetVRegLong(inst->VRegA_12x(inst_data), result);
1829 inst = inst->Next_1xx();
1830 }
1831
1832 ALWAYS_INLINE void DOUBLE_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001833 shadow_frame.SetVRegFloat(inst->VRegA_12x(inst_data),
1834 shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
1835 inst = inst->Next_1xx();
1836 }
1837
1838 ALWAYS_INLINE void INT_TO_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001839 shadow_frame.SetVReg(inst->VRegA_12x(inst_data), static_cast<int8_t>(
1840 shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
1841 inst = inst->Next_1xx();
1842 }
1843
1844 ALWAYS_INLINE void INT_TO_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001845 shadow_frame.SetVReg(inst->VRegA_12x(inst_data), static_cast<uint16_t>(
1846 shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
1847 inst = inst->Next_1xx();
1848 }
1849
1850 ALWAYS_INLINE void INT_TO_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001851 shadow_frame.SetVReg(inst->VRegA_12x(inst_data), static_cast<int16_t>(
1852 shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
1853 inst = inst->Next_1xx();
1854 }
1855
1856 ALWAYS_INLINE void ADD_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001857 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1858 SafeAdd(shadow_frame.GetVReg(inst->VRegB_23x()),
1859 shadow_frame.GetVReg(inst->VRegC_23x())));
1860 inst = inst->Next_2xx();
1861 }
1862
1863 ALWAYS_INLINE void SUB_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001864 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1865 SafeSub(shadow_frame.GetVReg(inst->VRegB_23x()),
1866 shadow_frame.GetVReg(inst->VRegC_23x())));
1867 inst = inst->Next_2xx();
1868 }
1869
1870 ALWAYS_INLINE void MUL_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001871 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1872 SafeMul(shadow_frame.GetVReg(inst->VRegB_23x()),
1873 shadow_frame.GetVReg(inst->VRegC_23x())));
1874 inst = inst->Next_2xx();
1875 }
1876
1877 ALWAYS_INLINE void DIV_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001878 bool success = DoIntDivide(shadow_frame, inst->VRegA_23x(inst_data),
1879 shadow_frame.GetVReg(inst->VRegB_23x()),
1880 shadow_frame.GetVReg(inst->VRegC_23x()));
1881 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1882 }
1883
1884 ALWAYS_INLINE void REM_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001885 bool success = DoIntRemainder(shadow_frame, inst->VRegA_23x(inst_data),
1886 shadow_frame.GetVReg(inst->VRegB_23x()),
1887 shadow_frame.GetVReg(inst->VRegC_23x()));
1888 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1889 }
1890
1891 ALWAYS_INLINE void SHL_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001892 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1893 shadow_frame.GetVReg(inst->VRegB_23x()) <<
1894 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x1f));
1895 inst = inst->Next_2xx();
1896 }
1897
1898 ALWAYS_INLINE void SHR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001899 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1900 shadow_frame.GetVReg(inst->VRegB_23x()) >>
1901 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x1f));
1902 inst = inst->Next_2xx();
1903 }
1904
1905 ALWAYS_INLINE void USHR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001906 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1907 static_cast<uint32_t>(shadow_frame.GetVReg(inst->VRegB_23x())) >>
1908 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x1f));
1909 inst = inst->Next_2xx();
1910 }
1911
1912 ALWAYS_INLINE void AND_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001913 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1914 shadow_frame.GetVReg(inst->VRegB_23x()) &
1915 shadow_frame.GetVReg(inst->VRegC_23x()));
1916 inst = inst->Next_2xx();
1917 }
1918
1919 ALWAYS_INLINE void OR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001920 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1921 shadow_frame.GetVReg(inst->VRegB_23x()) |
1922 shadow_frame.GetVReg(inst->VRegC_23x()));
1923 inst = inst->Next_2xx();
1924 }
1925
1926 ALWAYS_INLINE void XOR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001927 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1928 shadow_frame.GetVReg(inst->VRegB_23x()) ^
1929 shadow_frame.GetVReg(inst->VRegC_23x()));
1930 inst = inst->Next_2xx();
1931 }
1932
1933 ALWAYS_INLINE void ADD_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001934 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
1935 SafeAdd(shadow_frame.GetVRegLong(inst->VRegB_23x()),
1936 shadow_frame.GetVRegLong(inst->VRegC_23x())));
1937 inst = inst->Next_2xx();
1938 }
1939
1940 ALWAYS_INLINE void SUB_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001941 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
1942 SafeSub(shadow_frame.GetVRegLong(inst->VRegB_23x()),
1943 shadow_frame.GetVRegLong(inst->VRegC_23x())));
1944 inst = inst->Next_2xx();
1945 }
1946
1947 ALWAYS_INLINE void MUL_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001948 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
1949 SafeMul(shadow_frame.GetVRegLong(inst->VRegB_23x()),
1950 shadow_frame.GetVRegLong(inst->VRegC_23x())));
1951 inst = inst->Next_2xx();
1952 }
1953
1954 ALWAYS_INLINE void DIV_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001955 DoLongDivide(shadow_frame, inst->VRegA_23x(inst_data),
1956 shadow_frame.GetVRegLong(inst->VRegB_23x()),
1957 shadow_frame.GetVRegLong(inst->VRegC_23x()));
1958 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_2xx);
1959 }
1960
1961 ALWAYS_INLINE void REM_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001962 DoLongRemainder(shadow_frame, inst->VRegA_23x(inst_data),
1963 shadow_frame.GetVRegLong(inst->VRegB_23x()),
1964 shadow_frame.GetVRegLong(inst->VRegC_23x()));
1965 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_2xx);
1966 }
1967
1968 ALWAYS_INLINE void AND_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001969 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
1970 shadow_frame.GetVRegLong(inst->VRegB_23x()) &
1971 shadow_frame.GetVRegLong(inst->VRegC_23x()));
1972 inst = inst->Next_2xx();
1973 }
1974
1975 ALWAYS_INLINE void OR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001976 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
1977 shadow_frame.GetVRegLong(inst->VRegB_23x()) |
1978 shadow_frame.GetVRegLong(inst->VRegC_23x()));
1979 inst = inst->Next_2xx();
1980 }
1981
1982 ALWAYS_INLINE void XOR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001983 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
1984 shadow_frame.GetVRegLong(inst->VRegB_23x()) ^
1985 shadow_frame.GetVRegLong(inst->VRegC_23x()));
1986 inst = inst->Next_2xx();
1987 }
1988
1989 ALWAYS_INLINE void SHL_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001990 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
1991 shadow_frame.GetVRegLong(inst->VRegB_23x()) <<
1992 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x3f));
1993 inst = inst->Next_2xx();
1994 }
1995
1996 ALWAYS_INLINE void SHR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001997 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
1998 shadow_frame.GetVRegLong(inst->VRegB_23x()) >>
1999 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x3f));
2000 inst = inst->Next_2xx();
2001 }
2002
2003 ALWAYS_INLINE void USHR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002004 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
2005 static_cast<uint64_t>(shadow_frame.GetVRegLong(inst->VRegB_23x())) >>
2006 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x3f));
2007 inst = inst->Next_2xx();
2008 }
2009
2010 ALWAYS_INLINE void ADD_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002011 shadow_frame.SetVRegFloat(inst->VRegA_23x(inst_data),
2012 shadow_frame.GetVRegFloat(inst->VRegB_23x()) +
2013 shadow_frame.GetVRegFloat(inst->VRegC_23x()));
2014 inst = inst->Next_2xx();
2015 }
2016
2017 ALWAYS_INLINE void SUB_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002018 shadow_frame.SetVRegFloat(inst->VRegA_23x(inst_data),
2019 shadow_frame.GetVRegFloat(inst->VRegB_23x()) -
2020 shadow_frame.GetVRegFloat(inst->VRegC_23x()));
2021 inst = inst->Next_2xx();
2022 }
2023
2024 ALWAYS_INLINE void MUL_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002025 shadow_frame.SetVRegFloat(inst->VRegA_23x(inst_data),
2026 shadow_frame.GetVRegFloat(inst->VRegB_23x()) *
2027 shadow_frame.GetVRegFloat(inst->VRegC_23x()));
2028 inst = inst->Next_2xx();
2029 }
2030
2031 ALWAYS_INLINE void DIV_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002032 shadow_frame.SetVRegFloat(inst->VRegA_23x(inst_data),
2033 shadow_frame.GetVRegFloat(inst->VRegB_23x()) /
2034 shadow_frame.GetVRegFloat(inst->VRegC_23x()));
2035 inst = inst->Next_2xx();
2036 }
2037
2038 ALWAYS_INLINE void REM_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002039 shadow_frame.SetVRegFloat(inst->VRegA_23x(inst_data),
2040 fmodf(shadow_frame.GetVRegFloat(inst->VRegB_23x()),
2041 shadow_frame.GetVRegFloat(inst->VRegC_23x())));
2042 inst = inst->Next_2xx();
2043 }
2044
2045 ALWAYS_INLINE void ADD_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002046 shadow_frame.SetVRegDouble(inst->VRegA_23x(inst_data),
2047 shadow_frame.GetVRegDouble(inst->VRegB_23x()) +
2048 shadow_frame.GetVRegDouble(inst->VRegC_23x()));
2049 inst = inst->Next_2xx();
2050 }
2051
2052 ALWAYS_INLINE void SUB_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002053 shadow_frame.SetVRegDouble(inst->VRegA_23x(inst_data),
2054 shadow_frame.GetVRegDouble(inst->VRegB_23x()) -
2055 shadow_frame.GetVRegDouble(inst->VRegC_23x()));
2056 inst = inst->Next_2xx();
2057 }
2058
2059 ALWAYS_INLINE void MUL_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002060 shadow_frame.SetVRegDouble(inst->VRegA_23x(inst_data),
2061 shadow_frame.GetVRegDouble(inst->VRegB_23x()) *
2062 shadow_frame.GetVRegDouble(inst->VRegC_23x()));
2063 inst = inst->Next_2xx();
2064 }
2065
2066 ALWAYS_INLINE void DIV_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002067 shadow_frame.SetVRegDouble(inst->VRegA_23x(inst_data),
2068 shadow_frame.GetVRegDouble(inst->VRegB_23x()) /
2069 shadow_frame.GetVRegDouble(inst->VRegC_23x()));
2070 inst = inst->Next_2xx();
2071 }
2072
2073 ALWAYS_INLINE void REM_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002074 shadow_frame.SetVRegDouble(inst->VRegA_23x(inst_data),
2075 fmod(shadow_frame.GetVRegDouble(inst->VRegB_23x()),
2076 shadow_frame.GetVRegDouble(inst->VRegC_23x())));
2077 inst = inst->Next_2xx();
2078 }
2079
2080 ALWAYS_INLINE void ADD_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002081 uint4_t vregA = inst->VRegA_12x(inst_data);
2082 shadow_frame.SetVReg(vregA, SafeAdd(shadow_frame.GetVReg(vregA),
2083 shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
2084 inst = inst->Next_1xx();
2085 }
2086
2087 ALWAYS_INLINE void SUB_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002088 uint4_t vregA = inst->VRegA_12x(inst_data);
2089 shadow_frame.SetVReg(vregA,
2090 SafeSub(shadow_frame.GetVReg(vregA),
2091 shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
2092 inst = inst->Next_1xx();
2093 }
2094
2095 ALWAYS_INLINE void MUL_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002096 uint4_t vregA = inst->VRegA_12x(inst_data);
2097 shadow_frame.SetVReg(vregA,
2098 SafeMul(shadow_frame.GetVReg(vregA),
2099 shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
2100 inst = inst->Next_1xx();
2101 }
2102
2103 ALWAYS_INLINE void DIV_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002104 uint4_t vregA = inst->VRegA_12x(inst_data);
2105 bool success = DoIntDivide(shadow_frame, vregA, shadow_frame.GetVReg(vregA),
2106 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
2107 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_1xx);
2108 }
2109
2110 ALWAYS_INLINE void REM_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002111 uint4_t vregA = inst->VRegA_12x(inst_data);
2112 bool success = DoIntRemainder(shadow_frame, vregA, shadow_frame.GetVReg(vregA),
2113 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
2114 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_1xx);
2115 }
2116
2117 ALWAYS_INLINE void SHL_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 shadow_frame.GetVReg(vregA) <<
2121 (shadow_frame.GetVReg(inst->VRegB_12x(inst_data)) & 0x1f));
2122 inst = inst->Next_1xx();
2123 }
2124
2125 ALWAYS_INLINE void SHR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002126 uint4_t vregA = inst->VRegA_12x(inst_data);
2127 shadow_frame.SetVReg(vregA,
2128 shadow_frame.GetVReg(vregA) >>
2129 (shadow_frame.GetVReg(inst->VRegB_12x(inst_data)) & 0x1f));
2130 inst = inst->Next_1xx();
2131 }
2132
2133 ALWAYS_INLINE void USHR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002134 uint4_t vregA = inst->VRegA_12x(inst_data);
2135 shadow_frame.SetVReg(vregA,
2136 static_cast<uint32_t>(shadow_frame.GetVReg(vregA)) >>
2137 (shadow_frame.GetVReg(inst->VRegB_12x(inst_data)) & 0x1f));
2138 inst = inst->Next_1xx();
2139 }
2140
2141 ALWAYS_INLINE void AND_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002142 uint4_t vregA = inst->VRegA_12x(inst_data);
2143 shadow_frame.SetVReg(vregA,
2144 shadow_frame.GetVReg(vregA) &
2145 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
2146 inst = inst->Next_1xx();
2147 }
2148
2149 ALWAYS_INLINE void OR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002150 uint4_t vregA = inst->VRegA_12x(inst_data);
2151 shadow_frame.SetVReg(vregA,
2152 shadow_frame.GetVReg(vregA) |
2153 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
2154 inst = inst->Next_1xx();
2155 }
2156
2157 ALWAYS_INLINE void XOR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002158 uint4_t vregA = inst->VRegA_12x(inst_data);
2159 shadow_frame.SetVReg(vregA,
2160 shadow_frame.GetVReg(vregA) ^
2161 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
2162 inst = inst->Next_1xx();
2163 }
2164
2165 ALWAYS_INLINE void ADD_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002166 uint4_t vregA = inst->VRegA_12x(inst_data);
2167 shadow_frame.SetVRegLong(vregA,
2168 SafeAdd(shadow_frame.GetVRegLong(vregA),
2169 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data))));
2170 inst = inst->Next_1xx();
2171 }
2172
2173 ALWAYS_INLINE void SUB_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002174 uint4_t vregA = inst->VRegA_12x(inst_data);
2175 shadow_frame.SetVRegLong(vregA,
2176 SafeSub(shadow_frame.GetVRegLong(vregA),
2177 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data))));
2178 inst = inst->Next_1xx();
2179 }
2180
2181 ALWAYS_INLINE void MUL_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002182 uint4_t vregA = inst->VRegA_12x(inst_data);
2183 shadow_frame.SetVRegLong(vregA,
2184 SafeMul(shadow_frame.GetVRegLong(vregA),
2185 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data))));
2186 inst = inst->Next_1xx();
2187 }
2188
2189 ALWAYS_INLINE void DIV_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002190 uint4_t vregA = inst->VRegA_12x(inst_data);
2191 DoLongDivide(shadow_frame, vregA, shadow_frame.GetVRegLong(vregA),
2192 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
2193 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
2194 }
2195
2196 ALWAYS_INLINE void REM_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002197 uint4_t vregA = inst->VRegA_12x(inst_data);
2198 DoLongRemainder(shadow_frame, vregA, shadow_frame.GetVRegLong(vregA),
2199 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
2200 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
2201 }
2202
2203 ALWAYS_INLINE void AND_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 shadow_frame.GetVRegLong(vregA) &
2207 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
2208 inst = inst->Next_1xx();
2209 }
2210
2211 ALWAYS_INLINE void OR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002212 uint4_t vregA = inst->VRegA_12x(inst_data);
2213 shadow_frame.SetVRegLong(vregA,
2214 shadow_frame.GetVRegLong(vregA) |
2215 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
2216 inst = inst->Next_1xx();
2217 }
2218
2219 ALWAYS_INLINE void XOR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002220 uint4_t vregA = inst->VRegA_12x(inst_data);
2221 shadow_frame.SetVRegLong(vregA,
2222 shadow_frame.GetVRegLong(vregA) ^
2223 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
2224 inst = inst->Next_1xx();
2225 }
2226
2227 ALWAYS_INLINE void SHL_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002228 uint4_t vregA = inst->VRegA_12x(inst_data);
2229 shadow_frame.SetVRegLong(vregA,
2230 shadow_frame.GetVRegLong(vregA) <<
2231 (shadow_frame.GetVReg(inst->VRegB_12x(inst_data)) & 0x3f));
2232 inst = inst->Next_1xx();
2233 }
2234
2235 ALWAYS_INLINE void SHR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002236 uint4_t vregA = inst->VRegA_12x(inst_data);
2237 shadow_frame.SetVRegLong(vregA,
2238 shadow_frame.GetVRegLong(vregA) >>
2239 (shadow_frame.GetVReg(inst->VRegB_12x(inst_data)) & 0x3f));
2240 inst = inst->Next_1xx();
2241 }
2242
2243 ALWAYS_INLINE void USHR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002244 uint4_t vregA = inst->VRegA_12x(inst_data);
2245 shadow_frame.SetVRegLong(vregA,
2246 static_cast<uint64_t>(shadow_frame.GetVRegLong(vregA)) >>
2247 (shadow_frame.GetVReg(inst->VRegB_12x(inst_data)) & 0x3f));
2248 inst = inst->Next_1xx();
2249 }
2250
2251 ALWAYS_INLINE void ADD_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002252 uint4_t vregA = inst->VRegA_12x(inst_data);
2253 shadow_frame.SetVRegFloat(vregA,
2254 shadow_frame.GetVRegFloat(vregA) +
2255 shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
2256 inst = inst->Next_1xx();
2257 }
2258
2259 ALWAYS_INLINE void SUB_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002260 uint4_t vregA = inst->VRegA_12x(inst_data);
2261 shadow_frame.SetVRegFloat(vregA,
2262 shadow_frame.GetVRegFloat(vregA) -
2263 shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
2264 inst = inst->Next_1xx();
2265 }
2266
2267 ALWAYS_INLINE void MUL_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002268 uint4_t vregA = inst->VRegA_12x(inst_data);
2269 shadow_frame.SetVRegFloat(vregA,
2270 shadow_frame.GetVRegFloat(vregA) *
2271 shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
2272 inst = inst->Next_1xx();
2273 }
2274
2275 ALWAYS_INLINE void DIV_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002276 uint4_t vregA = inst->VRegA_12x(inst_data);
2277 shadow_frame.SetVRegFloat(vregA,
2278 shadow_frame.GetVRegFloat(vregA) /
2279 shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
2280 inst = inst->Next_1xx();
2281 }
2282
2283 ALWAYS_INLINE void REM_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002284 uint4_t vregA = inst->VRegA_12x(inst_data);
2285 shadow_frame.SetVRegFloat(vregA,
2286 fmodf(shadow_frame.GetVRegFloat(vregA),
2287 shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data))));
2288 inst = inst->Next_1xx();
2289 }
2290
2291 ALWAYS_INLINE void ADD_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002292 uint4_t vregA = inst->VRegA_12x(inst_data);
2293 shadow_frame.SetVRegDouble(vregA,
2294 shadow_frame.GetVRegDouble(vregA) +
2295 shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
2296 inst = inst->Next_1xx();
2297 }
2298
2299 ALWAYS_INLINE void SUB_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002300 uint4_t vregA = inst->VRegA_12x(inst_data);
2301 shadow_frame.SetVRegDouble(vregA,
2302 shadow_frame.GetVRegDouble(vregA) -
2303 shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
2304 inst = inst->Next_1xx();
2305 }
2306
2307 ALWAYS_INLINE void MUL_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002308 uint4_t vregA = inst->VRegA_12x(inst_data);
2309 shadow_frame.SetVRegDouble(vregA,
2310 shadow_frame.GetVRegDouble(vregA) *
2311 shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
2312 inst = inst->Next_1xx();
2313 }
2314
2315 ALWAYS_INLINE void DIV_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002316 uint4_t vregA = inst->VRegA_12x(inst_data);
2317 shadow_frame.SetVRegDouble(vregA,
2318 shadow_frame.GetVRegDouble(vregA) /
2319 shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
2320 inst = inst->Next_1xx();
2321 }
2322
2323 ALWAYS_INLINE void REM_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002324 uint4_t vregA = inst->VRegA_12x(inst_data);
2325 shadow_frame.SetVRegDouble(vregA,
2326 fmod(shadow_frame.GetVRegDouble(vregA),
2327 shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data))));
2328 inst = inst->Next_1xx();
2329 }
2330
2331 ALWAYS_INLINE void ADD_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002332 shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
2333 SafeAdd(shadow_frame.GetVReg(inst->VRegB_22s(inst_data)),
2334 inst->VRegC_22s()));
2335 inst = inst->Next_2xx();
2336 }
2337
2338 ALWAYS_INLINE void RSUB_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002339 shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
2340 SafeSub(inst->VRegC_22s(),
2341 shadow_frame.GetVReg(inst->VRegB_22s(inst_data))));
2342 inst = inst->Next_2xx();
2343 }
2344
2345 ALWAYS_INLINE void MUL_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002346 shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
2347 SafeMul(shadow_frame.GetVReg(inst->VRegB_22s(inst_data)),
2348 inst->VRegC_22s()));
2349 inst = inst->Next_2xx();
2350 }
2351
2352 ALWAYS_INLINE void DIV_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002353 bool success = DoIntDivide(shadow_frame, inst->VRegA_22s(inst_data),
2354 shadow_frame.GetVReg(inst->VRegB_22s(inst_data)),
2355 inst->VRegC_22s());
2356 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
2357 }
2358
2359 ALWAYS_INLINE void REM_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002360 bool success = DoIntRemainder(shadow_frame, inst->VRegA_22s(inst_data),
2361 shadow_frame.GetVReg(inst->VRegB_22s(inst_data)),
2362 inst->VRegC_22s());
2363 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
2364 }
2365
2366 ALWAYS_INLINE void AND_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002367 shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
2368 shadow_frame.GetVReg(inst->VRegB_22s(inst_data)) &
2369 inst->VRegC_22s());
2370 inst = inst->Next_2xx();
2371 }
2372
2373 ALWAYS_INLINE void OR_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002374 shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
2375 shadow_frame.GetVReg(inst->VRegB_22s(inst_data)) |
2376 inst->VRegC_22s());
2377 inst = inst->Next_2xx();
2378 }
2379
2380 ALWAYS_INLINE void XOR_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002381 shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
2382 shadow_frame.GetVReg(inst->VRegB_22s(inst_data)) ^
2383 inst->VRegC_22s());
2384 inst = inst->Next_2xx();
2385 }
2386
2387 ALWAYS_INLINE void ADD_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002388 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2389 SafeAdd(shadow_frame.GetVReg(inst->VRegB_22b()), inst->VRegC_22b()));
2390 inst = inst->Next_2xx();
2391 }
2392
2393 ALWAYS_INLINE void RSUB_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002394 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2395 SafeSub(inst->VRegC_22b(), shadow_frame.GetVReg(inst->VRegB_22b())));
2396 inst = inst->Next_2xx();
2397 }
2398
2399 ALWAYS_INLINE void MUL_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002400 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2401 SafeMul(shadow_frame.GetVReg(inst->VRegB_22b()), inst->VRegC_22b()));
2402 inst = inst->Next_2xx();
2403 }
2404
2405 ALWAYS_INLINE void DIV_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002406 bool success = DoIntDivide(shadow_frame, inst->VRegA_22b(inst_data),
2407 shadow_frame.GetVReg(inst->VRegB_22b()), inst->VRegC_22b());
2408 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
2409 }
2410
2411 ALWAYS_INLINE void REM_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002412 bool success = DoIntRemainder(shadow_frame, inst->VRegA_22b(inst_data),
2413 shadow_frame.GetVReg(inst->VRegB_22b()), inst->VRegC_22b());
2414 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
2415 }
2416
2417 ALWAYS_INLINE void AND_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002418 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2419 shadow_frame.GetVReg(inst->VRegB_22b()) &
2420 inst->VRegC_22b());
2421 inst = inst->Next_2xx();
2422 }
2423
2424 ALWAYS_INLINE void OR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002425 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2426 shadow_frame.GetVReg(inst->VRegB_22b()) |
2427 inst->VRegC_22b());
2428 inst = inst->Next_2xx();
2429 }
2430
2431 ALWAYS_INLINE void XOR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002432 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2433 shadow_frame.GetVReg(inst->VRegB_22b()) ^
2434 inst->VRegC_22b());
2435 inst = inst->Next_2xx();
2436 }
2437
2438 ALWAYS_INLINE void SHL_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002439 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2440 shadow_frame.GetVReg(inst->VRegB_22b()) <<
2441 (inst->VRegC_22b() & 0x1f));
2442 inst = inst->Next_2xx();
2443 }
2444
2445 ALWAYS_INLINE void SHR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002446 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2447 shadow_frame.GetVReg(inst->VRegB_22b()) >>
2448 (inst->VRegC_22b() & 0x1f));
2449 inst = inst->Next_2xx();
2450 }
2451
2452 ALWAYS_INLINE void USHR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01002453 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2454 static_cast<uint32_t>(shadow_frame.GetVReg(inst->VRegB_22b())) >>
2455 (inst->VRegC_22b() & 0x1f));
2456 inst = inst->Next_2xx();
2457 }
2458
2459 ALWAYS_INLINE void UNUSED_3E() REQUIRES_SHARED(Locks::mutator_lock_) {
2460 UnexpectedOpcode(inst, shadow_frame);
2461 }
2462
2463 ALWAYS_INLINE void UNUSED_3F() REQUIRES_SHARED(Locks::mutator_lock_) {
2464 UnexpectedOpcode(inst, shadow_frame);
2465 }
2466
2467 ALWAYS_INLINE void UNUSED_40() REQUIRES_SHARED(Locks::mutator_lock_) {
2468 UnexpectedOpcode(inst, shadow_frame);
2469 }
2470
2471 ALWAYS_INLINE void UNUSED_41() REQUIRES_SHARED(Locks::mutator_lock_) {
2472 UnexpectedOpcode(inst, shadow_frame);
2473 }
2474
2475 ALWAYS_INLINE void UNUSED_42() REQUIRES_SHARED(Locks::mutator_lock_) {
2476 UnexpectedOpcode(inst, shadow_frame);
2477 }
2478
2479 ALWAYS_INLINE void UNUSED_43() REQUIRES_SHARED(Locks::mutator_lock_) {
2480 UnexpectedOpcode(inst, shadow_frame);
2481 }
2482
2483 ALWAYS_INLINE void UNUSED_79() REQUIRES_SHARED(Locks::mutator_lock_) {
2484 UnexpectedOpcode(inst, shadow_frame);
2485 }
2486
2487 ALWAYS_INLINE void UNUSED_7A() REQUIRES_SHARED(Locks::mutator_lock_) {
2488 UnexpectedOpcode(inst, shadow_frame);
2489 }
2490
2491 ALWAYS_INLINE void UNUSED_F3() REQUIRES_SHARED(Locks::mutator_lock_) {
2492 UnexpectedOpcode(inst, shadow_frame);
2493 }
2494
2495 ALWAYS_INLINE void UNUSED_F4() REQUIRES_SHARED(Locks::mutator_lock_) {
2496 UnexpectedOpcode(inst, shadow_frame);
2497 }
2498
2499 ALWAYS_INLINE void UNUSED_F5() REQUIRES_SHARED(Locks::mutator_lock_) {
2500 UnexpectedOpcode(inst, shadow_frame);
2501 }
2502
2503 ALWAYS_INLINE void UNUSED_F6() REQUIRES_SHARED(Locks::mutator_lock_) {
2504 UnexpectedOpcode(inst, shadow_frame);
2505 }
2506
2507 ALWAYS_INLINE void UNUSED_F7() REQUIRES_SHARED(Locks::mutator_lock_) {
2508 UnexpectedOpcode(inst, shadow_frame);
2509 }
2510
2511 ALWAYS_INLINE void UNUSED_F8() REQUIRES_SHARED(Locks::mutator_lock_) {
2512 UnexpectedOpcode(inst, shadow_frame);
2513 }
2514
2515 ALWAYS_INLINE void UNUSED_F9() REQUIRES_SHARED(Locks::mutator_lock_) {
2516 UnexpectedOpcode(inst, shadow_frame);
2517 }
2518
2519 ALWAYS_INLINE InstructionHandler(SwitchImplContext* ctx,
2520 const instrumentation::Instrumentation* instrumentation,
2521 Thread* self,
2522 ShadowFrame& shadow_frame,
2523 uint16_t dex_pc,
2524 const Instruction*& inst,
2525 uint16_t inst_data,
2526 bool& exit_interpreter_loop)
2527 : ctx(ctx),
2528 instrumentation(instrumentation),
2529 self(self),
2530 shadow_frame(shadow_frame),
2531 dex_pc(dex_pc),
2532 inst(inst),
2533 inst_data(inst_data),
2534 exit_interpreter_loop(exit_interpreter_loop) {
2535 }
2536
2537 private:
2538 static constexpr bool do_assignability_check = do_access_check;
2539
2540 const CodeItemDataAccessor& Accessor() { return ctx->accessor; }
2541 const uint16_t* Insns() { return ctx->accessor.Insns(); }
2542 JValue* ResultRegister() { return &ctx->result_register; }
2543
2544 SwitchImplContext* const ctx;
2545 const instrumentation::Instrumentation* const instrumentation;
2546 Thread* const self;
2547 ShadowFrame& shadow_frame;
2548 uint32_t const dex_pc;
2549 const Instruction*& inst;
2550 uint16_t const inst_data;
2551 bool& exit_interpreter_loop;
2552};
2553
David Srbecky6da82472018-10-23 14:03:08 +01002554#undef BRANCH_INSTRUMENTATION
David Srbecky6da82472018-10-23 14:03:08 +01002555#undef POSSIBLY_HANDLE_PENDING_EXCEPTION
2556#undef POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE
2557#undef POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC
David Srbecky6da82472018-10-23 14:03:08 +01002558#undef HANDLE_PENDING_EXCEPTION
David Srbecky6da82472018-10-23 14:03:08 +01002559
Alex Light6f22e062018-10-05 15:05:12 -07002560// TODO On ASAN builds this function gets a huge stack frame. Since normally we run in the mterp
2561// this shouldn't cause any problems for stack overflow detection. Remove this once b/117341496 is
2562// fixed.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +01002563template<bool do_access_check, bool transaction_active>
Alex Light6f22e062018-10-05 15:05:12 -07002564ATTRIBUTE_NO_SANITIZE_ADDRESS void ExecuteSwitchImplCpp(SwitchImplContext* ctx) {
David Srbecky946bb092018-03-09 17:23:01 +00002565 Thread* self = ctx->self;
2566 const CodeItemDataAccessor& accessor = ctx->accessor;
2567 ShadowFrame& shadow_frame = ctx->shadow_frame;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002568 if (UNLIKELY(!shadow_frame.HasReferenceArray())) {
2569 LOG(FATAL) << "Invalid shadow frame for interpreter use";
David Srbecky946bb092018-03-09 17:23:01 +00002570 ctx->result = JValue();
2571 return;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002572 }
2573 self->VerifyStack();
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002574
2575 uint32_t dex_pc = shadow_frame.GetDexPC();
Mathieu Chartier2cebb242015-04-21 16:50:40 -07002576 const auto* const instrumentation = Runtime::Current()->GetInstrumentation();
Mathieu Chartier808c7a52017-12-15 11:19:33 -08002577 const uint16_t* const insns = accessor.Insns();
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002578 const Instruction* inst = Instruction::At(insns + dex_pc);
Sebastien Hertz3b588e02013-09-11 14:33:18 +02002579 uint16_t inst_data;
Igor Murashkin6918bf12015-09-27 19:19:06 -07002580
Alex Light0aa7a5a2018-10-10 15:58:14 +00002581 DCHECK(!shadow_frame.GetForceRetryInstruction())
2582 << "Entered interpreter from invoke without retry instruction being handled!";
2583
David Srbecky6da82472018-10-23 14:03:08 +01002584 bool const interpret_one_instruction = ctx->interpret_one_instruction;
2585 while (true) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002586 dex_pc = inst->GetDexPc(insns);
2587 shadow_frame.SetDexPC(dex_pc);
Ian Rogerse94652f2014-12-02 11:13:19 -08002588 TraceExecution(shadow_frame, inst, dex_pc);
Sebastien Hertz3b588e02013-09-11 14:33:18 +02002589 inst_data = inst->Fetch16(0);
2590 switch (inst->Opcode(inst_data)) {
David Srbecky6da82472018-10-23 14:03:08 +01002591#define OPCODE_CASE(OPCODE, OPCODE_NAME, pname, f, i, a, e, v) \
2592 case OPCODE: { \
2593 bool exit_loop = false; \
2594 InstructionHandler<do_access_check, transaction_active> handler( \
2595 ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, exit_loop); \
David Srbecky47ad3762018-10-31 12:43:40 +00002596 constexpr bool is_move_result_object = (OPCODE == Instruction::MOVE_RESULT_OBJECT); \
2597 if (handler.PreambleSave(is_move_result_object ? &ctx->result_register : nullptr)) { \
2598 handler.OPCODE_NAME(); \
2599 } \
David Srbecky6da82472018-10-23 14:03:08 +01002600 /* TODO: Advance 'inst' here, instead of explicitly in each handler */ \
2601 if (UNLIKELY(exit_loop)) { \
2602 return; \
2603 } \
2604 break; \
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002605 }
David Srbecky6da82472018-10-23 14:03:08 +01002606DEX_INSTRUCTION_LIST(OPCODE_CASE)
2607#undef OPCODE_CASE
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002608 }
David Srbecky6da82472018-10-23 14:03:08 +01002609 if (UNLIKELY(interpret_one_instruction)) {
2610 // Record where we stopped.
2611 shadow_frame.SetDexPC(inst->GetDexPc(insns));
2612 ctx->result = ctx->result_register;
2613 return;
2614 }
2615 }
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002616} // NOLINT(readability/fn_size)
2617
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002618} // namespace interpreter
2619} // namespace art
David Srbecky2ee09ff2018-10-24 13:24:22 +01002620
2621#endif // ART_RUNTIME_INTERPRETER_INTERPRETER_SWITCH_IMPL_INL_H_