blob: a487cd6630565d6a1595475e1ab12529e7081be8 [file] [log] [blame]
Sebastien Hertz8ece0502013-08-07 11:26:41 +02001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
David Srbecky2ee09ff2018-10-24 13:24:22 +010017#ifndef ART_RUNTIME_INTERPRETER_INTERPRETER_SWITCH_IMPL_INL_H_
18#define ART_RUNTIME_INTERPRETER_INTERPRETER_SWITCH_IMPL_INL_H_
19
Andreas Gampe5e26eb12016-08-22 17:54:17 -070020#include "interpreter_switch_impl.h"
21
Andreas Gampe542451c2016-07-26 09:02:02 -070022#include "base/enums.h"
Alex Light49af7042019-05-29 18:30:33 -070023#include "base/globals.h"
Alex Light6f22e062018-10-05 15:05:12 -070024#include "base/memory_tool.h"
David Sehrc431b9d2018-03-02 12:01:51 -080025#include "base/quasi_atomic.h"
David Sehr9e734c72018-01-04 17:56:19 -080026#include "dex/dex_file_types.h"
David Srbecky6da82472018-10-23 14:03:08 +010027#include "dex/dex_instruction_list.h"
Alex Lighteb7c1442015-08-31 13:17:42 -070028#include "experimental_flags.h"
Alex Light49af7042019-05-29 18:30:33 -070029#include "handle_scope.h"
Sebastien Hertz8ece0502013-08-07 11:26:41 +020030#include "interpreter_common.h"
Alex Light49af7042019-05-29 18:30:33 -070031#include "interpreter/shadow_frame.h"
David Srbeckye3fc2d12018-11-30 13:41:14 +000032#include "jit/jit-inl.h"
Mathieu Chartier28bd2e42016-10-04 13:54:57 -070033#include "jvalue-inl.h"
Andreas Gampefd63bbf2018-10-29 12:55:35 -070034#include "mirror/string-alloc-inl.h"
Alex Light49af7042019-05-29 18:30:33 -070035#include "mirror/throwable.h"
Alex Light0aa7a5a2018-10-10 15:58:14 +000036#include "nth_caller_visitor.h"
Ian Rogersf72a11d2014-10-30 15:41:08 -070037#include "safe_math.h"
Vladimir Marko6ec2a1b2018-05-22 15:33:48 +010038#include "shadow_frame-inl.h"
Alex Light0aa7a5a2018-10-10 15:58:14 +000039#include "thread.h"
Alex Light49af7042019-05-29 18:30:33 -070040#include "verifier/method_verifier.h"
Sebastien Hertz8ece0502013-08-07 11:26:41 +020041
42namespace art {
43namespace interpreter {
44
David Srbecky6da82472018-10-23 14:03:08 +010045// Short-lived helper class which executes single DEX bytecode. It is inlined by compiler.
46//
47// The function names must match the names from dex_instruction_list.h and have no arguments.
48//
49// Any relevant execution information is stored in the fields - it should be kept to minimum.
50//
David Srbecky47ad3762018-10-31 12:43:40 +000051// Helper methods may return boolean value - in which case 'false' always means
52// "stop executing current opcode" (which does not necessarily exit the interpreter loop).
53//
David Srbecky436f6c12019-05-22 13:28:42 +010054template<bool do_access_check, bool transaction_active, Instruction::Format kFormat>
David Srbecky6da82472018-10-23 14:03:08 +010055class InstructionHandler {
56 public:
Alex Light49af7042019-05-29 18:30:33 -070057 template <bool kMonitorCounting>
58 static NO_INLINE void UnlockHeldMonitors(Thread* self, ShadowFrame* shadow_frame)
59 REQUIRES_SHARED(Locks::mutator_lock_) {
60 DCHECK(shadow_frame->GetForcePopFrame());
61 // Unlock all monitors.
62 if (kMonitorCounting && shadow_frame->GetMethod()->MustCountLocks()) {
63 // Get the monitors from the shadow-frame monitor-count data.
64 shadow_frame->GetLockCountData().VisitMonitors(
65 [&](mirror::Object** obj) REQUIRES_SHARED(Locks::mutator_lock_) {
66 // Since we don't use the 'obj' pointer after the DoMonitorExit everything should be fine
67 // WRT suspension.
68 DoMonitorExit<do_assignability_check>(self, shadow_frame, *obj);
69 });
70 } else {
71 std::vector<verifier::MethodVerifier::DexLockInfo> locks;
72 verifier::MethodVerifier::FindLocksAtDexPc(shadow_frame->GetMethod(),
73 shadow_frame->GetDexPC(),
74 &locks,
75 Runtime::Current()->GetTargetSdkVersion());
76 for (const auto& reg : locks) {
77 if (UNLIKELY(reg.dex_registers.empty())) {
78 LOG(ERROR) << "Unable to determine reference locked by "
79 << shadow_frame->GetMethod()->PrettyMethod() << " at pc "
80 << shadow_frame->GetDexPC();
81 } else {
82 DoMonitorExit<do_assignability_check>(
83 self, shadow_frame, shadow_frame->GetVRegReference(*reg.dex_registers.begin()));
84 }
85 }
86 }
87 }
88
David Srbecky47ad3762018-10-31 12:43:40 +000089 ALWAYS_INLINE WARN_UNUSED bool CheckForceReturn()
90 REQUIRES_SHARED(Locks::mutator_lock_) {
91 if (UNLIKELY(shadow_frame.GetForcePopFrame())) {
92 DCHECK(PrevFrameWillRetry(self, shadow_frame))
93 << "Pop frame forced without previous frame ready to retry instruction!";
94 DCHECK(Runtime::Current()->AreNonStandardExitsEnabled());
Alex Light49af7042019-05-29 18:30:33 -070095 UnlockHeldMonitors<do_assignability_check>(self, &shadow_frame);
96 DoMonitorCheckOnExit<do_assignability_check>(self, &shadow_frame);
David Srbecky47ad3762018-10-31 12:43:40 +000097 if (UNLIKELY(NeedsMethodExitEvent(instrumentation))) {
98 SendMethodExitEvents(self,
99 instrumentation,
100 shadow_frame,
101 shadow_frame.GetThisObject(Accessor().InsSize()),
102 shadow_frame.GetMethod(),
103 inst->GetDexPc(Insns()),
104 JValue());
105 }
106 ctx->result = JValue(); /* Handled in caller. */
107 exit_interpreter_loop = true;
108 return false;
109 }
110 return true;
111 }
112
David Srbecky5f250012018-11-08 14:16:38 +0000113 NO_INLINE WARN_UNUSED bool HandlePendingExceptionWithInstrumentationImpl(
David Srbecky47ad3762018-10-31 12:43:40 +0000114 const instrumentation::Instrumentation* instr)
115 REQUIRES_SHARED(Locks::mutator_lock_) {
116 DCHECK(self->IsExceptionPending());
117 self->AllowThreadSuspension();
118 if (!CheckForceReturn()) {
119 return false;
120 }
121 if (!MoveToExceptionHandler(self, shadow_frame, instr)) {
122 /* Structured locking is to be enforced for abnormal termination, too. */
123 DoMonitorCheckOnExit<do_assignability_check>(self, &shadow_frame);
124 if (ctx->interpret_one_instruction) {
125 /* Signal mterp to return to caller */
126 shadow_frame.SetDexPC(dex::kDexNoIndex);
127 }
128 ctx->result = JValue(); /* Handled in caller. */
129 exit_interpreter_loop = true;
130 return false; // Return to caller.
131 }
132 if (!CheckForceReturn()) {
133 return false;
134 }
135 int32_t displacement =
136 static_cast<int32_t>(shadow_frame.GetDexPC()) - static_cast<int32_t>(dex_pc);
David Srbecky8867f3b2019-05-31 20:01:46 +0100137 SetNextInstruction(inst->RelativeAt(displacement));
David Srbecky47ad3762018-10-31 12:43:40 +0000138 inst = inst->RelativeAt(displacement);
139 return false; // Stop executing this opcode and continue in the exception handler.
140 }
141
David Srbecky5f250012018-11-08 14:16:38 +0000142 // Forwards the call to the NO_INLINE HandlePendingExceptionWithInstrumentationImpl.
143 ALWAYS_INLINE WARN_UNUSED bool HandlePendingExceptionWithInstrumentation(
144 const instrumentation::Instrumentation* instr)
145 REQUIRES_SHARED(Locks::mutator_lock_) {
146 // We need to help the compiler a bit to make the NO_INLINE call efficient.
147 // * All handler fields should be in registers, so we do not want to take the object
148 // address (for 'this' argument). Make a copy of the handler just for the slow path.
149 // * The modifiable fields should also be in registers, so we don't want to store their
150 // address even in the handler copy. Make a copy of them just for the call as well.
David Srbecky8867f3b2019-05-31 20:01:46 +0100151 const Instruction* inst2 = inst;
152 const Instruction* next2 = next;
153 bool exit2 = exit_interpreter_loop;
David Srbecky436f6c12019-05-22 13:28:42 +0100154 InstructionHandler<do_access_check, transaction_active, kFormat> handler_copy(
David Srbecky8867f3b2019-05-31 20:01:46 +0100155 ctx, instrumentation, self, shadow_frame, dex_pc, inst2, inst_data, next2, exit2);
David Srbecky5f250012018-11-08 14:16:38 +0000156 bool result = handler_copy.HandlePendingExceptionWithInstrumentationImpl(instr);
David Srbecky8867f3b2019-05-31 20:01:46 +0100157 inst = inst2;
158 next = next2;
159 exit_interpreter_loop = exit2;
David Srbecky5f250012018-11-08 14:16:38 +0000160 return result;
161 }
162
David Srbecky47ad3762018-10-31 12:43:40 +0000163 ALWAYS_INLINE WARN_UNUSED bool HandlePendingException()
164 REQUIRES_SHARED(Locks::mutator_lock_) {
165 return HandlePendingExceptionWithInstrumentation(instrumentation);
166 }
167
168 ALWAYS_INLINE WARN_UNUSED bool PossiblyHandlePendingExceptionOnInvokeImpl(
169 bool is_exception_pending,
170 const Instruction* next_inst)
171 REQUIRES_SHARED(Locks::mutator_lock_) {
172 if (UNLIKELY(shadow_frame.GetForceRetryInstruction())) {
173 /* Don't need to do anything except clear the flag and exception. We leave the */
174 /* instruction the same so it will be re-executed on the next go-around. */
175 DCHECK(inst->IsInvoke());
176 shadow_frame.SetForceRetryInstruction(false);
177 if (UNLIKELY(is_exception_pending)) {
178 DCHECK(self->IsExceptionPending());
179 if (kIsDebugBuild) {
180 LOG(WARNING) << "Suppressing exception for instruction-retry: "
181 << self->GetException()->Dump();
182 }
183 self->ClearException();
184 }
David Srbecky8867f3b2019-05-31 20:01:46 +0100185 SetNextInstruction(inst);
David Srbecky47ad3762018-10-31 12:43:40 +0000186 } else if (UNLIKELY(is_exception_pending)) {
187 /* Should have succeeded. */
188 DCHECK(!shadow_frame.GetForceRetryInstruction());
189 if (!HandlePendingException()) {
190 return false;
191 }
192 } else {
David Srbecky8867f3b2019-05-31 20:01:46 +0100193 SetNextInstruction(next_inst);
David Srbecky47ad3762018-10-31 12:43:40 +0000194 inst = next_inst;
195 }
196 return true;
197 }
198
199 ALWAYS_INLINE WARN_UNUSED bool PossiblyHandlePendingException(
200 bool is_exception_pending,
201 const Instruction* next_inst)
202 REQUIRES_SHARED(Locks::mutator_lock_) {
203 /* Should only be on invoke instructions. */
204 DCHECK(!shadow_frame.GetForceRetryInstruction());
205 if (UNLIKELY(is_exception_pending)) {
206 if (!HandlePendingException()) {
207 return false;
208 }
209 } else {
David Srbecky8867f3b2019-05-31 20:01:46 +0100210 SetNextInstruction(next_inst);
David Srbecky47ad3762018-10-31 12:43:40 +0000211 inst = next_inst;
212 }
213 return true;
214 }
215
216 ALWAYS_INLINE WARN_UNUSED bool HandleMonitorChecks()
217 REQUIRES_SHARED(Locks::mutator_lock_) {
218 if (!DoMonitorCheckOnExit<do_assignability_check>(self, &shadow_frame)) {
219 if (!HandlePendingException()) {
220 return false;
221 }
222 }
223 return true;
224 }
225
226 // Code to run before each dex instruction.
David Srbeckya4a96af2018-10-31 16:34:58 +0000227 ALWAYS_INLINE WARN_UNUSED bool Preamble()
David Srbecky47ad3762018-10-31 12:43:40 +0000228 REQUIRES_SHARED(Locks::mutator_lock_) {
229 /* We need to put this before & after the instrumentation to avoid having to put in a */
230 /* post-script macro. */
231 if (!CheckForceReturn()) {
232 return false;
233 }
234 if (UNLIKELY(instrumentation->HasDexPcListeners())) {
David Srbeckya4a96af2018-10-31 16:34:58 +0000235 uint8_t opcode = inst->Opcode(inst_data);
236 bool is_move_result_object = (opcode == Instruction::MOVE_RESULT_OBJECT);
237 JValue* save_ref = is_move_result_object ? &ctx->result_register : nullptr;
David Srbecky47ad3762018-10-31 12:43:40 +0000238 if (UNLIKELY(!DoDexPcMoveEvent(self,
239 Accessor(),
240 shadow_frame,
241 dex_pc,
242 instrumentation,
243 save_ref))) {
244 if (!HandlePendingException()) {
245 return false;
246 }
247 }
248 if (!CheckForceReturn()) {
249 return false;
250 }
251 }
252 return true;
253 }
254
255 ALWAYS_INLINE WARN_UNUSED bool BranchInstrumentation(int32_t offset)
256 REQUIRES_SHARED(Locks::mutator_lock_) {
257 if (UNLIKELY(instrumentation->HasBranchListeners())) {
258 instrumentation->Branch(self, shadow_frame.GetMethod(), dex_pc, offset);
259 }
260 JValue result;
261 if (jit::Jit::MaybeDoOnStackReplacement(self,
262 shadow_frame.GetMethod(),
263 dex_pc,
264 offset,
265 &result)) {
266 if (ctx->interpret_one_instruction) {
267 /* OSR has completed execution of the method. Signal mterp to return to caller */
268 shadow_frame.SetDexPC(dex::kDexNoIndex);
269 }
270 ctx->result = result;
271 exit_interpreter_loop = true;
272 return false;
273 }
274 return true;
275 }
276
277 ALWAYS_INLINE void HotnessUpdate()
278 REQUIRES_SHARED(Locks::mutator_lock_) {
279 jit::Jit* jit = Runtime::Current()->GetJit();
280 if (jit != nullptr) {
281 jit->AddSamples(self, shadow_frame.GetMethod(), 1, /*with_backedges=*/ true);
282 }
283 }
284
285 ALWAYS_INLINE WARN_UNUSED bool HandleAsyncException()
286 REQUIRES_SHARED(Locks::mutator_lock_) {
287 if (UNLIKELY(self->ObserveAsyncException())) {
288 if (!HandlePendingException()) {
289 return false;
290 }
291 }
292 return true;
293 }
294
295 ALWAYS_INLINE void HandleBackwardBranch(int32_t offset)
296 REQUIRES_SHARED(Locks::mutator_lock_) {
297 if (IsBackwardBranch(offset)) {
298 HotnessUpdate();
299 /* Record new dex pc early to have consistent suspend point at loop header. */
300 shadow_frame.SetDexPC(inst->GetDexPc(Insns()));
301 self->AllowThreadSuspension();
302 }
303 }
304
305 // Unlike most other events the DexPcMovedEvent can be sent when there is a pending exception (if
306 // the next instruction is MOVE_EXCEPTION). This means it needs to be handled carefully to be able
307 // to detect exceptions thrown by the DexPcMovedEvent itself. These exceptions could be thrown by
308 // jvmti-agents while handling breakpoint or single step events. We had to move this into its own
309 // function because it was making ExecuteSwitchImpl have too large a stack.
310 NO_INLINE static bool DoDexPcMoveEvent(Thread* self,
311 const CodeItemDataAccessor& accessor,
312 const ShadowFrame& shadow_frame,
313 uint32_t dex_pc,
314 const instrumentation::Instrumentation* instrumentation,
315 JValue* save_ref)
316 REQUIRES_SHARED(Locks::mutator_lock_) {
317 DCHECK(instrumentation->HasDexPcListeners());
318 StackHandleScope<2> hs(self);
319 Handle<mirror::Throwable> thr(hs.NewHandle(self->GetException()));
320 mirror::Object* null_obj = nullptr;
321 HandleWrapper<mirror::Object> h(
322 hs.NewHandleWrapper(LIKELY(save_ref == nullptr) ? &null_obj : save_ref->GetGCRoot()));
323 self->ClearException();
324 instrumentation->DexPcMovedEvent(self,
325 shadow_frame.GetThisObject(accessor.InsSize()),
326 shadow_frame.GetMethod(),
327 dex_pc);
328 if (UNLIKELY(self->IsExceptionPending())) {
329 // We got a new exception in the dex-pc-moved event.
330 // We just let this exception replace the old one.
331 // TODO It would be good to add the old exception to the
332 // suppressed exceptions of the new one if possible.
333 return false;
334 } else {
335 if (UNLIKELY(!thr.IsNull())) {
336 self->SetException(thr.Get());
337 }
338 return true;
339 }
340 }
341
342 static bool NeedsMethodExitEvent(const instrumentation::Instrumentation* ins)
343 REQUIRES_SHARED(Locks::mutator_lock_) {
344 return ins->HasMethodExitListeners() || ins->HasWatchedFramePopListeners();
345 }
346
347 // Sends the normal method exit event.
348 // Returns true if the events succeeded and false if there is a pending exception.
349 NO_INLINE static bool SendMethodExitEvents(
350 Thread* self,
351 const instrumentation::Instrumentation* instrumentation,
352 const ShadowFrame& frame,
353 ObjPtr<mirror::Object> thiz,
354 ArtMethod* method,
355 uint32_t dex_pc,
356 const JValue& result)
357 REQUIRES_SHARED(Locks::mutator_lock_) {
358 bool had_event = false;
359 // We don't send method-exit if it's a pop-frame. We still send frame_popped though.
360 if (UNLIKELY(instrumentation->HasMethodExitListeners() && !frame.GetForcePopFrame())) {
361 had_event = true;
Vladimir Marko19711d42019-04-12 14:05:34 +0100362 instrumentation->MethodExitEvent(self, thiz, method, dex_pc, result);
David Srbecky47ad3762018-10-31 12:43:40 +0000363 }
364 if (UNLIKELY(frame.NeedsNotifyPop() && instrumentation->HasWatchedFramePopListeners())) {
365 had_event = true;
366 instrumentation->WatchedFramePopped(self, frame);
367 }
368 if (UNLIKELY(had_event)) {
369 return !self->IsExceptionPending();
370 } else {
371 return true;
372 }
373 }
374
375#define BRANCH_INSTRUMENTATION(offset) \
376 if (!BranchInstrumentation(offset)) { \
David Srbeckybd613ec2019-05-30 15:39:38 +0100377 return false; \
David Srbecky47ad3762018-10-31 12:43:40 +0000378 }
379
380#define HANDLE_PENDING_EXCEPTION() \
381 if (!HandlePendingException()) { \
David Srbeckybd613ec2019-05-30 15:39:38 +0100382 return false; \
David Srbecky47ad3762018-10-31 12:43:40 +0000383 }
384
385#define POSSIBLY_HANDLE_PENDING_EXCEPTION(is_exception_pending, next_function) \
386 if (!PossiblyHandlePendingException(is_exception_pending, inst->next_function())) { \
David Srbeckybd613ec2019-05-30 15:39:38 +0100387 return false; \
David Srbecky47ad3762018-10-31 12:43:40 +0000388 }
389
390#define POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(is_exception_pending) \
391 if (!PossiblyHandlePendingExceptionOnInvokeImpl(is_exception_pending, inst->Next_4xx())) { \
David Srbeckybd613ec2019-05-30 15:39:38 +0100392 return false; \
David Srbecky47ad3762018-10-31 12:43:40 +0000393 }
394
395#define POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(is_exception_pending) \
396 if (!PossiblyHandlePendingExceptionOnInvokeImpl(is_exception_pending, inst->Next_3xx())) { \
David Srbeckybd613ec2019-05-30 15:39:38 +0100397 return false; \
David Srbecky47ad3762018-10-31 12:43:40 +0000398 }
399
David Srbeckyee12e3a2019-06-03 15:18:57 +0100400 ALWAYS_INLINE WARN_UNUSED bool HandleReturn(JValue result) REQUIRES_SHARED(Locks::mutator_lock_) {
401 self->AllowThreadSuspension();
402 if (!HandleMonitorChecks()) {
403 return false;
404 }
405 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
406 !SendMethodExitEvents(self,
407 instrumentation,
408 shadow_frame,
409 shadow_frame.GetThisObject(Accessor().InsSize()),
410 shadow_frame.GetMethod(),
411 inst->GetDexPc(Insns()),
412 result))) {
413 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
414 return false;
415 }
416 }
417 if (ctx->interpret_one_instruction) {
418 /* Signal mterp to return to caller */
419 shadow_frame.SetDexPC(dex::kDexNoIndex);
420 }
421 ctx->result = result;
422 exit_interpreter_loop = true;
423 return true;
424 }
425
426 ALWAYS_INLINE WARN_UNUSED bool HandleGoto(int32_t offset) REQUIRES_SHARED(Locks::mutator_lock_) {
427 if (!HandleAsyncException()) {
428 return false;
429 }
430 BRANCH_INSTRUMENTATION(offset);
David Srbecky8867f3b2019-05-31 20:01:46 +0100431 SetNextInstruction(inst->RelativeAt(offset));
David Srbeckyee12e3a2019-06-03 15:18:57 +0100432 inst = inst->RelativeAt(offset);
433 HandleBackwardBranch(offset);
434 return true;
435 }
436
437#pragma clang diagnostic push
438#pragma clang diagnostic ignored "-Wfloat-equal"
439
440 template<typename T>
441 ALWAYS_INLINE WARN_UNUSED bool HandleCmpl(T val1, T val2) REQUIRES_SHARED(Locks::mutator_lock_) {
442 int32_t result;
443 if (val1 > val2) {
444 result = 1;
445 } else if (val1 == val2) {
446 result = 0;
447 } else {
448 result = -1;
449 }
450 SetVReg(A(), result);
451 inst = inst->Next_2xx();
452 return true;
453 }
454
455 // Returns the same result as the function above. It only differs for NaN values.
456 template<typename T>
457 ALWAYS_INLINE WARN_UNUSED bool HandleCmpg(T val1, T val2) REQUIRES_SHARED(Locks::mutator_lock_) {
458 int32_t result;
459 if (val1 < val2) {
460 result = -1;
461 } else if (val1 == val2) {
462 result = 0;
463 } else {
464 result = 1;
465 }
466 SetVReg(A(), result);
467 inst = inst->Next_2xx();
468 return true;
469 }
470
471#pragma clang diagnostic pop
472
473 ALWAYS_INLINE WARN_UNUSED bool HandleIf(bool cond, int32_t offset)
474 REQUIRES_SHARED(Locks::mutator_lock_) {
475 if (cond) {
476 BRANCH_INSTRUMENTATION(offset);
David Srbecky8867f3b2019-05-31 20:01:46 +0100477 SetNextInstruction(inst->RelativeAt(offset));
David Srbeckyee12e3a2019-06-03 15:18:57 +0100478 inst = inst->RelativeAt(offset);
479 HandleBackwardBranch(offset);
480 } else {
481 BRANCH_INSTRUMENTATION(2);
482 inst = inst->Next_2xx();
483 }
484 return true;
485 }
486
David Srbecky1332c262019-06-04 13:13:37 +0100487 template<typename ArrayType, typename SetVRegFn>
488 ALWAYS_INLINE bool HandleAGet(SetVRegFn setVReg) REQUIRES_SHARED(Locks::mutator_lock_) {
489 ObjPtr<mirror::Object> a = GetVRegReference(B());
490 if (UNLIKELY(a == nullptr)) {
491 ThrowNullPointerExceptionFromInterpreter();
492 HANDLE_PENDING_EXCEPTION();
493 }
494 int32_t index = GetVReg(C());
495 ObjPtr<ArrayType> array = ObjPtr<ArrayType>::DownCast(a);
496 if (UNLIKELY(!array->CheckIsValidIndex(index))) {
497 HANDLE_PENDING_EXCEPTION();
498 } else {
499 (this->*setVReg)(A(), array->GetWithoutChecks(index));
500 inst = inst->Next_2xx();
501 }
502 return true;
503 }
504
505 template<typename ArrayType, typename T>
506 ALWAYS_INLINE bool HandleAPut(T value) REQUIRES_SHARED(Locks::mutator_lock_) {
507 ObjPtr<mirror::Object> a = GetVRegReference(B());
508 if (UNLIKELY(a == nullptr)) {
509 ThrowNullPointerExceptionFromInterpreter();
510 HANDLE_PENDING_EXCEPTION();
511 }
512 int32_t index = GetVReg(C());
513 ObjPtr<ArrayType> array = ObjPtr<ArrayType>::DownCast(a);
514 if (UNLIKELY(!array->CheckIsValidIndex(index))) {
515 HANDLE_PENDING_EXCEPTION();
516 } else {
517 array->template SetWithoutChecks<transaction_active>(index, value);
518 inst = inst->Next_2xx();
519 }
520 return true;
521 }
522
David Srbeckyee12e3a2019-06-03 15:18:57 +0100523 template<FindFieldType find_type, Primitive::Type field_type>
524 ALWAYS_INLINE WARN_UNUSED bool HandleGet() REQUIRES_SHARED(Locks::mutator_lock_) {
525 bool success = DoFieldGet<find_type, field_type, do_access_check, transaction_active>(
526 self, shadow_frame, inst, inst_data);
527 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
528 return true;
529 }
530
531 template<Primitive::Type field_type>
532 ALWAYS_INLINE WARN_UNUSED bool HandleGetQuick() REQUIRES_SHARED(Locks::mutator_lock_) {
533 bool success = DoIGetQuick<field_type>(shadow_frame, inst, inst_data);
534 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
535 return true;
536 }
537
538 template<FindFieldType find_type, Primitive::Type field_type>
539 ALWAYS_INLINE WARN_UNUSED bool HandlePut() REQUIRES_SHARED(Locks::mutator_lock_) {
540 bool success = DoFieldPut<find_type, field_type, do_access_check, transaction_active>(
541 self, shadow_frame, inst, inst_data);
542 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
543 return true;
544 }
545
546 template<Primitive::Type field_type>
547 ALWAYS_INLINE WARN_UNUSED bool HandlePutQuick() REQUIRES_SHARED(Locks::mutator_lock_) {
548 bool success = DoIPutQuick<field_type, transaction_active>(
549 shadow_frame, inst, inst_data);
550 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
551 return true;
552 }
553
554 template<InvokeType type, bool is_range, bool is_quick = false>
555 ALWAYS_INLINE WARN_UNUSED bool HandleInvoke() REQUIRES_SHARED(Locks::mutator_lock_) {
556 bool success = DoInvoke<type, is_range, do_access_check, /*is_mterp=*/ false, is_quick>(
557 self, shadow_frame, inst, inst_data, ResultRegister());
558 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
559 return true;
560 }
561
562 ALWAYS_INLINE WARN_UNUSED bool HandleUnused() REQUIRES_SHARED(Locks::mutator_lock_) {
563 UnexpectedOpcode(inst, shadow_frame);
564 return true;
565 }
566
David Srbeckybd613ec2019-05-30 15:39:38 +0100567 ALWAYS_INLINE bool NOP() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100568 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +0100569 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100570 }
571
David Srbeckybd613ec2019-05-30 15:39:38 +0100572 ALWAYS_INLINE bool MOVE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100573 SetVReg(A(), GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100574 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +0100575 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100576 }
577
David Srbeckybd613ec2019-05-30 15:39:38 +0100578 ALWAYS_INLINE bool MOVE_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100579 SetVReg(A(), GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100580 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +0100581 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100582 }
583
David Srbeckybd613ec2019-05-30 15:39:38 +0100584 ALWAYS_INLINE bool MOVE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100585 SetVReg(A(), GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100586 inst = inst->Next_3xx();
David Srbeckybd613ec2019-05-30 15:39:38 +0100587 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100588 }
589
David Srbeckybd613ec2019-05-30 15:39:38 +0100590 ALWAYS_INLINE bool MOVE_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100591 SetVRegLong(A(), GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100592 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +0100593 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100594 }
595
David Srbeckybd613ec2019-05-30 15:39:38 +0100596 ALWAYS_INLINE bool MOVE_WIDE_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100597 SetVRegLong(A(), GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100598 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +0100599 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100600 }
601
David Srbeckybd613ec2019-05-30 15:39:38 +0100602 ALWAYS_INLINE bool MOVE_WIDE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100603 SetVRegLong(A(), GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100604 inst = inst->Next_3xx();
David Srbeckybd613ec2019-05-30 15:39:38 +0100605 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100606 }
607
David Srbeckybd613ec2019-05-30 15:39:38 +0100608 ALWAYS_INLINE bool MOVE_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100609 SetVRegReference(A(), GetVRegReference(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100610 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +0100611 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100612 }
613
David Srbeckybd613ec2019-05-30 15:39:38 +0100614 ALWAYS_INLINE bool MOVE_OBJECT_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100615 SetVRegReference(A(), GetVRegReference(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100616 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +0100617 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100618 }
619
David Srbeckybd613ec2019-05-30 15:39:38 +0100620 ALWAYS_INLINE bool MOVE_OBJECT_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100621 SetVRegReference(A(), GetVRegReference(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100622 inst = inst->Next_3xx();
David Srbeckybd613ec2019-05-30 15:39:38 +0100623 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100624 }
625
David Srbeckybd613ec2019-05-30 15:39:38 +0100626 ALWAYS_INLINE bool MOVE_RESULT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100627 SetVReg(A(), ResultRegister()->GetI());
David Srbecky6da82472018-10-23 14:03:08 +0100628 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +0100629 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100630 }
631
David Srbeckybd613ec2019-05-30 15:39:38 +0100632 ALWAYS_INLINE bool MOVE_RESULT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100633 SetVRegLong(A(), ResultRegister()->GetJ());
David Srbecky6da82472018-10-23 14:03:08 +0100634 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +0100635 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100636 }
637
David Srbeckybd613ec2019-05-30 15:39:38 +0100638 ALWAYS_INLINE bool MOVE_RESULT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100639 SetVRegReference(A(), ResultRegister()->GetL());
David Srbecky6da82472018-10-23 14:03:08 +0100640 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +0100641 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100642 }
643
David Srbeckybd613ec2019-05-30 15:39:38 +0100644 ALWAYS_INLINE bool MOVE_EXCEPTION() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100645 ObjPtr<mirror::Throwable> exception = self->GetException();
646 DCHECK(exception != nullptr) << "No pending exception on MOVE_EXCEPTION instruction";
David Srbecky6baf6442019-05-30 14:57:43 +0100647 SetVRegReference(A(), exception);
David Srbecky6da82472018-10-23 14:03:08 +0100648 self->ClearException();
649 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +0100650 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100651 }
652
David Srbeckybd613ec2019-05-30 15:39:38 +0100653 ALWAYS_INLINE bool RETURN_VOID_NO_BARRIER() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100654 JValue result;
David Srbeckyee12e3a2019-06-03 15:18:57 +0100655 return HandleReturn(result);
David Srbecky6da82472018-10-23 14:03:08 +0100656 }
657
David Srbeckybd613ec2019-05-30 15:39:38 +0100658 ALWAYS_INLINE bool RETURN_VOID() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100659 QuasiAtomic::ThreadFenceForConstructor();
660 JValue result;
David Srbeckyee12e3a2019-06-03 15:18:57 +0100661 return HandleReturn(result);
David Srbecky6da82472018-10-23 14:03:08 +0100662 }
663
David Srbeckybd613ec2019-05-30 15:39:38 +0100664 ALWAYS_INLINE bool RETURN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100665 JValue result;
666 result.SetJ(0);
David Srbecky6baf6442019-05-30 14:57:43 +0100667 result.SetI(GetVReg(A()));
David Srbeckyee12e3a2019-06-03 15:18:57 +0100668 return HandleReturn(result);
David Srbecky6da82472018-10-23 14:03:08 +0100669 }
670
David Srbeckybd613ec2019-05-30 15:39:38 +0100671 ALWAYS_INLINE bool RETURN_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100672 JValue result;
David Srbecky6baf6442019-05-30 14:57:43 +0100673 result.SetJ(GetVRegLong(A()));
David Srbeckyee12e3a2019-06-03 15:18:57 +0100674 return HandleReturn(result);
David Srbecky6da82472018-10-23 14:03:08 +0100675 }
676
David Srbeckybd613ec2019-05-30 15:39:38 +0100677 ALWAYS_INLINE bool RETURN_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100678 JValue result;
679 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000680 if (!HandleMonitorChecks()) {
David Srbeckybd613ec2019-05-30 15:39:38 +0100681 return false;
David Srbecky47ad3762018-10-31 12:43:40 +0000682 }
David Srbeckyd6f579c2019-05-29 18:09:30 +0100683 const size_t ref_idx = A();
David Srbecky6baf6442019-05-30 14:57:43 +0100684 ObjPtr<mirror::Object> obj_result = GetVRegReference(ref_idx);
David Srbecky6da82472018-10-23 14:03:08 +0100685 if (do_assignability_check && obj_result != nullptr) {
686 ObjPtr<mirror::Class> return_type = shadow_frame.GetMethod()->ResolveReturnType();
687 // Re-load since it might have moved.
David Srbecky6baf6442019-05-30 14:57:43 +0100688 obj_result = GetVRegReference(ref_idx);
David Srbecky6da82472018-10-23 14:03:08 +0100689 if (return_type == nullptr) {
690 // Return the pending exception.
691 HANDLE_PENDING_EXCEPTION();
692 }
693 if (!obj_result->VerifierInstanceOf(return_type)) {
694 // This should never happen.
695 std::string temp1, temp2;
696 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
697 "Returning '%s' that is not instance of return type '%s'",
698 obj_result->GetClass()->GetDescriptor(&temp1),
699 return_type->GetDescriptor(&temp2));
700 HANDLE_PENDING_EXCEPTION();
701 }
702 }
703 result.SetL(obj_result);
704 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
705 !SendMethodExitEvents(self,
706 instrumentation,
707 shadow_frame,
708 shadow_frame.GetThisObject(Accessor().InsSize()),
709 shadow_frame.GetMethod(),
710 inst->GetDexPc(Insns()),
711 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000712 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
David Srbeckybd613ec2019-05-30 15:39:38 +0100713 return false;
David Srbecky47ad3762018-10-31 12:43:40 +0000714 }
David Srbecky6da82472018-10-23 14:03:08 +0100715 }
716 // Re-load since it might have moved during the MethodExitEvent.
David Srbecky6baf6442019-05-30 14:57:43 +0100717 result.SetL(GetVRegReference(ref_idx));
David Srbecky6da82472018-10-23 14:03:08 +0100718 if (ctx->interpret_one_instruction) {
719 /* Signal mterp to return to caller */
720 shadow_frame.SetDexPC(dex::kDexNoIndex);
721 }
722 ctx->result = result;
723 exit_interpreter_loop = true;
David Srbeckybd613ec2019-05-30 15:39:38 +0100724 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100725 }
726
David Srbeckybd613ec2019-05-30 15:39:38 +0100727 ALWAYS_INLINE bool CONST_4() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100728 uint4_t dst = inst->VRegA_11n(inst_data);
729 int4_t val = inst->VRegB_11n(inst_data);
David Srbecky6baf6442019-05-30 14:57:43 +0100730 SetVReg(dst, val);
David Srbecky6da82472018-10-23 14:03:08 +0100731 if (val == 0) {
David Srbecky6baf6442019-05-30 14:57:43 +0100732 SetVRegReference(dst, nullptr);
David Srbecky6da82472018-10-23 14:03:08 +0100733 }
734 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +0100735 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100736 }
737
David Srbeckybd613ec2019-05-30 15:39:38 +0100738 ALWAYS_INLINE bool CONST_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100739 uint8_t dst = A();
740 int16_t val = B();
David Srbecky6baf6442019-05-30 14:57:43 +0100741 SetVReg(dst, val);
David Srbecky6da82472018-10-23 14:03:08 +0100742 if (val == 0) {
David Srbecky6baf6442019-05-30 14:57:43 +0100743 SetVRegReference(dst, nullptr);
David Srbecky6da82472018-10-23 14:03:08 +0100744 }
745 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +0100746 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100747 }
748
David Srbeckybd613ec2019-05-30 15:39:38 +0100749 ALWAYS_INLINE bool CONST() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100750 uint8_t dst = A();
751 int32_t val = B();
David Srbecky6baf6442019-05-30 14:57:43 +0100752 SetVReg(dst, val);
David Srbecky6da82472018-10-23 14:03:08 +0100753 if (val == 0) {
David Srbecky6baf6442019-05-30 14:57:43 +0100754 SetVRegReference(dst, nullptr);
David Srbecky6da82472018-10-23 14:03:08 +0100755 }
756 inst = inst->Next_3xx();
David Srbeckybd613ec2019-05-30 15:39:38 +0100757 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100758 }
759
David Srbeckybd613ec2019-05-30 15:39:38 +0100760 ALWAYS_INLINE bool CONST_HIGH16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100761 uint8_t dst = A();
762 int32_t val = static_cast<int32_t>(B() << 16);
David Srbecky6baf6442019-05-30 14:57:43 +0100763 SetVReg(dst, val);
David Srbecky6da82472018-10-23 14:03:08 +0100764 if (val == 0) {
David Srbecky6baf6442019-05-30 14:57:43 +0100765 SetVRegReference(dst, nullptr);
David Srbecky6da82472018-10-23 14:03:08 +0100766 }
767 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +0100768 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100769 }
770
David Srbeckybd613ec2019-05-30 15:39:38 +0100771 ALWAYS_INLINE bool CONST_WIDE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100772 SetVRegLong(A(), B());
David Srbecky6da82472018-10-23 14:03:08 +0100773 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +0100774 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100775 }
776
David Srbeckybd613ec2019-05-30 15:39:38 +0100777 ALWAYS_INLINE bool CONST_WIDE_32() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100778 SetVRegLong(A(), B());
David Srbecky6da82472018-10-23 14:03:08 +0100779 inst = inst->Next_3xx();
David Srbeckybd613ec2019-05-30 15:39:38 +0100780 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100781 }
782
David Srbeckybd613ec2019-05-30 15:39:38 +0100783 ALWAYS_INLINE bool CONST_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100784 SetVRegLong(A(), inst->WideVRegB());
David Srbecky6da82472018-10-23 14:03:08 +0100785 inst = inst->Next_51l();
David Srbeckybd613ec2019-05-30 15:39:38 +0100786 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100787 }
788
David Srbeckybd613ec2019-05-30 15:39:38 +0100789 ALWAYS_INLINE bool CONST_WIDE_HIGH16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100790 SetVRegLong(A(), static_cast<uint64_t>(B()) << 48);
David Srbecky6da82472018-10-23 14:03:08 +0100791 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +0100792 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100793 }
794
David Srbeckybd613ec2019-05-30 15:39:38 +0100795 ALWAYS_INLINE bool CONST_STRING() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100796 ObjPtr<mirror::String> s = ResolveString(self, shadow_frame, dex::StringIndex(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100797 if (UNLIKELY(s == nullptr)) {
798 HANDLE_PENDING_EXCEPTION();
799 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100800 SetVRegReference(A(), s);
David Srbecky6da82472018-10-23 14:03:08 +0100801 inst = inst->Next_2xx();
802 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100803 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100804 }
805
David Srbeckybd613ec2019-05-30 15:39:38 +0100806 ALWAYS_INLINE bool CONST_STRING_JUMBO() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100807 ObjPtr<mirror::String> s = ResolveString(self, shadow_frame, dex::StringIndex(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100808 if (UNLIKELY(s == nullptr)) {
809 HANDLE_PENDING_EXCEPTION();
810 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100811 SetVRegReference(A(), s);
David Srbecky6da82472018-10-23 14:03:08 +0100812 inst = inst->Next_3xx();
813 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100814 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100815 }
816
David Srbeckybd613ec2019-05-30 15:39:38 +0100817 ALWAYS_INLINE bool CONST_CLASS() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100818 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(B()),
David Srbecky6da82472018-10-23 14:03:08 +0100819 shadow_frame.GetMethod(),
820 self,
821 false,
822 do_access_check);
823 if (UNLIKELY(c == nullptr)) {
824 HANDLE_PENDING_EXCEPTION();
825 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100826 SetVRegReference(A(), c);
David Srbecky6da82472018-10-23 14:03:08 +0100827 inst = inst->Next_2xx();
828 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100829 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100830 }
831
David Srbeckybd613ec2019-05-30 15:39:38 +0100832 ALWAYS_INLINE bool CONST_METHOD_HANDLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100833 ClassLinker* cl = Runtime::Current()->GetClassLinker();
834 ObjPtr<mirror::MethodHandle> mh = cl->ResolveMethodHandle(self,
David Srbeckyd6f579c2019-05-29 18:09:30 +0100835 B(),
David Srbecky6da82472018-10-23 14:03:08 +0100836 shadow_frame.GetMethod());
837 if (UNLIKELY(mh == nullptr)) {
838 HANDLE_PENDING_EXCEPTION();
839 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100840 SetVRegReference(A(), mh);
David Srbecky6da82472018-10-23 14:03:08 +0100841 inst = inst->Next_2xx();
842 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100843 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100844 }
845
David Srbeckybd613ec2019-05-30 15:39:38 +0100846 ALWAYS_INLINE bool CONST_METHOD_TYPE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100847 ClassLinker* cl = Runtime::Current()->GetClassLinker();
848 ObjPtr<mirror::MethodType> mt = cl->ResolveMethodType(self,
David Srbeckyd6f579c2019-05-29 18:09:30 +0100849 dex::ProtoIndex(B()),
David Srbecky6da82472018-10-23 14:03:08 +0100850 shadow_frame.GetMethod());
851 if (UNLIKELY(mt == nullptr)) {
852 HANDLE_PENDING_EXCEPTION();
853 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100854 SetVRegReference(A(), mt);
David Srbecky6da82472018-10-23 14:03:08 +0100855 inst = inst->Next_2xx();
856 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100857 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100858 }
859
David Srbeckybd613ec2019-05-30 15:39:38 +0100860 ALWAYS_INLINE bool MONITOR_ENTER() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000861 if (!HandleAsyncException()) {
David Srbeckybd613ec2019-05-30 15:39:38 +0100862 return false;
David Srbecky47ad3762018-10-31 12:43:40 +0000863 }
David Srbecky6baf6442019-05-30 14:57:43 +0100864 ObjPtr<mirror::Object> obj = GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +0100865 if (UNLIKELY(obj == nullptr)) {
866 ThrowNullPointerExceptionFromInterpreter();
867 HANDLE_PENDING_EXCEPTION();
868 } else {
869 DoMonitorEnter<do_assignability_check>(self, &shadow_frame, obj);
870 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
871 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100872 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100873 }
874
David Srbeckybd613ec2019-05-30 15:39:38 +0100875 ALWAYS_INLINE bool MONITOR_EXIT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000876 if (!HandleAsyncException()) {
David Srbeckybd613ec2019-05-30 15:39:38 +0100877 return false;
David Srbecky47ad3762018-10-31 12:43:40 +0000878 }
David Srbecky6baf6442019-05-30 14:57:43 +0100879 ObjPtr<mirror::Object> obj = GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +0100880 if (UNLIKELY(obj == nullptr)) {
881 ThrowNullPointerExceptionFromInterpreter();
882 HANDLE_PENDING_EXCEPTION();
883 } else {
884 DoMonitorExit<do_assignability_check>(self, &shadow_frame, obj);
885 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
886 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100887 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100888 }
889
David Srbeckybd613ec2019-05-30 15:39:38 +0100890 ALWAYS_INLINE bool CHECK_CAST() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100891 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(B()),
David Srbecky6da82472018-10-23 14:03:08 +0100892 shadow_frame.GetMethod(),
893 self,
894 false,
895 do_access_check);
896 if (UNLIKELY(c == nullptr)) {
897 HANDLE_PENDING_EXCEPTION();
898 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100899 ObjPtr<mirror::Object> obj = GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +0100900 if (UNLIKELY(obj != nullptr && !obj->InstanceOf(c))) {
901 ThrowClassCastException(c, obj->GetClass());
902 HANDLE_PENDING_EXCEPTION();
903 } else {
904 inst = inst->Next_2xx();
905 }
906 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100907 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100908 }
909
David Srbeckybd613ec2019-05-30 15:39:38 +0100910 ALWAYS_INLINE bool INSTANCE_OF() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100911 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(C()),
David Srbecky6da82472018-10-23 14:03:08 +0100912 shadow_frame.GetMethod(),
913 self,
914 false,
915 do_access_check);
916 if (UNLIKELY(c == nullptr)) {
917 HANDLE_PENDING_EXCEPTION();
918 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100919 ObjPtr<mirror::Object> obj = GetVRegReference(B());
920 SetVReg(A(), (obj != nullptr && obj->InstanceOf(c)) ? 1 : 0);
David Srbecky6da82472018-10-23 14:03:08 +0100921 inst = inst->Next_2xx();
922 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100923 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100924 }
925
David Srbeckybd613ec2019-05-30 15:39:38 +0100926 ALWAYS_INLINE bool ARRAY_LENGTH() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100927 ObjPtr<mirror::Object> array = GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +0100928 if (UNLIKELY(array == nullptr)) {
929 ThrowNullPointerExceptionFromInterpreter();
930 HANDLE_PENDING_EXCEPTION();
931 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100932 SetVReg(A(), array->AsArray()->GetLength());
David Srbecky6da82472018-10-23 14:03:08 +0100933 inst = inst->Next_1xx();
934 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100935 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100936 }
937
David Srbeckybd613ec2019-05-30 15:39:38 +0100938 ALWAYS_INLINE bool NEW_INSTANCE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100939 ObjPtr<mirror::Object> obj = nullptr;
David Srbeckyd6f579c2019-05-29 18:09:30 +0100940 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(B()),
David Srbecky6da82472018-10-23 14:03:08 +0100941 shadow_frame.GetMethod(),
942 self,
943 false,
944 do_access_check);
945 if (LIKELY(c != nullptr)) {
Vladimir Marko9b81ac32019-05-16 16:47:08 +0100946 gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
David Srbecky6da82472018-10-23 14:03:08 +0100947 if (UNLIKELY(c->IsStringClass())) {
Vladimir Marko9b81ac32019-05-16 16:47:08 +0100948 obj = mirror::String::AllocEmptyString(self, allocator_type);
David Srbecky6da82472018-10-23 14:03:08 +0100949 } else {
Vladimir Marko9b81ac32019-05-16 16:47:08 +0100950 obj = AllocObjectFromCode(c, self, allocator_type);
David Srbecky6da82472018-10-23 14:03:08 +0100951 }
952 }
953 if (UNLIKELY(obj == nullptr)) {
954 HANDLE_PENDING_EXCEPTION();
955 } else {
956 obj->GetClass()->AssertInitializedOrInitializingInThread(self);
957 // Don't allow finalizable objects to be allocated during a transaction since these can't
958 // be finalized without a started runtime.
959 if (transaction_active && obj->GetClass()->IsFinalizable()) {
960 AbortTransactionF(self, "Allocating finalizable object in transaction: %s",
961 obj->PrettyTypeOf().c_str());
962 HANDLE_PENDING_EXCEPTION();
963 }
David Srbecky6baf6442019-05-30 14:57:43 +0100964 SetVRegReference(A(), obj);
David Srbecky6da82472018-10-23 14:03:08 +0100965 inst = inst->Next_2xx();
966 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100967 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100968 }
969
David Srbeckybd613ec2019-05-30 15:39:38 +0100970 ALWAYS_INLINE bool NEW_ARRAY() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100971 int32_t length = GetVReg(B());
Vladimir Marko9b81ac32019-05-16 16:47:08 +0100972 ObjPtr<mirror::Object> obj = AllocArrayFromCode<do_access_check>(
David Srbeckyd6f579c2019-05-29 18:09:30 +0100973 dex::TypeIndex(C()),
David Srbecky6da82472018-10-23 14:03:08 +0100974 length,
975 shadow_frame.GetMethod(),
976 self,
977 Runtime::Current()->GetHeap()->GetCurrentAllocator());
978 if (UNLIKELY(obj == nullptr)) {
979 HANDLE_PENDING_EXCEPTION();
980 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100981 SetVRegReference(A(), obj);
David Srbecky6da82472018-10-23 14:03:08 +0100982 inst = inst->Next_2xx();
983 }
David Srbeckybd613ec2019-05-30 15:39:38 +0100984 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100985 }
986
David Srbeckybd613ec2019-05-30 15:39:38 +0100987 ALWAYS_INLINE bool FILLED_NEW_ARRAY() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100988 bool success =
989 DoFilledNewArray<false, do_access_check, transaction_active>(inst, shadow_frame, self,
990 ResultRegister());
991 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
David Srbeckybd613ec2019-05-30 15:39:38 +0100992 return true;
David Srbecky6da82472018-10-23 14:03:08 +0100993 }
994
David Srbeckybd613ec2019-05-30 15:39:38 +0100995 ALWAYS_INLINE bool FILLED_NEW_ARRAY_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100996 bool success =
997 DoFilledNewArray<true, do_access_check, transaction_active>(inst, shadow_frame,
998 self, ResultRegister());
999 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001000 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001001 }
1002
David Srbeckybd613ec2019-05-30 15:39:38 +01001003 ALWAYS_INLINE bool FILL_ARRAY_DATA() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001004 const uint16_t* payload_addr = reinterpret_cast<const uint16_t*>(inst) + B();
David Srbecky6da82472018-10-23 14:03:08 +01001005 const Instruction::ArrayDataPayload* payload =
1006 reinterpret_cast<const Instruction::ArrayDataPayload*>(payload_addr);
David Srbecky6baf6442019-05-30 14:57:43 +01001007 ObjPtr<mirror::Object> obj = GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +01001008 bool success = FillArrayData(obj, payload);
1009 if (!success) {
1010 HANDLE_PENDING_EXCEPTION();
1011 }
1012 if (transaction_active) {
1013 RecordArrayElementsInTransaction(obj->AsArray(), payload->element_count);
1014 }
1015 inst = inst->Next_3xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001016 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001017 }
1018
David Srbeckybd613ec2019-05-30 15:39:38 +01001019 ALWAYS_INLINE bool THROW() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +00001020 if (!HandleAsyncException()) {
David Srbeckybd613ec2019-05-30 15:39:38 +01001021 return false;
David Srbecky47ad3762018-10-31 12:43:40 +00001022 }
David Srbecky6baf6442019-05-30 14:57:43 +01001023 ObjPtr<mirror::Object> exception = GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +01001024 if (UNLIKELY(exception == nullptr)) {
1025 ThrowNullPointerException("throw with null exception");
1026 } else if (do_assignability_check && !exception->GetClass()->IsThrowableClass()) {
1027 // This should never happen.
1028 std::string temp;
1029 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
1030 "Throwing '%s' that is not instance of Throwable",
1031 exception->GetClass()->GetDescriptor(&temp));
1032 } else {
1033 self->SetException(exception->AsThrowable());
1034 }
1035 HANDLE_PENDING_EXCEPTION();
David Srbeckybd613ec2019-05-30 15:39:38 +01001036 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001037 }
1038
David Srbeckybd613ec2019-05-30 15:39:38 +01001039 ALWAYS_INLINE bool GOTO() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001040 return HandleGoto(A());
David Srbecky6da82472018-10-23 14:03:08 +01001041 }
1042
David Srbeckybd613ec2019-05-30 15:39:38 +01001043 ALWAYS_INLINE bool GOTO_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001044 return HandleGoto(A());
David Srbecky6da82472018-10-23 14:03:08 +01001045 }
1046
David Srbeckybd613ec2019-05-30 15:39:38 +01001047 ALWAYS_INLINE bool GOTO_32() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001048 return HandleGoto(A());
David Srbecky6da82472018-10-23 14:03:08 +01001049 }
1050
David Srbeckybd613ec2019-05-30 15:39:38 +01001051 ALWAYS_INLINE bool PACKED_SWITCH() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001052 int32_t offset = DoPackedSwitch(inst, shadow_frame, inst_data);
1053 BRANCH_INSTRUMENTATION(offset);
David Srbecky8867f3b2019-05-31 20:01:46 +01001054 SetNextInstruction(inst->RelativeAt(offset));
David Srbecky6da82472018-10-23 14:03:08 +01001055 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001056 HandleBackwardBranch(offset);
David Srbeckybd613ec2019-05-30 15:39:38 +01001057 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001058 }
1059
David Srbeckybd613ec2019-05-30 15:39:38 +01001060 ALWAYS_INLINE bool SPARSE_SWITCH() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001061 int32_t offset = DoSparseSwitch(inst, shadow_frame, inst_data);
1062 BRANCH_INSTRUMENTATION(offset);
David Srbecky8867f3b2019-05-31 20:01:46 +01001063 SetNextInstruction(inst->RelativeAt(offset));
David Srbecky6da82472018-10-23 14:03:08 +01001064 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001065 HandleBackwardBranch(offset);
David Srbeckybd613ec2019-05-30 15:39:38 +01001066 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001067 }
1068
David Srbeckybd613ec2019-05-30 15:39:38 +01001069 ALWAYS_INLINE bool CMPL_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001070 return HandleCmpl<float>(GetVRegFloat(B()), GetVRegFloat(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001071 }
1072
David Srbeckybd613ec2019-05-30 15:39:38 +01001073 ALWAYS_INLINE bool CMPG_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001074 return HandleCmpg<float>(GetVRegFloat(B()), GetVRegFloat(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001075 }
1076
David Srbeckybd613ec2019-05-30 15:39:38 +01001077 ALWAYS_INLINE bool CMPL_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001078 return HandleCmpl<double>(GetVRegDouble(B()), GetVRegDouble(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001079 }
1080
David Srbeckybd613ec2019-05-30 15:39:38 +01001081 ALWAYS_INLINE bool CMPG_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001082 return HandleCmpg<double>(GetVRegDouble(B()), GetVRegDouble(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001083 }
1084
David Srbeckybd613ec2019-05-30 15:39:38 +01001085 ALWAYS_INLINE bool CMP_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001086 return HandleCmpl<int64_t>(GetVRegLong(B()), GetVRegLong(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001087 }
1088
David Srbeckybd613ec2019-05-30 15:39:38 +01001089 ALWAYS_INLINE bool IF_EQ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001090 return HandleIf(GetVReg(A()) == GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +01001091 }
1092
David Srbeckybd613ec2019-05-30 15:39:38 +01001093 ALWAYS_INLINE bool IF_NE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001094 return HandleIf(GetVReg(A()) != GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +01001095 }
1096
David Srbeckybd613ec2019-05-30 15:39:38 +01001097 ALWAYS_INLINE bool IF_LT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001098 return HandleIf(GetVReg(A()) < GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +01001099 }
1100
David Srbeckybd613ec2019-05-30 15:39:38 +01001101 ALWAYS_INLINE bool IF_GE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001102 return HandleIf(GetVReg(A()) >= GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +01001103 }
1104
David Srbeckybd613ec2019-05-30 15:39:38 +01001105 ALWAYS_INLINE bool IF_GT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001106 return HandleIf(GetVReg(A()) > GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +01001107 }
1108
David Srbeckybd613ec2019-05-30 15:39:38 +01001109 ALWAYS_INLINE bool IF_LE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001110 return HandleIf(GetVReg(A()) <= GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +01001111 }
1112
David Srbeckybd613ec2019-05-30 15:39:38 +01001113 ALWAYS_INLINE bool IF_EQZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001114 return HandleIf(GetVReg(A()) == 0, B());
David Srbecky6da82472018-10-23 14:03:08 +01001115 }
1116
David Srbeckybd613ec2019-05-30 15:39:38 +01001117 ALWAYS_INLINE bool IF_NEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001118 return HandleIf(GetVReg(A()) != 0, B());
David Srbecky6da82472018-10-23 14:03:08 +01001119 }
1120
David Srbeckybd613ec2019-05-30 15:39:38 +01001121 ALWAYS_INLINE bool IF_LTZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001122 return HandleIf(GetVReg(A()) < 0, B());
David Srbecky6da82472018-10-23 14:03:08 +01001123 }
1124
David Srbeckybd613ec2019-05-30 15:39:38 +01001125 ALWAYS_INLINE bool IF_GEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001126 return HandleIf(GetVReg(A()) >= 0, B());
David Srbecky6da82472018-10-23 14:03:08 +01001127 }
1128
David Srbeckybd613ec2019-05-30 15:39:38 +01001129 ALWAYS_INLINE bool IF_GTZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001130 return HandleIf(GetVReg(A()) > 0, B());
David Srbecky6da82472018-10-23 14:03:08 +01001131 }
1132
David Srbeckybd613ec2019-05-30 15:39:38 +01001133 ALWAYS_INLINE bool IF_LEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001134 return HandleIf(GetVReg(A()) <= 0, B());
David Srbecky6da82472018-10-23 14:03:08 +01001135 }
1136
David Srbeckybd613ec2019-05-30 15:39:38 +01001137 ALWAYS_INLINE bool AGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001138 return HandleAGet<mirror::BooleanArray>(&InstructionHandler::SetVReg);
David Srbecky6da82472018-10-23 14:03:08 +01001139 }
1140
David Srbeckybd613ec2019-05-30 15:39:38 +01001141 ALWAYS_INLINE bool AGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001142 return HandleAGet<mirror::ByteArray>(&InstructionHandler::SetVReg);
David Srbecky6da82472018-10-23 14:03:08 +01001143 }
1144
David Srbeckybd613ec2019-05-30 15:39:38 +01001145 ALWAYS_INLINE bool AGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001146 return HandleAGet<mirror::CharArray>(&InstructionHandler::SetVReg);
David Srbecky6da82472018-10-23 14:03:08 +01001147 }
1148
David Srbeckybd613ec2019-05-30 15:39:38 +01001149 ALWAYS_INLINE bool AGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001150 return HandleAGet<mirror::ShortArray>(&InstructionHandler::SetVReg);
David Srbecky6da82472018-10-23 14:03:08 +01001151 }
1152
David Srbeckybd613ec2019-05-30 15:39:38 +01001153 ALWAYS_INLINE bool AGET() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001154 return HandleAGet<mirror::IntArray>(&InstructionHandler::SetVReg);
David Srbecky6da82472018-10-23 14:03:08 +01001155 }
1156
David Srbeckybd613ec2019-05-30 15:39:38 +01001157 ALWAYS_INLINE bool AGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001158 return HandleAGet<mirror::LongArray>(&InstructionHandler::SetVRegLong);
David Srbecky6da82472018-10-23 14:03:08 +01001159 }
1160
David Srbeckybd613ec2019-05-30 15:39:38 +01001161 ALWAYS_INLINE bool AGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001162 return HandleAGet<mirror::ObjectArray<mirror::Object>>(&InstructionHandler::SetVRegReference);
David Srbecky6da82472018-10-23 14:03:08 +01001163 }
1164
David Srbeckybd613ec2019-05-30 15:39:38 +01001165 ALWAYS_INLINE bool APUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001166 return HandleAPut<mirror::BooleanArray>(GetVReg(A()));
David Srbecky6da82472018-10-23 14:03:08 +01001167 }
1168
David Srbeckybd613ec2019-05-30 15:39:38 +01001169 ALWAYS_INLINE bool APUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001170 return HandleAPut<mirror::ByteArray>(GetVReg(A()));
David Srbecky6da82472018-10-23 14:03:08 +01001171 }
1172
David Srbeckybd613ec2019-05-30 15:39:38 +01001173 ALWAYS_INLINE bool APUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001174 return HandleAPut<mirror::CharArray>(GetVReg(A()));
David Srbecky6da82472018-10-23 14:03:08 +01001175 }
1176
David Srbeckybd613ec2019-05-30 15:39:38 +01001177 ALWAYS_INLINE bool APUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001178 return HandleAPut<mirror::ShortArray>(GetVReg(A()));
David Srbecky6da82472018-10-23 14:03:08 +01001179 }
1180
David Srbeckybd613ec2019-05-30 15:39:38 +01001181 ALWAYS_INLINE bool APUT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001182 return HandleAPut<mirror::IntArray>(GetVReg(A()));
David Srbecky6da82472018-10-23 14:03:08 +01001183 }
1184
David Srbeckybd613ec2019-05-30 15:39:38 +01001185 ALWAYS_INLINE bool APUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky1332c262019-06-04 13:13:37 +01001186 return HandleAPut<mirror::LongArray>(GetVRegLong(A()));
David Srbecky6da82472018-10-23 14:03:08 +01001187 }
1188
David Srbeckybd613ec2019-05-30 15:39:38 +01001189 ALWAYS_INLINE bool APUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001190 ObjPtr<mirror::Object> a = GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001191 if (UNLIKELY(a == nullptr)) {
1192 ThrowNullPointerExceptionFromInterpreter();
1193 HANDLE_PENDING_EXCEPTION();
1194 }
David Srbecky6baf6442019-05-30 14:57:43 +01001195 int32_t index = GetVReg(C());
1196 ObjPtr<mirror::Object> val = GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +01001197 ObjPtr<mirror::ObjectArray<mirror::Object>> array = a->AsObjectArray<mirror::Object>();
1198 if (array->CheckIsValidIndex(index) && array->CheckAssignable(val)) {
1199 array->SetWithoutChecks<transaction_active>(index, val);
1200 inst = inst->Next_2xx();
1201 } else {
1202 HANDLE_PENDING_EXCEPTION();
1203 }
David Srbeckybd613ec2019-05-30 15:39:38 +01001204 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001205 }
1206
David Srbeckybd613ec2019-05-30 15:39:38 +01001207 ALWAYS_INLINE bool IGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001208 return HandleGet<InstancePrimitiveRead, Primitive::kPrimBoolean>();
David Srbecky6da82472018-10-23 14:03:08 +01001209 }
1210
David Srbeckybd613ec2019-05-30 15:39:38 +01001211 ALWAYS_INLINE bool IGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001212 return HandleGet<InstancePrimitiveRead, Primitive::kPrimByte>();
David Srbecky6da82472018-10-23 14:03:08 +01001213 }
1214
David Srbeckybd613ec2019-05-30 15:39:38 +01001215 ALWAYS_INLINE bool IGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001216 return HandleGet<InstancePrimitiveRead, Primitive::kPrimChar>();
David Srbecky6da82472018-10-23 14:03:08 +01001217 }
1218
David Srbeckybd613ec2019-05-30 15:39:38 +01001219 ALWAYS_INLINE bool IGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001220 return HandleGet<InstancePrimitiveRead, Primitive::kPrimShort>();
David Srbecky6da82472018-10-23 14:03:08 +01001221 }
1222
David Srbeckybd613ec2019-05-30 15:39:38 +01001223 ALWAYS_INLINE bool IGET() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001224 return HandleGet<InstancePrimitiveRead, Primitive::kPrimInt>();
David Srbecky6da82472018-10-23 14:03:08 +01001225 }
1226
David Srbeckybd613ec2019-05-30 15:39:38 +01001227 ALWAYS_INLINE bool IGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001228 return HandleGet<InstancePrimitiveRead, Primitive::kPrimLong>();
David Srbecky6da82472018-10-23 14:03:08 +01001229 }
1230
David Srbeckybd613ec2019-05-30 15:39:38 +01001231 ALWAYS_INLINE bool IGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001232 return HandleGet<InstanceObjectRead, Primitive::kPrimNot>();
David Srbecky6da82472018-10-23 14:03:08 +01001233 }
1234
David Srbeckybd613ec2019-05-30 15:39:38 +01001235 ALWAYS_INLINE bool IGET_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001236 return HandleGetQuick<Primitive::kPrimInt>();
David Srbecky6da82472018-10-23 14:03:08 +01001237 }
1238
David Srbeckybd613ec2019-05-30 15:39:38 +01001239 ALWAYS_INLINE bool IGET_WIDE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001240 return HandleGetQuick<Primitive::kPrimLong>();
David Srbecky6da82472018-10-23 14:03:08 +01001241 }
1242
David Srbeckybd613ec2019-05-30 15:39:38 +01001243 ALWAYS_INLINE bool IGET_OBJECT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001244 return HandleGetQuick<Primitive::kPrimNot>();
David Srbecky6da82472018-10-23 14:03:08 +01001245 }
1246
David Srbeckybd613ec2019-05-30 15:39:38 +01001247 ALWAYS_INLINE bool IGET_BOOLEAN_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001248 return HandleGetQuick<Primitive::kPrimBoolean>();
David Srbecky6da82472018-10-23 14:03:08 +01001249 }
1250
David Srbeckybd613ec2019-05-30 15:39:38 +01001251 ALWAYS_INLINE bool IGET_BYTE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001252 return HandleGetQuick<Primitive::kPrimByte>();
David Srbecky6da82472018-10-23 14:03:08 +01001253 }
1254
David Srbeckybd613ec2019-05-30 15:39:38 +01001255 ALWAYS_INLINE bool IGET_CHAR_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001256 return HandleGetQuick<Primitive::kPrimChar>();
David Srbecky6da82472018-10-23 14:03:08 +01001257 }
1258
David Srbeckybd613ec2019-05-30 15:39:38 +01001259 ALWAYS_INLINE bool IGET_SHORT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001260 return HandleGetQuick<Primitive::kPrimShort>();
David Srbecky6da82472018-10-23 14:03:08 +01001261 }
1262
David Srbeckybd613ec2019-05-30 15:39:38 +01001263 ALWAYS_INLINE bool SGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001264 return HandleGet<StaticPrimitiveRead, Primitive::kPrimBoolean>();
David Srbecky6da82472018-10-23 14:03:08 +01001265 }
1266
David Srbeckybd613ec2019-05-30 15:39:38 +01001267 ALWAYS_INLINE bool SGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001268 return HandleGet<StaticPrimitiveRead, Primitive::kPrimByte>();
David Srbecky6da82472018-10-23 14:03:08 +01001269 }
1270
David Srbeckybd613ec2019-05-30 15:39:38 +01001271 ALWAYS_INLINE bool SGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001272 return HandleGet<StaticPrimitiveRead, Primitive::kPrimChar>();
David Srbecky6da82472018-10-23 14:03:08 +01001273 }
1274
David Srbeckybd613ec2019-05-30 15:39:38 +01001275 ALWAYS_INLINE bool SGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001276 return HandleGet<StaticPrimitiveRead, Primitive::kPrimShort>();
David Srbecky6da82472018-10-23 14:03:08 +01001277 }
1278
David Srbeckybd613ec2019-05-30 15:39:38 +01001279 ALWAYS_INLINE bool SGET() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001280 return HandleGet<StaticPrimitiveRead, Primitive::kPrimInt>();
David Srbecky6da82472018-10-23 14:03:08 +01001281 }
1282
David Srbeckybd613ec2019-05-30 15:39:38 +01001283 ALWAYS_INLINE bool SGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001284 return HandleGet<StaticPrimitiveRead, Primitive::kPrimLong>();
David Srbecky6da82472018-10-23 14:03:08 +01001285 }
1286
David Srbeckybd613ec2019-05-30 15:39:38 +01001287 ALWAYS_INLINE bool SGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001288 return HandleGet<StaticObjectRead, Primitive::kPrimNot>();
David Srbecky6da82472018-10-23 14:03:08 +01001289 }
1290
David Srbeckybd613ec2019-05-30 15:39:38 +01001291 ALWAYS_INLINE bool IPUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001292 return HandlePut<InstancePrimitiveWrite, Primitive::kPrimBoolean>();
David Srbecky6da82472018-10-23 14:03:08 +01001293 }
1294
David Srbeckybd613ec2019-05-30 15:39:38 +01001295 ALWAYS_INLINE bool IPUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001296 return HandlePut<InstancePrimitiveWrite, Primitive::kPrimByte>();
David Srbecky6da82472018-10-23 14:03:08 +01001297 }
1298
David Srbeckybd613ec2019-05-30 15:39:38 +01001299 ALWAYS_INLINE bool IPUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001300 return HandlePut<InstancePrimitiveWrite, Primitive::kPrimChar>();
David Srbecky6da82472018-10-23 14:03:08 +01001301 }
1302
David Srbeckybd613ec2019-05-30 15:39:38 +01001303 ALWAYS_INLINE bool IPUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001304 return HandlePut<InstancePrimitiveWrite, Primitive::kPrimShort>();
David Srbecky6da82472018-10-23 14:03:08 +01001305 }
1306
David Srbeckybd613ec2019-05-30 15:39:38 +01001307 ALWAYS_INLINE bool IPUT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001308 return HandlePut<InstancePrimitiveWrite, Primitive::kPrimInt>();
David Srbecky6da82472018-10-23 14:03:08 +01001309 }
1310
David Srbeckybd613ec2019-05-30 15:39:38 +01001311 ALWAYS_INLINE bool IPUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001312 return HandlePut<InstancePrimitiveWrite, Primitive::kPrimLong>();
David Srbecky6da82472018-10-23 14:03:08 +01001313 }
1314
David Srbeckybd613ec2019-05-30 15:39:38 +01001315 ALWAYS_INLINE bool IPUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001316 return HandlePut<InstanceObjectWrite, Primitive::kPrimNot>();
David Srbecky6da82472018-10-23 14:03:08 +01001317 }
1318
David Srbeckybd613ec2019-05-30 15:39:38 +01001319 ALWAYS_INLINE bool IPUT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001320 return HandlePutQuick<Primitive::kPrimInt>();
David Srbecky6da82472018-10-23 14:03:08 +01001321 }
1322
David Srbeckybd613ec2019-05-30 15:39:38 +01001323 ALWAYS_INLINE bool IPUT_BOOLEAN_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001324 return HandlePutQuick<Primitive::kPrimBoolean>();
David Srbecky6da82472018-10-23 14:03:08 +01001325 }
1326
David Srbeckybd613ec2019-05-30 15:39:38 +01001327 ALWAYS_INLINE bool IPUT_BYTE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001328 return HandlePutQuick<Primitive::kPrimByte>();
David Srbecky6da82472018-10-23 14:03:08 +01001329 }
1330
David Srbeckybd613ec2019-05-30 15:39:38 +01001331 ALWAYS_INLINE bool IPUT_CHAR_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001332 return HandlePutQuick<Primitive::kPrimChar>();
David Srbecky6da82472018-10-23 14:03:08 +01001333 }
1334
David Srbeckybd613ec2019-05-30 15:39:38 +01001335 ALWAYS_INLINE bool IPUT_SHORT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001336 return HandlePutQuick<Primitive::kPrimShort>();
David Srbecky6da82472018-10-23 14:03:08 +01001337 }
1338
David Srbeckybd613ec2019-05-30 15:39:38 +01001339 ALWAYS_INLINE bool IPUT_WIDE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001340 return HandlePutQuick<Primitive::kPrimLong>();
David Srbecky6da82472018-10-23 14:03:08 +01001341 }
1342
David Srbeckybd613ec2019-05-30 15:39:38 +01001343 ALWAYS_INLINE bool IPUT_OBJECT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001344 return HandlePutQuick<Primitive::kPrimNot>();
David Srbecky6da82472018-10-23 14:03:08 +01001345 }
1346
David Srbeckybd613ec2019-05-30 15:39:38 +01001347 ALWAYS_INLINE bool SPUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001348 return HandlePut<StaticPrimitiveWrite, Primitive::kPrimBoolean>();
David Srbecky6da82472018-10-23 14:03:08 +01001349 }
1350
David Srbeckybd613ec2019-05-30 15:39:38 +01001351 ALWAYS_INLINE bool SPUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001352 return HandlePut<StaticPrimitiveWrite, Primitive::kPrimByte>();
David Srbecky6da82472018-10-23 14:03:08 +01001353 }
1354
David Srbeckybd613ec2019-05-30 15:39:38 +01001355 ALWAYS_INLINE bool SPUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001356 return HandlePut<StaticPrimitiveWrite, Primitive::kPrimChar>();
David Srbecky6da82472018-10-23 14:03:08 +01001357 }
1358
David Srbeckybd613ec2019-05-30 15:39:38 +01001359 ALWAYS_INLINE bool SPUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001360 return HandlePut<StaticPrimitiveWrite, Primitive::kPrimShort>();
David Srbecky6da82472018-10-23 14:03:08 +01001361 }
1362
David Srbeckybd613ec2019-05-30 15:39:38 +01001363 ALWAYS_INLINE bool SPUT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001364 return HandlePut<StaticPrimitiveWrite, Primitive::kPrimInt>();
David Srbecky6da82472018-10-23 14:03:08 +01001365 }
1366
David Srbeckybd613ec2019-05-30 15:39:38 +01001367 ALWAYS_INLINE bool SPUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001368 return HandlePut<StaticPrimitiveWrite, Primitive::kPrimLong>();
David Srbecky6da82472018-10-23 14:03:08 +01001369 }
1370
David Srbeckybd613ec2019-05-30 15:39:38 +01001371 ALWAYS_INLINE bool SPUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001372 return HandlePut<StaticObjectWrite, Primitive::kPrimNot>();
David Srbecky6da82472018-10-23 14:03:08 +01001373 }
1374
David Srbeckybd613ec2019-05-30 15:39:38 +01001375 ALWAYS_INLINE bool INVOKE_VIRTUAL() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001376 return HandleInvoke<kVirtual, /*is_range=*/ false>();
David Srbecky6da82472018-10-23 14:03:08 +01001377 }
1378
David Srbeckybd613ec2019-05-30 15:39:38 +01001379 ALWAYS_INLINE bool INVOKE_VIRTUAL_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001380 return HandleInvoke<kVirtual, /*is_range=*/ true>();
David Srbecky6da82472018-10-23 14:03:08 +01001381 }
1382
David Srbeckybd613ec2019-05-30 15:39:38 +01001383 ALWAYS_INLINE bool INVOKE_SUPER() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001384 return HandleInvoke<kSuper, /*is_range=*/ false>();
David Srbecky6da82472018-10-23 14:03:08 +01001385 }
1386
David Srbeckybd613ec2019-05-30 15:39:38 +01001387 ALWAYS_INLINE bool INVOKE_SUPER_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001388 return HandleInvoke<kSuper, /*is_range=*/ true>();
David Srbecky6da82472018-10-23 14:03:08 +01001389 }
1390
David Srbeckybd613ec2019-05-30 15:39:38 +01001391 ALWAYS_INLINE bool INVOKE_DIRECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001392 return HandleInvoke<kDirect, /*is_range=*/ false>();
David Srbecky6da82472018-10-23 14:03:08 +01001393 }
1394
David Srbeckybd613ec2019-05-30 15:39:38 +01001395 ALWAYS_INLINE bool INVOKE_DIRECT_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001396 return HandleInvoke<kDirect, /*is_range=*/ true>();
David Srbecky6da82472018-10-23 14:03:08 +01001397 }
1398
David Srbeckybd613ec2019-05-30 15:39:38 +01001399 ALWAYS_INLINE bool INVOKE_INTERFACE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001400 return HandleInvoke<kInterface, /*is_range=*/ false>();
David Srbecky6da82472018-10-23 14:03:08 +01001401 }
1402
David Srbeckybd613ec2019-05-30 15:39:38 +01001403 ALWAYS_INLINE bool INVOKE_INTERFACE_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001404 return HandleInvoke<kInterface, /*is_range=*/ true>();
David Srbecky6da82472018-10-23 14:03:08 +01001405 }
1406
David Srbeckybd613ec2019-05-30 15:39:38 +01001407 ALWAYS_INLINE bool INVOKE_STATIC() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001408 return HandleInvoke<kStatic, /*is_range=*/ false>();
David Srbecky6da82472018-10-23 14:03:08 +01001409 }
1410
David Srbeckybd613ec2019-05-30 15:39:38 +01001411 ALWAYS_INLINE bool INVOKE_STATIC_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001412 return HandleInvoke<kStatic, /*is_range=*/ true>();
David Srbecky6da82472018-10-23 14:03:08 +01001413 }
1414
David Srbeckybd613ec2019-05-30 15:39:38 +01001415 ALWAYS_INLINE bool INVOKE_VIRTUAL_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001416 return HandleInvoke<kVirtual, /*is_range=*/ false, /*is_quick=*/ true>();
David Srbecky6da82472018-10-23 14:03:08 +01001417 }
1418
David Srbeckybd613ec2019-05-30 15:39:38 +01001419 ALWAYS_INLINE bool INVOKE_VIRTUAL_RANGE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01001420 return HandleInvoke<kVirtual, /*is_range=*/ true, /*is_quick=*/ true>();
David Srbecky6da82472018-10-23 14:03:08 +01001421 }
1422
David Srbeckybd613ec2019-05-30 15:39:38 +01001423 ALWAYS_INLINE bool INVOKE_POLYMORPHIC() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001424 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1425 bool success = DoInvokePolymorphic</* is_range= */ false>(
1426 self, shadow_frame, inst, inst_data, ResultRegister());
1427 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(!success);
David Srbeckybd613ec2019-05-30 15:39:38 +01001428 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001429 }
1430
David Srbeckybd613ec2019-05-30 15:39:38 +01001431 ALWAYS_INLINE bool INVOKE_POLYMORPHIC_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001432 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1433 bool success = DoInvokePolymorphic</* is_range= */ true>(
1434 self, shadow_frame, inst, inst_data, ResultRegister());
1435 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(!success);
David Srbeckybd613ec2019-05-30 15:39:38 +01001436 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001437 }
1438
David Srbeckybd613ec2019-05-30 15:39:38 +01001439 ALWAYS_INLINE bool INVOKE_CUSTOM() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001440 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1441 bool success = DoInvokeCustom</* is_range= */ false>(
1442 self, shadow_frame, inst, inst_data, ResultRegister());
1443 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
David Srbeckybd613ec2019-05-30 15:39:38 +01001444 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001445 }
1446
David Srbeckybd613ec2019-05-30 15:39:38 +01001447 ALWAYS_INLINE bool INVOKE_CUSTOM_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001448 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1449 bool success = DoInvokeCustom</* is_range= */ true>(
1450 self, shadow_frame, inst, inst_data, ResultRegister());
1451 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
David Srbeckybd613ec2019-05-30 15:39:38 +01001452 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001453 }
1454
David Srbeckybd613ec2019-05-30 15:39:38 +01001455 ALWAYS_INLINE bool NEG_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001456 SetVReg(A(), -GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001457 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001458 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001459 }
1460
David Srbeckybd613ec2019-05-30 15:39:38 +01001461 ALWAYS_INLINE bool NOT_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001462 SetVReg(A(), ~GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001463 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001464 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001465 }
1466
David Srbeckybd613ec2019-05-30 15:39:38 +01001467 ALWAYS_INLINE bool NEG_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001468 SetVRegLong(A(), -GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001469 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001470 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001471 }
1472
David Srbeckybd613ec2019-05-30 15:39:38 +01001473 ALWAYS_INLINE bool NOT_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001474 SetVRegLong(A(), ~GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001475 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001476 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001477 }
1478
David Srbeckybd613ec2019-05-30 15:39:38 +01001479 ALWAYS_INLINE bool NEG_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001480 SetVRegFloat(A(), -GetVRegFloat(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001481 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001482 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001483 }
1484
David Srbeckybd613ec2019-05-30 15:39:38 +01001485 ALWAYS_INLINE bool NEG_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001486 SetVRegDouble(A(), -GetVRegDouble(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001487 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001488 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001489 }
1490
David Srbeckybd613ec2019-05-30 15:39:38 +01001491 ALWAYS_INLINE bool INT_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001492 SetVRegLong(A(), GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001493 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001494 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001495 }
1496
David Srbeckybd613ec2019-05-30 15:39:38 +01001497 ALWAYS_INLINE bool INT_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001498 SetVRegFloat(A(), GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001499 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001500 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001501 }
1502
David Srbeckybd613ec2019-05-30 15:39:38 +01001503 ALWAYS_INLINE bool INT_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001504 SetVRegDouble(A(), GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001505 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001506 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001507 }
1508
David Srbeckybd613ec2019-05-30 15:39:38 +01001509 ALWAYS_INLINE bool LONG_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001510 SetVReg(A(), GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001511 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001512 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001513 }
1514
David Srbeckybd613ec2019-05-30 15:39:38 +01001515 ALWAYS_INLINE bool LONG_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001516 SetVRegFloat(A(), GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001517 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001518 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001519 }
1520
David Srbeckybd613ec2019-05-30 15:39:38 +01001521 ALWAYS_INLINE bool LONG_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001522 SetVRegDouble(A(), GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001523 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001524 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001525 }
1526
David Srbeckybd613ec2019-05-30 15:39:38 +01001527 ALWAYS_INLINE bool FLOAT_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001528 float val = GetVRegFloat(B());
David Srbecky6da82472018-10-23 14:03:08 +01001529 int32_t result = art_float_to_integral<int32_t, float>(val);
David Srbecky6baf6442019-05-30 14:57:43 +01001530 SetVReg(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +01001531 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001532 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001533 }
1534
David Srbeckybd613ec2019-05-30 15:39:38 +01001535 ALWAYS_INLINE bool FLOAT_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001536 float val = GetVRegFloat(B());
David Srbecky6da82472018-10-23 14:03:08 +01001537 int64_t result = art_float_to_integral<int64_t, float>(val);
David Srbecky6baf6442019-05-30 14:57:43 +01001538 SetVRegLong(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +01001539 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001540 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001541 }
1542
David Srbeckybd613ec2019-05-30 15:39:38 +01001543 ALWAYS_INLINE bool FLOAT_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001544 SetVRegDouble(A(), GetVRegFloat(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001545 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001546 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001547 }
1548
David Srbeckybd613ec2019-05-30 15:39:38 +01001549 ALWAYS_INLINE bool DOUBLE_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001550 double val = GetVRegDouble(B());
David Srbecky6da82472018-10-23 14:03:08 +01001551 int32_t result = art_float_to_integral<int32_t, double>(val);
David Srbecky6baf6442019-05-30 14:57:43 +01001552 SetVReg(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +01001553 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001554 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001555 }
1556
David Srbeckybd613ec2019-05-30 15:39:38 +01001557 ALWAYS_INLINE bool DOUBLE_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001558 double val = GetVRegDouble(B());
David Srbecky6da82472018-10-23 14:03:08 +01001559 int64_t result = art_float_to_integral<int64_t, double>(val);
David Srbecky6baf6442019-05-30 14:57:43 +01001560 SetVRegLong(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +01001561 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001562 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001563 }
1564
David Srbeckybd613ec2019-05-30 15:39:38 +01001565 ALWAYS_INLINE bool DOUBLE_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001566 SetVRegFloat(A(), GetVRegDouble(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001567 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001568 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001569 }
1570
David Srbeckybd613ec2019-05-30 15:39:38 +01001571 ALWAYS_INLINE bool INT_TO_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001572 SetVReg(A(), static_cast<int8_t>(GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01001573 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001574 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001575 }
1576
David Srbeckybd613ec2019-05-30 15:39:38 +01001577 ALWAYS_INLINE bool INT_TO_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001578 SetVReg(A(), static_cast<uint16_t>(GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01001579 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001580 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001581 }
1582
David Srbeckybd613ec2019-05-30 15:39:38 +01001583 ALWAYS_INLINE bool INT_TO_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001584 SetVReg(A(), static_cast<int16_t>(GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01001585 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001586 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001587 }
1588
David Srbeckybd613ec2019-05-30 15:39:38 +01001589 ALWAYS_INLINE bool ADD_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001590 SetVReg(A(), SafeAdd(GetVReg(B()), GetVReg(C())));
David Srbecky6da82472018-10-23 14:03:08 +01001591 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001592 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001593 }
1594
David Srbeckybd613ec2019-05-30 15:39:38 +01001595 ALWAYS_INLINE bool SUB_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001596 SetVReg(A(), SafeSub(GetVReg(B()), GetVReg(C())));
David Srbecky6da82472018-10-23 14:03:08 +01001597 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001598 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001599 }
1600
David Srbeckybd613ec2019-05-30 15:39:38 +01001601 ALWAYS_INLINE bool MUL_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001602 SetVReg(A(), SafeMul(GetVReg(B()), GetVReg(C())));
David Srbecky6da82472018-10-23 14:03:08 +01001603 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001604 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001605 }
1606
David Srbeckybd613ec2019-05-30 15:39:38 +01001607 ALWAYS_INLINE bool DIV_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001608 bool success = DoIntDivide(shadow_frame, A(), GetVReg(B()), GetVReg(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001609 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001610 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001611 }
1612
David Srbeckybd613ec2019-05-30 15:39:38 +01001613 ALWAYS_INLINE bool REM_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001614 bool success = DoIntRemainder(shadow_frame, A(), GetVReg(B()), GetVReg(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001615 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001616 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001617 }
1618
David Srbeckybd613ec2019-05-30 15:39:38 +01001619 ALWAYS_INLINE bool SHL_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001620 SetVReg(A(), GetVReg(B()) << (GetVReg(C()) & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01001621 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001622 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001623 }
1624
David Srbeckybd613ec2019-05-30 15:39:38 +01001625 ALWAYS_INLINE bool SHR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001626 SetVReg(A(), GetVReg(B()) >> (GetVReg(C()) & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01001627 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001628 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001629 }
1630
David Srbeckybd613ec2019-05-30 15:39:38 +01001631 ALWAYS_INLINE bool USHR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001632 SetVReg(A(), static_cast<uint32_t>(GetVReg(B())) >> (GetVReg(C()) & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01001633 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001634 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001635 }
1636
David Srbeckybd613ec2019-05-30 15:39:38 +01001637 ALWAYS_INLINE bool AND_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001638 SetVReg(A(), GetVReg(B()) & GetVReg(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001639 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001640 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001641 }
1642
David Srbeckybd613ec2019-05-30 15:39:38 +01001643 ALWAYS_INLINE bool OR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001644 SetVReg(A(), GetVReg(B()) | GetVReg(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001645 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001646 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001647 }
1648
David Srbeckybd613ec2019-05-30 15:39:38 +01001649 ALWAYS_INLINE bool XOR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001650 SetVReg(A(), GetVReg(B()) ^ GetVReg(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001651 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001652 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001653 }
1654
David Srbeckybd613ec2019-05-30 15:39:38 +01001655 ALWAYS_INLINE bool ADD_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001656 SetVRegLong(A(), SafeAdd(GetVRegLong(B()), GetVRegLong(C())));
David Srbecky6da82472018-10-23 14:03:08 +01001657 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001658 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001659 }
1660
David Srbeckybd613ec2019-05-30 15:39:38 +01001661 ALWAYS_INLINE bool SUB_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001662 SetVRegLong(A(), SafeSub(GetVRegLong(B()), GetVRegLong(C())));
David Srbecky6da82472018-10-23 14:03:08 +01001663 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001664 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001665 }
1666
David Srbeckybd613ec2019-05-30 15:39:38 +01001667 ALWAYS_INLINE bool MUL_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001668 SetVRegLong(A(), SafeMul(GetVRegLong(B()), GetVRegLong(C())));
David Srbecky6da82472018-10-23 14:03:08 +01001669 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001670 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001671 }
1672
David Srbeckybd613ec2019-05-30 15:39:38 +01001673 ALWAYS_INLINE bool DIV_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001674 DoLongDivide(shadow_frame, A(), GetVRegLong(B()), GetVRegLong(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001675 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_2xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001676 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001677 }
1678
David Srbeckybd613ec2019-05-30 15:39:38 +01001679 ALWAYS_INLINE bool REM_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001680 DoLongRemainder(shadow_frame, A(), GetVRegLong(B()), GetVRegLong(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001681 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_2xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001682 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001683 }
1684
David Srbeckybd613ec2019-05-30 15:39:38 +01001685 ALWAYS_INLINE bool AND_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001686 SetVRegLong(A(), GetVRegLong(B()) & GetVRegLong(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001687 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001688 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001689 }
1690
David Srbeckybd613ec2019-05-30 15:39:38 +01001691 ALWAYS_INLINE bool OR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001692 SetVRegLong(A(), GetVRegLong(B()) | GetVRegLong(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001693 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001694 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001695 }
1696
David Srbeckybd613ec2019-05-30 15:39:38 +01001697 ALWAYS_INLINE bool XOR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001698 SetVRegLong(A(), GetVRegLong(B()) ^ GetVRegLong(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001699 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001700 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001701 }
1702
David Srbeckybd613ec2019-05-30 15:39:38 +01001703 ALWAYS_INLINE bool SHL_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001704 SetVRegLong(A(), GetVRegLong(B()) << (GetVReg(C()) & 0x3f));
David Srbecky6da82472018-10-23 14:03:08 +01001705 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001706 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001707 }
1708
David Srbeckybd613ec2019-05-30 15:39:38 +01001709 ALWAYS_INLINE bool SHR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001710 SetVRegLong(A(), GetVRegLong(B()) >> (GetVReg(C()) & 0x3f));
David Srbecky6da82472018-10-23 14:03:08 +01001711 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001712 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001713 }
1714
David Srbeckybd613ec2019-05-30 15:39:38 +01001715 ALWAYS_INLINE bool USHR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001716 SetVRegLong(A(), static_cast<uint64_t>(GetVRegLong(B())) >> (GetVReg(C()) & 0x3f));
David Srbecky6da82472018-10-23 14:03:08 +01001717 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001718 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001719 }
1720
David Srbeckybd613ec2019-05-30 15:39:38 +01001721 ALWAYS_INLINE bool ADD_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001722 SetVRegFloat(A(), GetVRegFloat(B()) + GetVRegFloat(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001723 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001724 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001725 }
1726
David Srbeckybd613ec2019-05-30 15:39:38 +01001727 ALWAYS_INLINE bool SUB_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001728 SetVRegFloat(A(), GetVRegFloat(B()) - GetVRegFloat(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001729 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001730 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001731 }
1732
David Srbeckybd613ec2019-05-30 15:39:38 +01001733 ALWAYS_INLINE bool MUL_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001734 SetVRegFloat(A(), GetVRegFloat(B()) * GetVRegFloat(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001735 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001736 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001737 }
1738
David Srbeckybd613ec2019-05-30 15:39:38 +01001739 ALWAYS_INLINE bool DIV_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001740 SetVRegFloat(A(), GetVRegFloat(B()) / GetVRegFloat(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001741 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001742 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001743 }
1744
David Srbeckybd613ec2019-05-30 15:39:38 +01001745 ALWAYS_INLINE bool REM_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001746 SetVRegFloat(A(), fmodf(GetVRegFloat(B()), GetVRegFloat(C())));
David Srbecky6da82472018-10-23 14:03:08 +01001747 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001748 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001749 }
1750
David Srbeckybd613ec2019-05-30 15:39:38 +01001751 ALWAYS_INLINE bool ADD_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001752 SetVRegDouble(A(), GetVRegDouble(B()) + GetVRegDouble(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001753 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001754 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001755 }
1756
David Srbeckybd613ec2019-05-30 15:39:38 +01001757 ALWAYS_INLINE bool SUB_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001758 SetVRegDouble(A(), GetVRegDouble(B()) - GetVRegDouble(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001759 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001760 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001761 }
1762
David Srbeckybd613ec2019-05-30 15:39:38 +01001763 ALWAYS_INLINE bool MUL_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001764 SetVRegDouble(A(), GetVRegDouble(B()) * GetVRegDouble(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001765 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001766 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001767 }
1768
David Srbeckybd613ec2019-05-30 15:39:38 +01001769 ALWAYS_INLINE bool DIV_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001770 SetVRegDouble(A(), GetVRegDouble(B()) / GetVRegDouble(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001771 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001772 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001773 }
1774
David Srbeckybd613ec2019-05-30 15:39:38 +01001775 ALWAYS_INLINE bool REM_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001776 SetVRegDouble(A(), fmod(GetVRegDouble(B()), GetVRegDouble(C())));
David Srbecky6da82472018-10-23 14:03:08 +01001777 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001778 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001779 }
1780
David Srbeckybd613ec2019-05-30 15:39:38 +01001781 ALWAYS_INLINE bool ADD_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001782 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001783 SetVReg(vregA, SafeAdd(GetVReg(vregA), GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01001784 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001785 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001786 }
1787
David Srbeckybd613ec2019-05-30 15:39:38 +01001788 ALWAYS_INLINE bool SUB_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001789 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001790 SetVReg(vregA, SafeSub(GetVReg(vregA), GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01001791 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001792 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001793 }
1794
David Srbeckybd613ec2019-05-30 15:39:38 +01001795 ALWAYS_INLINE bool MUL_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001796 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001797 SetVReg(vregA, SafeMul(GetVReg(vregA), GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01001798 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001799 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001800 }
1801
David Srbeckybd613ec2019-05-30 15:39:38 +01001802 ALWAYS_INLINE bool DIV_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001803 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001804 bool success = DoIntDivide(shadow_frame, vregA, GetVReg(vregA), GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001805 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_1xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001806 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001807 }
1808
David Srbeckybd613ec2019-05-30 15:39:38 +01001809 ALWAYS_INLINE bool REM_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001810 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001811 bool success = DoIntRemainder(shadow_frame, vregA, GetVReg(vregA), GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001812 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_1xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001813 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001814 }
1815
David Srbeckybd613ec2019-05-30 15:39:38 +01001816 ALWAYS_INLINE bool SHL_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001817 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001818 SetVReg(vregA, GetVReg(vregA) << (GetVReg(B()) & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01001819 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001820 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001821 }
1822
David Srbeckybd613ec2019-05-30 15:39:38 +01001823 ALWAYS_INLINE bool SHR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001824 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001825 SetVReg(vregA, GetVReg(vregA) >> (GetVReg(B()) & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01001826 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001827 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001828 }
1829
David Srbeckybd613ec2019-05-30 15:39:38 +01001830 ALWAYS_INLINE bool USHR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001831 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001832 SetVReg(vregA, static_cast<uint32_t>(GetVReg(vregA)) >> (GetVReg(B()) & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01001833 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001834 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001835 }
1836
David Srbeckybd613ec2019-05-30 15:39:38 +01001837 ALWAYS_INLINE bool AND_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001838 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001839 SetVReg(vregA, GetVReg(vregA) & GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001840 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001841 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001842 }
1843
David Srbeckybd613ec2019-05-30 15:39:38 +01001844 ALWAYS_INLINE bool OR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001845 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001846 SetVReg(vregA, GetVReg(vregA) | GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001847 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001848 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001849 }
1850
David Srbeckybd613ec2019-05-30 15:39:38 +01001851 ALWAYS_INLINE bool XOR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001852 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001853 SetVReg(vregA, GetVReg(vregA) ^ GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001854 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001855 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001856 }
1857
David Srbeckybd613ec2019-05-30 15:39:38 +01001858 ALWAYS_INLINE bool ADD_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001859 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001860 SetVRegLong(vregA, SafeAdd(GetVRegLong(vregA), GetVRegLong(B())));
David Srbecky6da82472018-10-23 14:03:08 +01001861 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001862 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001863 }
1864
David Srbeckybd613ec2019-05-30 15:39:38 +01001865 ALWAYS_INLINE bool SUB_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001866 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001867 SetVRegLong(vregA, SafeSub(GetVRegLong(vregA), GetVRegLong(B())));
David Srbecky6da82472018-10-23 14:03:08 +01001868 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001869 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001870 }
1871
David Srbeckybd613ec2019-05-30 15:39:38 +01001872 ALWAYS_INLINE bool MUL_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001873 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001874 SetVRegLong(vregA, SafeMul(GetVRegLong(vregA), GetVRegLong(B())));
David Srbecky6da82472018-10-23 14:03:08 +01001875 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001876 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001877 }
1878
David Srbeckybd613ec2019-05-30 15:39:38 +01001879 ALWAYS_INLINE bool DIV_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001880 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001881 DoLongDivide(shadow_frame, vregA, GetVRegLong(vregA), GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001882 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001883 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001884 }
1885
David Srbeckybd613ec2019-05-30 15:39:38 +01001886 ALWAYS_INLINE bool REM_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001887 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001888 DoLongRemainder(shadow_frame, vregA, GetVRegLong(vregA), GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001889 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01001890 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001891 }
1892
David Srbeckybd613ec2019-05-30 15:39:38 +01001893 ALWAYS_INLINE bool AND_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001894 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001895 SetVRegLong(vregA, GetVRegLong(vregA) & GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001896 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001897 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001898 }
1899
David Srbeckybd613ec2019-05-30 15:39:38 +01001900 ALWAYS_INLINE bool OR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001901 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001902 SetVRegLong(vregA, GetVRegLong(vregA) | GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001903 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001904 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001905 }
1906
David Srbeckybd613ec2019-05-30 15:39:38 +01001907 ALWAYS_INLINE bool XOR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001908 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001909 SetVRegLong(vregA, GetVRegLong(vregA) ^ GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001910 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001911 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001912 }
1913
David Srbeckybd613ec2019-05-30 15:39:38 +01001914 ALWAYS_INLINE bool SHL_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001915 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001916 SetVRegLong(vregA, GetVRegLong(vregA) << (GetVReg(B()) & 0x3f));
David Srbecky6da82472018-10-23 14:03:08 +01001917 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001918 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001919 }
1920
David Srbeckybd613ec2019-05-30 15:39:38 +01001921 ALWAYS_INLINE bool SHR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001922 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001923 SetVRegLong(vregA, GetVRegLong(vregA) >> (GetVReg(B()) & 0x3f));
David Srbecky6da82472018-10-23 14:03:08 +01001924 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001925 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001926 }
1927
David Srbeckybd613ec2019-05-30 15:39:38 +01001928 ALWAYS_INLINE bool USHR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001929 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001930 SetVRegLong(vregA, static_cast<uint64_t>(GetVRegLong(vregA)) >> (GetVReg(B()) & 0x3f));
David Srbecky6da82472018-10-23 14:03:08 +01001931 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001932 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001933 }
1934
David Srbeckybd613ec2019-05-30 15:39:38 +01001935 ALWAYS_INLINE bool ADD_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001936 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001937 SetVRegFloat(vregA, GetVRegFloat(vregA) + GetVRegFloat(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001938 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001939 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001940 }
1941
David Srbeckybd613ec2019-05-30 15:39:38 +01001942 ALWAYS_INLINE bool SUB_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001943 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001944 SetVRegFloat(vregA, GetVRegFloat(vregA) - GetVRegFloat(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001945 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001946 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001947 }
1948
David Srbeckybd613ec2019-05-30 15:39:38 +01001949 ALWAYS_INLINE bool MUL_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001950 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001951 SetVRegFloat(vregA, GetVRegFloat(vregA) * GetVRegFloat(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001952 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001953 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001954 }
1955
David Srbeckybd613ec2019-05-30 15:39:38 +01001956 ALWAYS_INLINE bool DIV_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001957 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001958 SetVRegFloat(vregA, GetVRegFloat(vregA) / GetVRegFloat(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001959 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001960 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001961 }
1962
David Srbeckybd613ec2019-05-30 15:39:38 +01001963 ALWAYS_INLINE bool REM_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001964 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001965 SetVRegFloat(vregA, fmodf(GetVRegFloat(vregA), GetVRegFloat(B())));
David Srbecky6da82472018-10-23 14:03:08 +01001966 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001967 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001968 }
1969
David Srbeckybd613ec2019-05-30 15:39:38 +01001970 ALWAYS_INLINE bool ADD_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001971 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001972 SetVRegDouble(vregA, GetVRegDouble(vregA) + GetVRegDouble(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001973 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001974 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001975 }
1976
David Srbeckybd613ec2019-05-30 15:39:38 +01001977 ALWAYS_INLINE bool SUB_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001978 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001979 SetVRegDouble(vregA, GetVRegDouble(vregA) - GetVRegDouble(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001980 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001981 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001982 }
1983
David Srbeckybd613ec2019-05-30 15:39:38 +01001984 ALWAYS_INLINE bool MUL_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001985 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001986 SetVRegDouble(vregA, GetVRegDouble(vregA) * GetVRegDouble(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001987 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001988 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001989 }
1990
David Srbeckybd613ec2019-05-30 15:39:38 +01001991 ALWAYS_INLINE bool DIV_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001992 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01001993 SetVRegDouble(vregA, GetVRegDouble(vregA) / GetVRegDouble(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001994 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01001995 return true;
David Srbecky6da82472018-10-23 14:03:08 +01001996 }
1997
David Srbeckybd613ec2019-05-30 15:39:38 +01001998 ALWAYS_INLINE bool REM_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001999 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002000 SetVRegDouble(vregA, fmod(GetVRegDouble(vregA), GetVRegDouble(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002001 inst = inst->Next_1xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01002002 return true;
David Srbecky6da82472018-10-23 14:03:08 +01002003 }
2004
David Srbeckybd613ec2019-05-30 15:39:38 +01002005 ALWAYS_INLINE bool ADD_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002006 SetVReg(A(), SafeAdd(GetVReg(B()), C()));
David Srbecky6da82472018-10-23 14:03:08 +01002007 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01002008 return true;
David Srbecky6da82472018-10-23 14:03:08 +01002009 }
2010
David Srbeckybd613ec2019-05-30 15:39:38 +01002011 ALWAYS_INLINE bool RSUB_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002012 SetVReg(A(), SafeSub(C(), GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002013 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01002014 return true;
David Srbecky6da82472018-10-23 14:03:08 +01002015 }
2016
David Srbeckybd613ec2019-05-30 15:39:38 +01002017 ALWAYS_INLINE bool MUL_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002018 SetVReg(A(), SafeMul(GetVReg(B()), C()));
David Srbecky6da82472018-10-23 14:03:08 +01002019 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01002020 return true;
David Srbecky6da82472018-10-23 14:03:08 +01002021 }
2022
David Srbeckybd613ec2019-05-30 15:39:38 +01002023 ALWAYS_INLINE bool DIV_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002024 bool success = DoIntDivide(shadow_frame, A(), GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +01002025 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01002026 return true;
David Srbecky6da82472018-10-23 14:03:08 +01002027 }
2028
David Srbeckybd613ec2019-05-30 15:39:38 +01002029 ALWAYS_INLINE bool REM_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002030 bool success = DoIntRemainder(shadow_frame, A(), GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +01002031 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01002032 return true;
David Srbecky6da82472018-10-23 14:03:08 +01002033 }
2034
David Srbeckybd613ec2019-05-30 15:39:38 +01002035 ALWAYS_INLINE bool AND_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002036 SetVReg(A(), GetVReg(B()) & C());
David Srbecky6da82472018-10-23 14:03:08 +01002037 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01002038 return true;
David Srbecky6da82472018-10-23 14:03:08 +01002039 }
2040
David Srbeckybd613ec2019-05-30 15:39:38 +01002041 ALWAYS_INLINE bool OR_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002042 SetVReg(A(), GetVReg(B()) | C());
David Srbecky6da82472018-10-23 14:03:08 +01002043 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01002044 return true;
David Srbecky6da82472018-10-23 14:03:08 +01002045 }
2046
David Srbeckybd613ec2019-05-30 15:39:38 +01002047 ALWAYS_INLINE bool XOR_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002048 SetVReg(A(), GetVReg(B()) ^ C());
David Srbecky6da82472018-10-23 14:03:08 +01002049 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01002050 return true;
David Srbecky6da82472018-10-23 14:03:08 +01002051 }
2052
David Srbeckybd613ec2019-05-30 15:39:38 +01002053 ALWAYS_INLINE bool ADD_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002054 SetVReg(A(), SafeAdd(GetVReg(B()), C()));
David Srbecky6da82472018-10-23 14:03:08 +01002055 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01002056 return true;
David Srbecky6da82472018-10-23 14:03:08 +01002057 }
2058
David Srbeckybd613ec2019-05-30 15:39:38 +01002059 ALWAYS_INLINE bool RSUB_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002060 SetVReg(A(), SafeSub(C(), GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002061 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01002062 return true;
David Srbecky6da82472018-10-23 14:03:08 +01002063 }
2064
David Srbeckybd613ec2019-05-30 15:39:38 +01002065 ALWAYS_INLINE bool MUL_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002066 SetVReg(A(), SafeMul(GetVReg(B()), C()));
David Srbecky6da82472018-10-23 14:03:08 +01002067 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01002068 return true;
David Srbecky6da82472018-10-23 14:03:08 +01002069 }
2070
David Srbeckybd613ec2019-05-30 15:39:38 +01002071 ALWAYS_INLINE bool DIV_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002072 bool success = DoIntDivide(shadow_frame, A(), GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +01002073 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01002074 return true;
David Srbecky6da82472018-10-23 14:03:08 +01002075 }
2076
David Srbeckybd613ec2019-05-30 15:39:38 +01002077 ALWAYS_INLINE bool REM_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002078 bool success = DoIntRemainder(shadow_frame, A(), GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +01002079 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
David Srbeckybd613ec2019-05-30 15:39:38 +01002080 return true;
David Srbecky6da82472018-10-23 14:03:08 +01002081 }
2082
David Srbeckybd613ec2019-05-30 15:39:38 +01002083 ALWAYS_INLINE bool AND_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002084 SetVReg(A(), GetVReg(B()) & C());
David Srbecky6da82472018-10-23 14:03:08 +01002085 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01002086 return true;
David Srbecky6da82472018-10-23 14:03:08 +01002087 }
2088
David Srbeckybd613ec2019-05-30 15:39:38 +01002089 ALWAYS_INLINE bool OR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002090 SetVReg(A(), GetVReg(B()) | C());
David Srbecky6da82472018-10-23 14:03:08 +01002091 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01002092 return true;
David Srbecky6da82472018-10-23 14:03:08 +01002093 }
2094
David Srbeckybd613ec2019-05-30 15:39:38 +01002095 ALWAYS_INLINE bool XOR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002096 SetVReg(A(), GetVReg(B()) ^ C());
David Srbecky6da82472018-10-23 14:03:08 +01002097 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01002098 return true;
David Srbecky6da82472018-10-23 14:03:08 +01002099 }
2100
David Srbeckybd613ec2019-05-30 15:39:38 +01002101 ALWAYS_INLINE bool SHL_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002102 SetVReg(A(), GetVReg(B()) << (C() & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01002103 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01002104 return true;
David Srbecky6da82472018-10-23 14:03:08 +01002105 }
2106
David Srbeckybd613ec2019-05-30 15:39:38 +01002107 ALWAYS_INLINE bool SHR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002108 SetVReg(A(), GetVReg(B()) >> (C() & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01002109 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01002110 return true;
David Srbecky6da82472018-10-23 14:03:08 +01002111 }
2112
David Srbeckybd613ec2019-05-30 15:39:38 +01002113 ALWAYS_INLINE bool USHR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002114 SetVReg(A(), static_cast<uint32_t>(GetVReg(B())) >> (C() & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01002115 inst = inst->Next_2xx();
David Srbeckybd613ec2019-05-30 15:39:38 +01002116 return true;
David Srbecky6da82472018-10-23 14:03:08 +01002117 }
2118
David Srbeckybd613ec2019-05-30 15:39:38 +01002119 ALWAYS_INLINE bool UNUSED_3E() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01002120 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01002121 }
2122
David Srbeckybd613ec2019-05-30 15:39:38 +01002123 ALWAYS_INLINE bool UNUSED_3F() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01002124 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01002125 }
2126
David Srbeckybd613ec2019-05-30 15:39:38 +01002127 ALWAYS_INLINE bool UNUSED_40() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01002128 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01002129 }
2130
David Srbeckybd613ec2019-05-30 15:39:38 +01002131 ALWAYS_INLINE bool UNUSED_41() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01002132 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01002133 }
2134
David Srbeckybd613ec2019-05-30 15:39:38 +01002135 ALWAYS_INLINE bool UNUSED_42() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01002136 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01002137 }
2138
David Srbeckybd613ec2019-05-30 15:39:38 +01002139 ALWAYS_INLINE bool UNUSED_43() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01002140 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01002141 }
2142
David Srbeckybd613ec2019-05-30 15:39:38 +01002143 ALWAYS_INLINE bool UNUSED_79() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01002144 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01002145 }
2146
David Srbeckybd613ec2019-05-30 15:39:38 +01002147 ALWAYS_INLINE bool UNUSED_7A() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01002148 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01002149 }
2150
David Srbeckybd613ec2019-05-30 15:39:38 +01002151 ALWAYS_INLINE bool UNUSED_F3() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01002152 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01002153 }
2154
David Srbeckybd613ec2019-05-30 15:39:38 +01002155 ALWAYS_INLINE bool UNUSED_F4() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01002156 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01002157 }
2158
David Srbeckybd613ec2019-05-30 15:39:38 +01002159 ALWAYS_INLINE bool UNUSED_F5() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01002160 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01002161 }
2162
David Srbeckybd613ec2019-05-30 15:39:38 +01002163 ALWAYS_INLINE bool UNUSED_F6() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01002164 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01002165 }
2166
David Srbeckybd613ec2019-05-30 15:39:38 +01002167 ALWAYS_INLINE bool UNUSED_F7() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01002168 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01002169 }
2170
David Srbeckybd613ec2019-05-30 15:39:38 +01002171 ALWAYS_INLINE bool UNUSED_F8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01002172 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01002173 }
2174
David Srbeckybd613ec2019-05-30 15:39:38 +01002175 ALWAYS_INLINE bool UNUSED_F9() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyee12e3a2019-06-03 15:18:57 +01002176 return HandleUnused();
David Srbecky6da82472018-10-23 14:03:08 +01002177 }
2178
2179 ALWAYS_INLINE InstructionHandler(SwitchImplContext* ctx,
2180 const instrumentation::Instrumentation* instrumentation,
2181 Thread* self,
2182 ShadowFrame& shadow_frame,
2183 uint16_t dex_pc,
2184 const Instruction*& inst,
2185 uint16_t inst_data,
David Srbecky8867f3b2019-05-31 20:01:46 +01002186 const Instruction*& next,
David Srbecky6da82472018-10-23 14:03:08 +01002187 bool& exit_interpreter_loop)
2188 : ctx(ctx),
2189 instrumentation(instrumentation),
2190 self(self),
2191 shadow_frame(shadow_frame),
2192 dex_pc(dex_pc),
2193 inst(inst),
2194 inst_data(inst_data),
David Srbecky8867f3b2019-05-31 20:01:46 +01002195 next(next),
David Srbecky6da82472018-10-23 14:03:08 +01002196 exit_interpreter_loop(exit_interpreter_loop) {
2197 }
2198
2199 private:
2200 static constexpr bool do_assignability_check = do_access_check;
2201
2202 const CodeItemDataAccessor& Accessor() { return ctx->accessor; }
2203 const uint16_t* Insns() { return ctx->accessor.Insns(); }
2204 JValue* ResultRegister() { return &ctx->result_register; }
2205
David Srbecky436f6c12019-05-22 13:28:42 +01002206 ALWAYS_INLINE int32_t A() { return inst->VRegA(kFormat, inst_data); }
2207 ALWAYS_INLINE int32_t B() { return inst->VRegB(kFormat, inst_data); }
2208 ALWAYS_INLINE int32_t C() { return inst->VRegC(kFormat); }
2209
David Srbecky6baf6442019-05-30 14:57:43 +01002210 int32_t GetVReg(size_t i) const { return shadow_frame.GetVReg(i); }
2211 int64_t GetVRegLong(size_t i) const { return shadow_frame.GetVRegLong(i); }
2212 float GetVRegFloat(size_t i) const { return shadow_frame.GetVRegFloat(i); }
2213 double GetVRegDouble(size_t i) const { return shadow_frame.GetVRegDouble(i); }
2214 ObjPtr<mirror::Object> GetVRegReference(size_t i) const REQUIRES_SHARED(Locks::mutator_lock_) {
2215 return shadow_frame.GetVRegReference(i);
2216 }
2217
2218 void SetVReg(size_t i, int32_t val) { shadow_frame.SetVReg(i, val); }
2219 void SetVRegLong(size_t i, int64_t val) { shadow_frame.SetVRegLong(i, val); }
2220 void SetVRegFloat(size_t i, float val) { shadow_frame.SetVRegFloat(i, val); }
2221 void SetVRegDouble(size_t i, double val) { shadow_frame.SetVRegDouble(i, val); }
2222 void SetVRegReference(size_t i, ObjPtr<mirror::Object> val)
2223 REQUIRES_SHARED(Locks::mutator_lock_) {
2224 shadow_frame.SetVRegReference(i, val);
2225 }
2226
David Srbecky8867f3b2019-05-31 20:01:46 +01002227 // Set the next instruction to be executed. It is the 'fall-through' instruction by default.
2228 ALWAYS_INLINE void SetNextInstruction(const Instruction* next_inst) {
2229 DCHECK_LT(next_inst->GetDexPc(Insns()), Accessor().InsnsSizeInCodeUnits());
2230 next = next_inst;
2231 }
2232
David Srbecky6da82472018-10-23 14:03:08 +01002233 SwitchImplContext* const ctx;
2234 const instrumentation::Instrumentation* const instrumentation;
2235 Thread* const self;
2236 ShadowFrame& shadow_frame;
2237 uint32_t const dex_pc;
2238 const Instruction*& inst;
2239 uint16_t const inst_data;
David Srbecky8867f3b2019-05-31 20:01:46 +01002240 const Instruction*& next;
2241
David Srbecky6da82472018-10-23 14:03:08 +01002242 bool& exit_interpreter_loop;
2243};
2244
David Srbecky6da82472018-10-23 14:03:08 +01002245#undef BRANCH_INSTRUMENTATION
David Srbecky6da82472018-10-23 14:03:08 +01002246#undef POSSIBLY_HANDLE_PENDING_EXCEPTION
2247#undef POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE
2248#undef POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC
David Srbecky6da82472018-10-23 14:03:08 +01002249#undef HANDLE_PENDING_EXCEPTION
David Srbecky6da82472018-10-23 14:03:08 +01002250
Alex Light6f22e062018-10-05 15:05:12 -07002251// TODO On ASAN builds this function gets a huge stack frame. Since normally we run in the mterp
2252// this shouldn't cause any problems for stack overflow detection. Remove this once b/117341496 is
2253// fixed.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +01002254template<bool do_access_check, bool transaction_active>
Alex Light6f22e062018-10-05 15:05:12 -07002255ATTRIBUTE_NO_SANITIZE_ADDRESS void ExecuteSwitchImplCpp(SwitchImplContext* ctx) {
David Srbecky946bb092018-03-09 17:23:01 +00002256 Thread* self = ctx->self;
2257 const CodeItemDataAccessor& accessor = ctx->accessor;
2258 ShadowFrame& shadow_frame = ctx->shadow_frame;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002259 if (UNLIKELY(!shadow_frame.HasReferenceArray())) {
2260 LOG(FATAL) << "Invalid shadow frame for interpreter use";
David Srbecky946bb092018-03-09 17:23:01 +00002261 ctx->result = JValue();
2262 return;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002263 }
2264 self->VerifyStack();
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002265
2266 uint32_t dex_pc = shadow_frame.GetDexPC();
Mathieu Chartier2cebb242015-04-21 16:50:40 -07002267 const auto* const instrumentation = Runtime::Current()->GetInstrumentation();
Mathieu Chartier808c7a52017-12-15 11:19:33 -08002268 const uint16_t* const insns = accessor.Insns();
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002269 const Instruction* inst = Instruction::At(insns + dex_pc);
Sebastien Hertz3b588e02013-09-11 14:33:18 +02002270 uint16_t inst_data;
Igor Murashkin6918bf12015-09-27 19:19:06 -07002271
Alex Light0aa7a5a2018-10-10 15:58:14 +00002272 DCHECK(!shadow_frame.GetForceRetryInstruction())
2273 << "Entered interpreter from invoke without retry instruction being handled!";
2274
David Srbecky6da82472018-10-23 14:03:08 +01002275 bool const interpret_one_instruction = ctx->interpret_one_instruction;
2276 while (true) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002277 dex_pc = inst->GetDexPc(insns);
2278 shadow_frame.SetDexPC(dex_pc);
Ian Rogerse94652f2014-12-02 11:13:19 -08002279 TraceExecution(shadow_frame, inst, dex_pc);
Sebastien Hertz3b588e02013-09-11 14:33:18 +02002280 inst_data = inst->Fetch16(0);
David Srbeckya4a96af2018-10-31 16:34:58 +00002281 {
David Srbecky8867f3b2019-05-31 20:01:46 +01002282 const Instruction* next = nullptr;
David Srbeckya4a96af2018-10-31 16:34:58 +00002283 bool exit_loop = false;
David Srbecky436f6c12019-05-22 13:28:42 +01002284 InstructionHandler<do_access_check, transaction_active, Instruction::kInvalidFormat> handler(
David Srbecky8867f3b2019-05-31 20:01:46 +01002285 ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, next, exit_loop);
David Srbeckya4a96af2018-10-31 16:34:58 +00002286 if (!handler.Preamble()) {
2287 if (UNLIKELY(exit_loop)) {
2288 return;
2289 }
2290 if (UNLIKELY(interpret_one_instruction)) {
2291 break;
2292 }
2293 continue;
2294 }
2295 }
Sebastien Hertz3b588e02013-09-11 14:33:18 +02002296 switch (inst->Opcode(inst_data)) {
David Srbecky8867f3b2019-05-31 20:01:46 +01002297#define OPCODE_CASE(OPCODE, OPCODE_NAME, NAME, FORMAT, i, a, e, v) \
David Srbecky6da82472018-10-23 14:03:08 +01002298 case OPCODE: { \
David Srbecky8867f3b2019-05-31 20:01:46 +01002299 size_t inst_size = Instruction::SizeInCodeUnits(Instruction::FORMAT); \
2300 const Instruction* next = inst->RelativeAt(inst_size); \
David Srbecky6da82472018-10-23 14:03:08 +01002301 bool exit_loop = false; \
David Srbecky436f6c12019-05-22 13:28:42 +01002302 InstructionHandler<do_access_check, transaction_active, Instruction::FORMAT> handler( \
David Srbecky8867f3b2019-05-31 20:01:46 +01002303 ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, next, exit_loop); \
David Srbeckya4a96af2018-10-31 16:34:58 +00002304 handler.OPCODE_NAME(); \
David Srbecky6da82472018-10-23 14:03:08 +01002305 if (UNLIKELY(exit_loop)) { \
2306 return; \
2307 } \
David Srbecky8867f3b2019-05-31 20:01:46 +01002308 DCHECK_EQ(next, inst) << NAME; \
David Srbecky6da82472018-10-23 14:03:08 +01002309 break; \
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002310 }
David Srbecky6da82472018-10-23 14:03:08 +01002311DEX_INSTRUCTION_LIST(OPCODE_CASE)
2312#undef OPCODE_CASE
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002313 }
David Srbecky6da82472018-10-23 14:03:08 +01002314 if (UNLIKELY(interpret_one_instruction)) {
David Srbeckya4a96af2018-10-31 16:34:58 +00002315 break;
David Srbecky6da82472018-10-23 14:03:08 +01002316 }
2317 }
David Srbeckya4a96af2018-10-31 16:34:58 +00002318 // Record where we stopped.
2319 shadow_frame.SetDexPC(inst->GetDexPc(insns));
2320 ctx->result = ctx->result_register;
2321 return;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002322} // NOLINT(readability/fn_size)
2323
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002324} // namespace interpreter
2325} // namespace art
David Srbecky2ee09ff2018-10-24 13:24:22 +01002326
2327#endif // ART_RUNTIME_INTERPRETER_INTERPRETER_SWITCH_IMPL_INL_H_