blob: 90acc7ecb4dc38eea4ce16974b7f13f982d48cac [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);
137 inst = inst->RelativeAt(displacement);
138 return false; // Stop executing this opcode and continue in the exception handler.
139 }
140
David Srbecky5f250012018-11-08 14:16:38 +0000141 // Forwards the call to the NO_INLINE HandlePendingExceptionWithInstrumentationImpl.
142 ALWAYS_INLINE WARN_UNUSED bool HandlePendingExceptionWithInstrumentation(
143 const instrumentation::Instrumentation* instr)
144 REQUIRES_SHARED(Locks::mutator_lock_) {
145 // We need to help the compiler a bit to make the NO_INLINE call efficient.
146 // * All handler fields should be in registers, so we do not want to take the object
147 // address (for 'this' argument). Make a copy of the handler just for the slow path.
148 // * The modifiable fields should also be in registers, so we don't want to store their
149 // address even in the handler copy. Make a copy of them just for the call as well.
150 const Instruction* inst_copy = inst;
151 bool exit_loop_copy = exit_interpreter_loop;
David Srbecky436f6c12019-05-22 13:28:42 +0100152 InstructionHandler<do_access_check, transaction_active, kFormat> handler_copy(
David Srbecky5f250012018-11-08 14:16:38 +0000153 ctx, instrumentation, self, shadow_frame, dex_pc, inst_copy, inst_data, exit_loop_copy);
154 bool result = handler_copy.HandlePendingExceptionWithInstrumentationImpl(instr);
155 inst = inst_copy;
156 exit_interpreter_loop = exit_loop_copy;
157 return result;
158 }
159
David Srbecky47ad3762018-10-31 12:43:40 +0000160 ALWAYS_INLINE WARN_UNUSED bool HandlePendingException()
161 REQUIRES_SHARED(Locks::mutator_lock_) {
162 return HandlePendingExceptionWithInstrumentation(instrumentation);
163 }
164
165 ALWAYS_INLINE WARN_UNUSED bool PossiblyHandlePendingExceptionOnInvokeImpl(
166 bool is_exception_pending,
167 const Instruction* next_inst)
168 REQUIRES_SHARED(Locks::mutator_lock_) {
169 if (UNLIKELY(shadow_frame.GetForceRetryInstruction())) {
170 /* Don't need to do anything except clear the flag and exception. We leave the */
171 /* instruction the same so it will be re-executed on the next go-around. */
172 DCHECK(inst->IsInvoke());
173 shadow_frame.SetForceRetryInstruction(false);
174 if (UNLIKELY(is_exception_pending)) {
175 DCHECK(self->IsExceptionPending());
176 if (kIsDebugBuild) {
177 LOG(WARNING) << "Suppressing exception for instruction-retry: "
178 << self->GetException()->Dump();
179 }
180 self->ClearException();
181 }
182 } else if (UNLIKELY(is_exception_pending)) {
183 /* Should have succeeded. */
184 DCHECK(!shadow_frame.GetForceRetryInstruction());
185 if (!HandlePendingException()) {
186 return false;
187 }
188 } else {
189 inst = next_inst;
190 }
191 return true;
192 }
193
194 ALWAYS_INLINE WARN_UNUSED bool PossiblyHandlePendingException(
195 bool is_exception_pending,
196 const Instruction* next_inst)
197 REQUIRES_SHARED(Locks::mutator_lock_) {
198 /* Should only be on invoke instructions. */
199 DCHECK(!shadow_frame.GetForceRetryInstruction());
200 if (UNLIKELY(is_exception_pending)) {
201 if (!HandlePendingException()) {
202 return false;
203 }
204 } else {
205 inst = next_inst;
206 }
207 return true;
208 }
209
210 ALWAYS_INLINE WARN_UNUSED bool HandleMonitorChecks()
211 REQUIRES_SHARED(Locks::mutator_lock_) {
212 if (!DoMonitorCheckOnExit<do_assignability_check>(self, &shadow_frame)) {
213 if (!HandlePendingException()) {
214 return false;
215 }
216 }
217 return true;
218 }
219
220 // Code to run before each dex instruction.
David Srbeckya4a96af2018-10-31 16:34:58 +0000221 ALWAYS_INLINE WARN_UNUSED bool Preamble()
David Srbecky47ad3762018-10-31 12:43:40 +0000222 REQUIRES_SHARED(Locks::mutator_lock_) {
223 /* We need to put this before & after the instrumentation to avoid having to put in a */
224 /* post-script macro. */
225 if (!CheckForceReturn()) {
226 return false;
227 }
228 if (UNLIKELY(instrumentation->HasDexPcListeners())) {
David Srbeckya4a96af2018-10-31 16:34:58 +0000229 uint8_t opcode = inst->Opcode(inst_data);
230 bool is_move_result_object = (opcode == Instruction::MOVE_RESULT_OBJECT);
231 JValue* save_ref = is_move_result_object ? &ctx->result_register : nullptr;
David Srbecky47ad3762018-10-31 12:43:40 +0000232 if (UNLIKELY(!DoDexPcMoveEvent(self,
233 Accessor(),
234 shadow_frame,
235 dex_pc,
236 instrumentation,
237 save_ref))) {
238 if (!HandlePendingException()) {
239 return false;
240 }
241 }
242 if (!CheckForceReturn()) {
243 return false;
244 }
245 }
246 return true;
247 }
248
249 ALWAYS_INLINE WARN_UNUSED bool BranchInstrumentation(int32_t offset)
250 REQUIRES_SHARED(Locks::mutator_lock_) {
251 if (UNLIKELY(instrumentation->HasBranchListeners())) {
252 instrumentation->Branch(self, shadow_frame.GetMethod(), dex_pc, offset);
253 }
254 JValue result;
255 if (jit::Jit::MaybeDoOnStackReplacement(self,
256 shadow_frame.GetMethod(),
257 dex_pc,
258 offset,
259 &result)) {
260 if (ctx->interpret_one_instruction) {
261 /* OSR has completed execution of the method. Signal mterp to return to caller */
262 shadow_frame.SetDexPC(dex::kDexNoIndex);
263 }
264 ctx->result = result;
265 exit_interpreter_loop = true;
266 return false;
267 }
268 return true;
269 }
270
271 ALWAYS_INLINE void HotnessUpdate()
272 REQUIRES_SHARED(Locks::mutator_lock_) {
273 jit::Jit* jit = Runtime::Current()->GetJit();
274 if (jit != nullptr) {
275 jit->AddSamples(self, shadow_frame.GetMethod(), 1, /*with_backedges=*/ true);
276 }
277 }
278
279 ALWAYS_INLINE WARN_UNUSED bool HandleAsyncException()
280 REQUIRES_SHARED(Locks::mutator_lock_) {
281 if (UNLIKELY(self->ObserveAsyncException())) {
282 if (!HandlePendingException()) {
283 return false;
284 }
285 }
286 return true;
287 }
288
289 ALWAYS_INLINE void HandleBackwardBranch(int32_t offset)
290 REQUIRES_SHARED(Locks::mutator_lock_) {
291 if (IsBackwardBranch(offset)) {
292 HotnessUpdate();
293 /* Record new dex pc early to have consistent suspend point at loop header. */
294 shadow_frame.SetDexPC(inst->GetDexPc(Insns()));
295 self->AllowThreadSuspension();
296 }
297 }
298
299 // Unlike most other events the DexPcMovedEvent can be sent when there is a pending exception (if
300 // the next instruction is MOVE_EXCEPTION). This means it needs to be handled carefully to be able
301 // to detect exceptions thrown by the DexPcMovedEvent itself. These exceptions could be thrown by
302 // jvmti-agents while handling breakpoint or single step events. We had to move this into its own
303 // function because it was making ExecuteSwitchImpl have too large a stack.
304 NO_INLINE static bool DoDexPcMoveEvent(Thread* self,
305 const CodeItemDataAccessor& accessor,
306 const ShadowFrame& shadow_frame,
307 uint32_t dex_pc,
308 const instrumentation::Instrumentation* instrumentation,
309 JValue* save_ref)
310 REQUIRES_SHARED(Locks::mutator_lock_) {
311 DCHECK(instrumentation->HasDexPcListeners());
312 StackHandleScope<2> hs(self);
313 Handle<mirror::Throwable> thr(hs.NewHandle(self->GetException()));
314 mirror::Object* null_obj = nullptr;
315 HandleWrapper<mirror::Object> h(
316 hs.NewHandleWrapper(LIKELY(save_ref == nullptr) ? &null_obj : save_ref->GetGCRoot()));
317 self->ClearException();
318 instrumentation->DexPcMovedEvent(self,
319 shadow_frame.GetThisObject(accessor.InsSize()),
320 shadow_frame.GetMethod(),
321 dex_pc);
322 if (UNLIKELY(self->IsExceptionPending())) {
323 // We got a new exception in the dex-pc-moved event.
324 // We just let this exception replace the old one.
325 // TODO It would be good to add the old exception to the
326 // suppressed exceptions of the new one if possible.
327 return false;
328 } else {
329 if (UNLIKELY(!thr.IsNull())) {
330 self->SetException(thr.Get());
331 }
332 return true;
333 }
334 }
335
336 static bool NeedsMethodExitEvent(const instrumentation::Instrumentation* ins)
337 REQUIRES_SHARED(Locks::mutator_lock_) {
338 return ins->HasMethodExitListeners() || ins->HasWatchedFramePopListeners();
339 }
340
341 // Sends the normal method exit event.
342 // Returns true if the events succeeded and false if there is a pending exception.
343 NO_INLINE static bool SendMethodExitEvents(
344 Thread* self,
345 const instrumentation::Instrumentation* instrumentation,
346 const ShadowFrame& frame,
347 ObjPtr<mirror::Object> thiz,
348 ArtMethod* method,
349 uint32_t dex_pc,
350 const JValue& result)
351 REQUIRES_SHARED(Locks::mutator_lock_) {
352 bool had_event = false;
353 // We don't send method-exit if it's a pop-frame. We still send frame_popped though.
354 if (UNLIKELY(instrumentation->HasMethodExitListeners() && !frame.GetForcePopFrame())) {
355 had_event = true;
Vladimir Marko19711d42019-04-12 14:05:34 +0100356 instrumentation->MethodExitEvent(self, thiz, method, dex_pc, result);
David Srbecky47ad3762018-10-31 12:43:40 +0000357 }
358 if (UNLIKELY(frame.NeedsNotifyPop() && instrumentation->HasWatchedFramePopListeners())) {
359 had_event = true;
360 instrumentation->WatchedFramePopped(self, frame);
361 }
362 if (UNLIKELY(had_event)) {
363 return !self->IsExceptionPending();
364 } else {
365 return true;
366 }
367 }
368
369#define BRANCH_INSTRUMENTATION(offset) \
370 if (!BranchInstrumentation(offset)) { \
371 return; \
372 }
373
374#define HANDLE_PENDING_EXCEPTION() \
375 if (!HandlePendingException()) { \
376 return; \
377 }
378
379#define POSSIBLY_HANDLE_PENDING_EXCEPTION(is_exception_pending, next_function) \
380 if (!PossiblyHandlePendingException(is_exception_pending, inst->next_function())) { \
381 return; \
382 }
383
384#define POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(is_exception_pending) \
385 if (!PossiblyHandlePendingExceptionOnInvokeImpl(is_exception_pending, inst->Next_4xx())) { \
386 return; \
387 }
388
389#define POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(is_exception_pending) \
390 if (!PossiblyHandlePendingExceptionOnInvokeImpl(is_exception_pending, inst->Next_3xx())) { \
391 return; \
392 }
393
David Srbecky6da82472018-10-23 14:03:08 +0100394 ALWAYS_INLINE void NOP() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100395 inst = inst->Next_1xx();
396 }
397
398 ALWAYS_INLINE void MOVE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100399 shadow_frame.SetVReg(A(),
400 shadow_frame.GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100401 inst = inst->Next_1xx();
402 }
403
404 ALWAYS_INLINE void MOVE_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100405 shadow_frame.SetVReg(A(),
406 shadow_frame.GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100407 inst = inst->Next_2xx();
408 }
409
410 ALWAYS_INLINE void MOVE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100411 shadow_frame.SetVReg(A(),
412 shadow_frame.GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100413 inst = inst->Next_3xx();
414 }
415
416 ALWAYS_INLINE void MOVE_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100417 shadow_frame.SetVRegLong(A(),
418 shadow_frame.GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100419 inst = inst->Next_1xx();
420 }
421
422 ALWAYS_INLINE void MOVE_WIDE_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100423 shadow_frame.SetVRegLong(A(),
424 shadow_frame.GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100425 inst = inst->Next_2xx();
426 }
427
428 ALWAYS_INLINE void MOVE_WIDE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100429 shadow_frame.SetVRegLong(A(),
430 shadow_frame.GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100431 inst = inst->Next_3xx();
432 }
433
434 ALWAYS_INLINE void MOVE_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100435 shadow_frame.SetVRegReference(A(),
436 shadow_frame.GetVRegReference(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100437 inst = inst->Next_1xx();
438 }
439
440 ALWAYS_INLINE void MOVE_OBJECT_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100441 shadow_frame.SetVRegReference(A(),
442 shadow_frame.GetVRegReference(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100443 inst = inst->Next_2xx();
444 }
445
446 ALWAYS_INLINE void MOVE_OBJECT_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100447 shadow_frame.SetVRegReference(A(),
448 shadow_frame.GetVRegReference(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100449 inst = inst->Next_3xx();
450 }
451
452 ALWAYS_INLINE void MOVE_RESULT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100453 shadow_frame.SetVReg(A(), ResultRegister()->GetI());
David Srbecky6da82472018-10-23 14:03:08 +0100454 inst = inst->Next_1xx();
455 }
456
457 ALWAYS_INLINE void MOVE_RESULT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100458 shadow_frame.SetVRegLong(A(), ResultRegister()->GetJ());
David Srbecky6da82472018-10-23 14:03:08 +0100459 inst = inst->Next_1xx();
460 }
461
462 ALWAYS_INLINE void MOVE_RESULT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100463 shadow_frame.SetVRegReference(A(), ResultRegister()->GetL());
David Srbecky6da82472018-10-23 14:03:08 +0100464 inst = inst->Next_1xx();
465 }
466
467 ALWAYS_INLINE void MOVE_EXCEPTION() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100468 ObjPtr<mirror::Throwable> exception = self->GetException();
469 DCHECK(exception != nullptr) << "No pending exception on MOVE_EXCEPTION instruction";
David Srbecky436f6c12019-05-22 13:28:42 +0100470 shadow_frame.SetVRegReference(A(), exception);
David Srbecky6da82472018-10-23 14:03:08 +0100471 self->ClearException();
472 inst = inst->Next_1xx();
473 }
474
475 ALWAYS_INLINE void RETURN_VOID_NO_BARRIER() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100476 JValue result;
477 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000478 if (!HandleMonitorChecks()) {
479 return;
480 }
David Srbecky6da82472018-10-23 14:03:08 +0100481 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
482 !SendMethodExitEvents(self,
483 instrumentation,
484 shadow_frame,
485 shadow_frame.GetThisObject(Accessor().InsSize()),
486 shadow_frame.GetMethod(),
487 inst->GetDexPc(Insns()),
488 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000489 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
490 return;
491 }
David Srbecky6da82472018-10-23 14:03:08 +0100492 }
493 if (ctx->interpret_one_instruction) {
494 /* Signal mterp to return to caller */
495 shadow_frame.SetDexPC(dex::kDexNoIndex);
496 }
497 ctx->result = result;
498 exit_interpreter_loop = true;
499 }
500
501 ALWAYS_INLINE void RETURN_VOID() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100502 QuasiAtomic::ThreadFenceForConstructor();
503 JValue result;
504 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000505 if (!HandleMonitorChecks()) {
506 return;
507 }
David Srbecky6da82472018-10-23 14:03:08 +0100508 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
509 !SendMethodExitEvents(self,
510 instrumentation,
511 shadow_frame,
512 shadow_frame.GetThisObject(Accessor().InsSize()),
513 shadow_frame.GetMethod(),
514 inst->GetDexPc(Insns()),
515 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000516 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
517 return;
518 }
David Srbecky6da82472018-10-23 14:03:08 +0100519 }
520 if (ctx->interpret_one_instruction) {
521 /* Signal mterp to return to caller */
522 shadow_frame.SetDexPC(dex::kDexNoIndex);
523 }
524 ctx->result = result;
525 exit_interpreter_loop = true;
526 }
527
528 ALWAYS_INLINE void RETURN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100529 JValue result;
530 result.SetJ(0);
David Srbecky436f6c12019-05-22 13:28:42 +0100531 result.SetI(shadow_frame.GetVReg(A()));
David Srbecky6da82472018-10-23 14:03:08 +0100532 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000533 if (!HandleMonitorChecks()) {
534 return;
535 }
David Srbecky6da82472018-10-23 14:03:08 +0100536 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
537 !SendMethodExitEvents(self,
538 instrumentation,
539 shadow_frame,
540 shadow_frame.GetThisObject(Accessor().InsSize()),
541 shadow_frame.GetMethod(),
542 inst->GetDexPc(Insns()),
543 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000544 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
545 return;
546 }
David Srbecky6da82472018-10-23 14:03:08 +0100547 }
548 if (ctx->interpret_one_instruction) {
549 /* Signal mterp to return to caller */
550 shadow_frame.SetDexPC(dex::kDexNoIndex);
551 }
552 ctx->result = result;
553 exit_interpreter_loop = true;
554 }
555
556 ALWAYS_INLINE void RETURN_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100557 JValue result;
David Srbecky436f6c12019-05-22 13:28:42 +0100558 result.SetJ(shadow_frame.GetVRegLong(A()));
David Srbecky6da82472018-10-23 14:03:08 +0100559 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000560 if (!HandleMonitorChecks()) {
561 return;
562 }
David Srbecky6da82472018-10-23 14:03:08 +0100563 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
564 !SendMethodExitEvents(self,
565 instrumentation,
566 shadow_frame,
567 shadow_frame.GetThisObject(Accessor().InsSize()),
568 shadow_frame.GetMethod(),
569 inst->GetDexPc(Insns()),
570 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000571 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
572 return;
573 }
David Srbecky6da82472018-10-23 14:03:08 +0100574 }
575 if (ctx->interpret_one_instruction) {
576 /* Signal mterp to return to caller */
577 shadow_frame.SetDexPC(dex::kDexNoIndex);
578 }
579 ctx->result = result;
580 exit_interpreter_loop = true;
581 }
582
583 ALWAYS_INLINE void RETURN_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100584 JValue result;
585 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000586 if (!HandleMonitorChecks()) {
587 return;
588 }
David Srbeckyd6f579c2019-05-29 18:09:30 +0100589 const size_t ref_idx = A();
David Srbecky6da82472018-10-23 14:03:08 +0100590 ObjPtr<mirror::Object> obj_result = shadow_frame.GetVRegReference(ref_idx);
591 if (do_assignability_check && obj_result != nullptr) {
592 ObjPtr<mirror::Class> return_type = shadow_frame.GetMethod()->ResolveReturnType();
593 // Re-load since it might have moved.
594 obj_result = shadow_frame.GetVRegReference(ref_idx);
595 if (return_type == nullptr) {
596 // Return the pending exception.
597 HANDLE_PENDING_EXCEPTION();
598 }
599 if (!obj_result->VerifierInstanceOf(return_type)) {
600 // This should never happen.
601 std::string temp1, temp2;
602 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
603 "Returning '%s' that is not instance of return type '%s'",
604 obj_result->GetClass()->GetDescriptor(&temp1),
605 return_type->GetDescriptor(&temp2));
606 HANDLE_PENDING_EXCEPTION();
607 }
608 }
609 result.SetL(obj_result);
610 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
611 !SendMethodExitEvents(self,
612 instrumentation,
613 shadow_frame,
614 shadow_frame.GetThisObject(Accessor().InsSize()),
615 shadow_frame.GetMethod(),
616 inst->GetDexPc(Insns()),
617 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000618 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
619 return;
620 }
David Srbecky6da82472018-10-23 14:03:08 +0100621 }
622 // Re-load since it might have moved during the MethodExitEvent.
623 result.SetL(shadow_frame.GetVRegReference(ref_idx));
624 if (ctx->interpret_one_instruction) {
625 /* Signal mterp to return to caller */
626 shadow_frame.SetDexPC(dex::kDexNoIndex);
627 }
628 ctx->result = result;
629 exit_interpreter_loop = true;
630 }
631
632 ALWAYS_INLINE void CONST_4() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100633 uint4_t dst = inst->VRegA_11n(inst_data);
634 int4_t val = inst->VRegB_11n(inst_data);
635 shadow_frame.SetVReg(dst, val);
636 if (val == 0) {
637 shadow_frame.SetVRegReference(dst, nullptr);
638 }
639 inst = inst->Next_1xx();
640 }
641
642 ALWAYS_INLINE void CONST_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100643 uint8_t dst = A();
644 int16_t val = B();
David Srbecky6da82472018-10-23 14:03:08 +0100645 shadow_frame.SetVReg(dst, val);
646 if (val == 0) {
647 shadow_frame.SetVRegReference(dst, nullptr);
648 }
649 inst = inst->Next_2xx();
650 }
651
652 ALWAYS_INLINE void CONST() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100653 uint8_t dst = A();
654 int32_t val = B();
David Srbecky6da82472018-10-23 14:03:08 +0100655 shadow_frame.SetVReg(dst, val);
656 if (val == 0) {
657 shadow_frame.SetVRegReference(dst, nullptr);
658 }
659 inst = inst->Next_3xx();
660 }
661
662 ALWAYS_INLINE void CONST_HIGH16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100663 uint8_t dst = A();
664 int32_t val = static_cast<int32_t>(B() << 16);
David Srbecky6da82472018-10-23 14:03:08 +0100665 shadow_frame.SetVReg(dst, val);
666 if (val == 0) {
667 shadow_frame.SetVRegReference(dst, nullptr);
668 }
669 inst = inst->Next_2xx();
670 }
671
672 ALWAYS_INLINE void CONST_WIDE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100673 shadow_frame.SetVRegLong(A(), B());
David Srbecky6da82472018-10-23 14:03:08 +0100674 inst = inst->Next_2xx();
675 }
676
677 ALWAYS_INLINE void CONST_WIDE_32() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100678 shadow_frame.SetVRegLong(A(), B());
David Srbecky6da82472018-10-23 14:03:08 +0100679 inst = inst->Next_3xx();
680 }
681
682 ALWAYS_INLINE void CONST_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100683 shadow_frame.SetVRegLong(A(), inst->WideVRegB());
David Srbecky6da82472018-10-23 14:03:08 +0100684 inst = inst->Next_51l();
685 }
686
687 ALWAYS_INLINE void CONST_WIDE_HIGH16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100688 shadow_frame.SetVRegLong(A(),
David Srbeckyd6f579c2019-05-29 18:09:30 +0100689 static_cast<uint64_t>(B()) << 48);
David Srbecky6da82472018-10-23 14:03:08 +0100690 inst = inst->Next_2xx();
691 }
692
693 ALWAYS_INLINE void CONST_STRING() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100694 ObjPtr<mirror::String> s = ResolveString(self,
695 shadow_frame,
David Srbeckyd6f579c2019-05-29 18:09:30 +0100696 dex::StringIndex(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100697 if (UNLIKELY(s == nullptr)) {
698 HANDLE_PENDING_EXCEPTION();
699 } else {
David Srbecky436f6c12019-05-22 13:28:42 +0100700 shadow_frame.SetVRegReference(A(), s);
David Srbecky6da82472018-10-23 14:03:08 +0100701 inst = inst->Next_2xx();
702 }
703 }
704
705 ALWAYS_INLINE void CONST_STRING_JUMBO() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100706 ObjPtr<mirror::String> s = ResolveString(self,
707 shadow_frame,
David Srbeckyd6f579c2019-05-29 18:09:30 +0100708 dex::StringIndex(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100709 if (UNLIKELY(s == nullptr)) {
710 HANDLE_PENDING_EXCEPTION();
711 } else {
David Srbecky436f6c12019-05-22 13:28:42 +0100712 shadow_frame.SetVRegReference(A(), s);
David Srbecky6da82472018-10-23 14:03:08 +0100713 inst = inst->Next_3xx();
714 }
715 }
716
717 ALWAYS_INLINE void CONST_CLASS() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100718 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(B()),
David Srbecky6da82472018-10-23 14:03:08 +0100719 shadow_frame.GetMethod(),
720 self,
721 false,
722 do_access_check);
723 if (UNLIKELY(c == nullptr)) {
724 HANDLE_PENDING_EXCEPTION();
725 } else {
David Srbecky436f6c12019-05-22 13:28:42 +0100726 shadow_frame.SetVRegReference(A(), c);
David Srbecky6da82472018-10-23 14:03:08 +0100727 inst = inst->Next_2xx();
728 }
729 }
730
731 ALWAYS_INLINE void CONST_METHOD_HANDLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100732 ClassLinker* cl = Runtime::Current()->GetClassLinker();
733 ObjPtr<mirror::MethodHandle> mh = cl->ResolveMethodHandle(self,
David Srbeckyd6f579c2019-05-29 18:09:30 +0100734 B(),
David Srbecky6da82472018-10-23 14:03:08 +0100735 shadow_frame.GetMethod());
736 if (UNLIKELY(mh == nullptr)) {
737 HANDLE_PENDING_EXCEPTION();
738 } else {
David Srbecky436f6c12019-05-22 13:28:42 +0100739 shadow_frame.SetVRegReference(A(), mh);
David Srbecky6da82472018-10-23 14:03:08 +0100740 inst = inst->Next_2xx();
741 }
742 }
743
744 ALWAYS_INLINE void CONST_METHOD_TYPE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100745 ClassLinker* cl = Runtime::Current()->GetClassLinker();
746 ObjPtr<mirror::MethodType> mt = cl->ResolveMethodType(self,
David Srbeckyd6f579c2019-05-29 18:09:30 +0100747 dex::ProtoIndex(B()),
David Srbecky6da82472018-10-23 14:03:08 +0100748 shadow_frame.GetMethod());
749 if (UNLIKELY(mt == nullptr)) {
750 HANDLE_PENDING_EXCEPTION();
751 } else {
David Srbecky436f6c12019-05-22 13:28:42 +0100752 shadow_frame.SetVRegReference(A(), mt);
David Srbecky6da82472018-10-23 14:03:08 +0100753 inst = inst->Next_2xx();
754 }
755 }
756
757 ALWAYS_INLINE void MONITOR_ENTER() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000758 if (!HandleAsyncException()) {
759 return;
760 }
David Srbecky436f6c12019-05-22 13:28:42 +0100761 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +0100762 if (UNLIKELY(obj == nullptr)) {
763 ThrowNullPointerExceptionFromInterpreter();
764 HANDLE_PENDING_EXCEPTION();
765 } else {
766 DoMonitorEnter<do_assignability_check>(self, &shadow_frame, obj);
767 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
768 }
769 }
770
771 ALWAYS_INLINE void MONITOR_EXIT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000772 if (!HandleAsyncException()) {
773 return;
774 }
David Srbecky436f6c12019-05-22 13:28:42 +0100775 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +0100776 if (UNLIKELY(obj == nullptr)) {
777 ThrowNullPointerExceptionFromInterpreter();
778 HANDLE_PENDING_EXCEPTION();
779 } else {
780 DoMonitorExit<do_assignability_check>(self, &shadow_frame, obj);
781 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
782 }
783 }
784
785 ALWAYS_INLINE void CHECK_CAST() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100786 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(B()),
David Srbecky6da82472018-10-23 14:03:08 +0100787 shadow_frame.GetMethod(),
788 self,
789 false,
790 do_access_check);
791 if (UNLIKELY(c == nullptr)) {
792 HANDLE_PENDING_EXCEPTION();
793 } else {
David Srbecky436f6c12019-05-22 13:28:42 +0100794 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +0100795 if (UNLIKELY(obj != nullptr && !obj->InstanceOf(c))) {
796 ThrowClassCastException(c, obj->GetClass());
797 HANDLE_PENDING_EXCEPTION();
798 } else {
799 inst = inst->Next_2xx();
800 }
801 }
802 }
803
804 ALWAYS_INLINE void INSTANCE_OF() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100805 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(C()),
David Srbecky6da82472018-10-23 14:03:08 +0100806 shadow_frame.GetMethod(),
807 self,
808 false,
809 do_access_check);
810 if (UNLIKELY(c == nullptr)) {
811 HANDLE_PENDING_EXCEPTION();
812 } else {
David Srbecky436f6c12019-05-22 13:28:42 +0100813 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(B());
814 shadow_frame.SetVReg(A(),
David Srbecky6da82472018-10-23 14:03:08 +0100815 (obj != nullptr && obj->InstanceOf(c)) ? 1 : 0);
816 inst = inst->Next_2xx();
817 }
818 }
819
820 ALWAYS_INLINE void ARRAY_LENGTH() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100821 ObjPtr<mirror::Object> array = shadow_frame.GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +0100822 if (UNLIKELY(array == nullptr)) {
823 ThrowNullPointerExceptionFromInterpreter();
824 HANDLE_PENDING_EXCEPTION();
825 } else {
David Srbecky436f6c12019-05-22 13:28:42 +0100826 shadow_frame.SetVReg(A(), array->AsArray()->GetLength());
David Srbecky6da82472018-10-23 14:03:08 +0100827 inst = inst->Next_1xx();
828 }
829 }
830
831 ALWAYS_INLINE void NEW_INSTANCE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100832 ObjPtr<mirror::Object> obj = nullptr;
David Srbeckyd6f579c2019-05-29 18:09:30 +0100833 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(B()),
David Srbecky6da82472018-10-23 14:03:08 +0100834 shadow_frame.GetMethod(),
835 self,
836 false,
837 do_access_check);
838 if (LIKELY(c != nullptr)) {
Vladimir Marko9b81ac32019-05-16 16:47:08 +0100839 gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
David Srbecky6da82472018-10-23 14:03:08 +0100840 if (UNLIKELY(c->IsStringClass())) {
Vladimir Marko9b81ac32019-05-16 16:47:08 +0100841 obj = mirror::String::AllocEmptyString(self, allocator_type);
David Srbecky6da82472018-10-23 14:03:08 +0100842 } else {
Vladimir Marko9b81ac32019-05-16 16:47:08 +0100843 obj = AllocObjectFromCode(c, self, allocator_type);
David Srbecky6da82472018-10-23 14:03:08 +0100844 }
845 }
846 if (UNLIKELY(obj == nullptr)) {
847 HANDLE_PENDING_EXCEPTION();
848 } else {
849 obj->GetClass()->AssertInitializedOrInitializingInThread(self);
850 // Don't allow finalizable objects to be allocated during a transaction since these can't
851 // be finalized without a started runtime.
852 if (transaction_active && obj->GetClass()->IsFinalizable()) {
853 AbortTransactionF(self, "Allocating finalizable object in transaction: %s",
854 obj->PrettyTypeOf().c_str());
855 HANDLE_PENDING_EXCEPTION();
856 }
David Srbecky436f6c12019-05-22 13:28:42 +0100857 shadow_frame.SetVRegReference(A(), obj);
David Srbecky6da82472018-10-23 14:03:08 +0100858 inst = inst->Next_2xx();
859 }
860 }
861
862 ALWAYS_INLINE void NEW_ARRAY() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100863 int32_t length = shadow_frame.GetVReg(B());
Vladimir Marko9b81ac32019-05-16 16:47:08 +0100864 ObjPtr<mirror::Object> obj = AllocArrayFromCode<do_access_check>(
David Srbeckyd6f579c2019-05-29 18:09:30 +0100865 dex::TypeIndex(C()),
David Srbecky6da82472018-10-23 14:03:08 +0100866 length,
867 shadow_frame.GetMethod(),
868 self,
869 Runtime::Current()->GetHeap()->GetCurrentAllocator());
870 if (UNLIKELY(obj == nullptr)) {
871 HANDLE_PENDING_EXCEPTION();
872 } else {
David Srbecky436f6c12019-05-22 13:28:42 +0100873 shadow_frame.SetVRegReference(A(), obj);
David Srbecky6da82472018-10-23 14:03:08 +0100874 inst = inst->Next_2xx();
875 }
876 }
877
878 ALWAYS_INLINE void FILLED_NEW_ARRAY() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100879 bool success =
880 DoFilledNewArray<false, do_access_check, transaction_active>(inst, shadow_frame, self,
881 ResultRegister());
882 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
883 }
884
885 ALWAYS_INLINE void FILLED_NEW_ARRAY_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100886 bool success =
887 DoFilledNewArray<true, do_access_check, transaction_active>(inst, shadow_frame,
888 self, ResultRegister());
889 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
890 }
891
892 ALWAYS_INLINE void FILL_ARRAY_DATA() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100893 const uint16_t* payload_addr = reinterpret_cast<const uint16_t*>(inst) + B();
David Srbecky6da82472018-10-23 14:03:08 +0100894 const Instruction::ArrayDataPayload* payload =
895 reinterpret_cast<const Instruction::ArrayDataPayload*>(payload_addr);
David Srbecky436f6c12019-05-22 13:28:42 +0100896 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +0100897 bool success = FillArrayData(obj, payload);
898 if (!success) {
899 HANDLE_PENDING_EXCEPTION();
900 }
901 if (transaction_active) {
902 RecordArrayElementsInTransaction(obj->AsArray(), payload->element_count);
903 }
904 inst = inst->Next_3xx();
905 }
906
907 ALWAYS_INLINE void THROW() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000908 if (!HandleAsyncException()) {
909 return;
910 }
David Srbecky6da82472018-10-23 14:03:08 +0100911 ObjPtr<mirror::Object> exception =
David Srbecky436f6c12019-05-22 13:28:42 +0100912 shadow_frame.GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +0100913 if (UNLIKELY(exception == nullptr)) {
914 ThrowNullPointerException("throw with null exception");
915 } else if (do_assignability_check && !exception->GetClass()->IsThrowableClass()) {
916 // This should never happen.
917 std::string temp;
918 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
919 "Throwing '%s' that is not instance of Throwable",
920 exception->GetClass()->GetDescriptor(&temp));
921 } else {
922 self->SetException(exception->AsThrowable());
923 }
924 HANDLE_PENDING_EXCEPTION();
925 }
926
927 ALWAYS_INLINE void GOTO() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000928 if (!HandleAsyncException()) {
929 return;
930 }
David Srbeckyd6f579c2019-05-29 18:09:30 +0100931 int8_t offset = A();
David Srbecky6da82472018-10-23 14:03:08 +0100932 BRANCH_INSTRUMENTATION(offset);
933 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +0000934 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +0100935 }
936
937 ALWAYS_INLINE void GOTO_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000938 if (!HandleAsyncException()) {
939 return;
940 }
David Srbeckyd6f579c2019-05-29 18:09:30 +0100941 int16_t offset = A();
David Srbecky6da82472018-10-23 14:03:08 +0100942 BRANCH_INSTRUMENTATION(offset);
943 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +0000944 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +0100945 }
946
947 ALWAYS_INLINE void GOTO_32() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000948 if (!HandleAsyncException()) {
949 return;
950 }
David Srbeckyd6f579c2019-05-29 18:09:30 +0100951 int32_t offset = A();
David Srbecky6da82472018-10-23 14:03:08 +0100952 BRANCH_INSTRUMENTATION(offset);
953 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +0000954 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +0100955 }
956
957 ALWAYS_INLINE void PACKED_SWITCH() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100958 int32_t offset = DoPackedSwitch(inst, shadow_frame, inst_data);
959 BRANCH_INSTRUMENTATION(offset);
960 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +0000961 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +0100962 }
963
964 ALWAYS_INLINE void SPARSE_SWITCH() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100965 int32_t offset = DoSparseSwitch(inst, shadow_frame, inst_data);
966 BRANCH_INSTRUMENTATION(offset);
967 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +0000968 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +0100969 }
970
971#pragma clang diagnostic push
972#pragma clang diagnostic ignored "-Wfloat-equal"
973
974
975 ALWAYS_INLINE void CMPL_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100976 float val1 = shadow_frame.GetVRegFloat(B());
977 float val2 = shadow_frame.GetVRegFloat(C());
David Srbecky6da82472018-10-23 14:03:08 +0100978 int32_t result;
979 if (val1 > val2) {
980 result = 1;
981 } else if (val1 == val2) {
982 result = 0;
983 } else {
984 result = -1;
985 }
David Srbecky436f6c12019-05-22 13:28:42 +0100986 shadow_frame.SetVReg(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +0100987 inst = inst->Next_2xx();
988 }
989
990 ALWAYS_INLINE void CMPG_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +0100991 float val1 = shadow_frame.GetVRegFloat(B());
992 float val2 = shadow_frame.GetVRegFloat(C());
David Srbecky6da82472018-10-23 14:03:08 +0100993 int32_t result;
994 if (val1 < val2) {
995 result = -1;
996 } else if (val1 == val2) {
997 result = 0;
998 } else {
999 result = 1;
1000 }
David Srbecky436f6c12019-05-22 13:28:42 +01001001 shadow_frame.SetVReg(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +01001002 inst = inst->Next_2xx();
1003 }
1004
1005 ALWAYS_INLINE void CMPL_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001006 double val1 = shadow_frame.GetVRegDouble(B());
1007 double val2 = shadow_frame.GetVRegDouble(C());
David Srbecky6da82472018-10-23 14:03:08 +01001008 int32_t result;
1009 if (val1 > val2) {
1010 result = 1;
1011 } else if (val1 == val2) {
1012 result = 0;
1013 } else {
1014 result = -1;
1015 }
David Srbecky436f6c12019-05-22 13:28:42 +01001016 shadow_frame.SetVReg(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +01001017 inst = inst->Next_2xx();
1018 }
1019
1020
1021 ALWAYS_INLINE void CMPG_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001022 double val1 = shadow_frame.GetVRegDouble(B());
1023 double val2 = shadow_frame.GetVRegDouble(C());
David Srbecky6da82472018-10-23 14:03:08 +01001024 int32_t result;
1025 if (val1 < val2) {
1026 result = -1;
1027 } else if (val1 == val2) {
1028 result = 0;
1029 } else {
1030 result = 1;
1031 }
David Srbecky436f6c12019-05-22 13:28:42 +01001032 shadow_frame.SetVReg(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +01001033 inst = inst->Next_2xx();
1034 }
1035
1036#pragma clang diagnostic pop
1037
1038
1039 ALWAYS_INLINE void CMP_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001040 int64_t val1 = shadow_frame.GetVRegLong(B());
1041 int64_t val2 = shadow_frame.GetVRegLong(C());
David Srbecky6da82472018-10-23 14:03:08 +01001042 int32_t result;
1043 if (val1 > val2) {
1044 result = 1;
1045 } else if (val1 == val2) {
1046 result = 0;
1047 } else {
1048 result = -1;
1049 }
David Srbecky436f6c12019-05-22 13:28:42 +01001050 shadow_frame.SetVReg(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +01001051 inst = inst->Next_2xx();
1052 }
1053
1054 ALWAYS_INLINE void IF_EQ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001055 if (shadow_frame.GetVReg(A()) ==
1056 shadow_frame.GetVReg(B())) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001057 int16_t offset = C();
David Srbecky6da82472018-10-23 14:03:08 +01001058 BRANCH_INSTRUMENTATION(offset);
1059 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001060 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001061 } else {
1062 BRANCH_INSTRUMENTATION(2);
1063 inst = inst->Next_2xx();
1064 }
1065 }
1066
1067 ALWAYS_INLINE void IF_NE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001068 if (shadow_frame.GetVReg(A()) !=
1069 shadow_frame.GetVReg(B())) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001070 int16_t offset = C();
David Srbecky6da82472018-10-23 14:03:08 +01001071 BRANCH_INSTRUMENTATION(offset);
1072 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001073 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001074 } else {
1075 BRANCH_INSTRUMENTATION(2);
1076 inst = inst->Next_2xx();
1077 }
1078 }
1079
1080 ALWAYS_INLINE void IF_LT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001081 if (shadow_frame.GetVReg(A()) <
1082 shadow_frame.GetVReg(B())) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001083 int16_t offset = C();
David Srbecky6da82472018-10-23 14:03:08 +01001084 BRANCH_INSTRUMENTATION(offset);
1085 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001086 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001087 } else {
1088 BRANCH_INSTRUMENTATION(2);
1089 inst = inst->Next_2xx();
1090 }
1091 }
1092
1093 ALWAYS_INLINE void IF_GE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001094 if (shadow_frame.GetVReg(A()) >=
1095 shadow_frame.GetVReg(B())) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001096 int16_t offset = C();
David Srbecky6da82472018-10-23 14:03:08 +01001097 BRANCH_INSTRUMENTATION(offset);
1098 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001099 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001100 } else {
1101 BRANCH_INSTRUMENTATION(2);
1102 inst = inst->Next_2xx();
1103 }
1104 }
1105
1106 ALWAYS_INLINE void IF_GT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001107 if (shadow_frame.GetVReg(A()) >
1108 shadow_frame.GetVReg(B())) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001109 int16_t offset = C();
David Srbecky6da82472018-10-23 14:03:08 +01001110 BRANCH_INSTRUMENTATION(offset);
1111 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001112 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001113 } else {
1114 BRANCH_INSTRUMENTATION(2);
1115 inst = inst->Next_2xx();
1116 }
1117 }
1118
1119 ALWAYS_INLINE void IF_LE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001120 if (shadow_frame.GetVReg(A()) <=
1121 shadow_frame.GetVReg(B())) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001122 int16_t offset = C();
David Srbecky6da82472018-10-23 14:03:08 +01001123 BRANCH_INSTRUMENTATION(offset);
1124 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001125 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001126 } else {
1127 BRANCH_INSTRUMENTATION(2);
1128 inst = inst->Next_2xx();
1129 }
1130 }
1131
1132 ALWAYS_INLINE void IF_EQZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001133 if (shadow_frame.GetVReg(A()) == 0) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001134 int16_t offset = B();
David Srbecky6da82472018-10-23 14:03:08 +01001135 BRANCH_INSTRUMENTATION(offset);
1136 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001137 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001138 } else {
1139 BRANCH_INSTRUMENTATION(2);
1140 inst = inst->Next_2xx();
1141 }
1142 }
1143
1144 ALWAYS_INLINE void IF_NEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001145 if (shadow_frame.GetVReg(A()) != 0) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001146 int16_t offset = B();
David Srbecky6da82472018-10-23 14:03:08 +01001147 BRANCH_INSTRUMENTATION(offset);
1148 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001149 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001150 } else {
1151 BRANCH_INSTRUMENTATION(2);
1152 inst = inst->Next_2xx();
1153 }
1154 }
1155
1156 ALWAYS_INLINE void IF_LTZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001157 if (shadow_frame.GetVReg(A()) < 0) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001158 int16_t offset = B();
David Srbecky6da82472018-10-23 14:03:08 +01001159 BRANCH_INSTRUMENTATION(offset);
1160 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001161 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001162 } else {
1163 BRANCH_INSTRUMENTATION(2);
1164 inst = inst->Next_2xx();
1165 }
1166 }
1167
1168 ALWAYS_INLINE void IF_GEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001169 if (shadow_frame.GetVReg(A()) >= 0) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001170 int16_t offset = B();
David Srbecky6da82472018-10-23 14:03:08 +01001171 BRANCH_INSTRUMENTATION(offset);
1172 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001173 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001174 } else {
1175 BRANCH_INSTRUMENTATION(2);
1176 inst = inst->Next_2xx();
1177 }
1178 }
1179
1180 ALWAYS_INLINE void IF_GTZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001181 if (shadow_frame.GetVReg(A()) > 0) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001182 int16_t offset = B();
David Srbecky6da82472018-10-23 14:03:08 +01001183 BRANCH_INSTRUMENTATION(offset);
1184 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001185 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001186 } else {
1187 BRANCH_INSTRUMENTATION(2);
1188 inst = inst->Next_2xx();
1189 }
1190 }
1191
1192 ALWAYS_INLINE void IF_LEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001193 if (shadow_frame.GetVReg(A()) <= 0) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001194 int16_t offset = B();
David Srbecky6da82472018-10-23 14:03:08 +01001195 BRANCH_INSTRUMENTATION(offset);
1196 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001197 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001198 } else {
1199 BRANCH_INSTRUMENTATION(2);
1200 inst = inst->Next_2xx();
1201 }
1202 }
1203
1204 ALWAYS_INLINE void AGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001205 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001206 if (UNLIKELY(a == nullptr)) {
1207 ThrowNullPointerExceptionFromInterpreter();
1208 HANDLE_PENDING_EXCEPTION();
1209 }
David Srbecky436f6c12019-05-22 13:28:42 +01001210 int32_t index = shadow_frame.GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001211 ObjPtr<mirror::BooleanArray> array = a->AsBooleanArray();
1212 if (array->CheckIsValidIndex(index)) {
David Srbecky436f6c12019-05-22 13:28:42 +01001213 shadow_frame.SetVReg(A(), array->GetWithoutChecks(index));
David Srbecky6da82472018-10-23 14:03:08 +01001214 inst = inst->Next_2xx();
1215 } else {
1216 HANDLE_PENDING_EXCEPTION();
1217 }
1218 }
1219
1220 ALWAYS_INLINE void AGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001221 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001222 if (UNLIKELY(a == nullptr)) {
1223 ThrowNullPointerExceptionFromInterpreter();
1224 HANDLE_PENDING_EXCEPTION();
1225 }
David Srbecky436f6c12019-05-22 13:28:42 +01001226 int32_t index = shadow_frame.GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001227 ObjPtr<mirror::ByteArray> array = a->AsByteArray();
1228 if (array->CheckIsValidIndex(index)) {
David Srbecky436f6c12019-05-22 13:28:42 +01001229 shadow_frame.SetVReg(A(), array->GetWithoutChecks(index));
David Srbecky6da82472018-10-23 14:03:08 +01001230 inst = inst->Next_2xx();
1231 } else {
1232 HANDLE_PENDING_EXCEPTION();
1233 }
1234 }
1235
1236 ALWAYS_INLINE void AGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001237 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001238 if (UNLIKELY(a == nullptr)) {
1239 ThrowNullPointerExceptionFromInterpreter();
1240 HANDLE_PENDING_EXCEPTION();
1241 }
David Srbecky436f6c12019-05-22 13:28:42 +01001242 int32_t index = shadow_frame.GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001243 ObjPtr<mirror::CharArray> array = a->AsCharArray();
1244 if (array->CheckIsValidIndex(index)) {
David Srbecky436f6c12019-05-22 13:28:42 +01001245 shadow_frame.SetVReg(A(), array->GetWithoutChecks(index));
David Srbecky6da82472018-10-23 14:03:08 +01001246 inst = inst->Next_2xx();
1247 } else {
1248 HANDLE_PENDING_EXCEPTION();
1249 }
1250 }
1251
1252 ALWAYS_INLINE void AGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001253 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001254 if (UNLIKELY(a == nullptr)) {
1255 ThrowNullPointerExceptionFromInterpreter();
1256 HANDLE_PENDING_EXCEPTION();
1257 }
David Srbecky436f6c12019-05-22 13:28:42 +01001258 int32_t index = shadow_frame.GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001259 ObjPtr<mirror::ShortArray> array = a->AsShortArray();
1260 if (array->CheckIsValidIndex(index)) {
David Srbecky436f6c12019-05-22 13:28:42 +01001261 shadow_frame.SetVReg(A(), array->GetWithoutChecks(index));
David Srbecky6da82472018-10-23 14:03:08 +01001262 inst = inst->Next_2xx();
1263 } else {
1264 HANDLE_PENDING_EXCEPTION();
1265 }
1266 }
1267
1268 ALWAYS_INLINE void AGET() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001269 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001270 if (UNLIKELY(a == nullptr)) {
1271 ThrowNullPointerExceptionFromInterpreter();
1272 HANDLE_PENDING_EXCEPTION();
1273 }
David Srbecky436f6c12019-05-22 13:28:42 +01001274 int32_t index = shadow_frame.GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001275 DCHECK(a->IsIntArray() || a->IsFloatArray()) << a->PrettyTypeOf();
1276 ObjPtr<mirror::IntArray> array = ObjPtr<mirror::IntArray>::DownCast(a);
1277 if (array->CheckIsValidIndex(index)) {
David Srbecky436f6c12019-05-22 13:28:42 +01001278 shadow_frame.SetVReg(A(), array->GetWithoutChecks(index));
David Srbecky6da82472018-10-23 14:03:08 +01001279 inst = inst->Next_2xx();
1280 } else {
1281 HANDLE_PENDING_EXCEPTION();
1282 }
1283 }
1284
1285 ALWAYS_INLINE void AGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001286 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001287 if (UNLIKELY(a == nullptr)) {
1288 ThrowNullPointerExceptionFromInterpreter();
1289 HANDLE_PENDING_EXCEPTION();
1290 }
David Srbecky436f6c12019-05-22 13:28:42 +01001291 int32_t index = shadow_frame.GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001292 DCHECK(a->IsLongArray() || a->IsDoubleArray()) << a->PrettyTypeOf();
1293 ObjPtr<mirror::LongArray> array = ObjPtr<mirror::LongArray>::DownCast(a);
1294 if (array->CheckIsValidIndex(index)) {
David Srbecky436f6c12019-05-22 13:28:42 +01001295 shadow_frame.SetVRegLong(A(), array->GetWithoutChecks(index));
David Srbecky6da82472018-10-23 14:03:08 +01001296 inst = inst->Next_2xx();
1297 } else {
1298 HANDLE_PENDING_EXCEPTION();
1299 }
1300 }
1301
1302 ALWAYS_INLINE void AGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001303 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001304 if (UNLIKELY(a == nullptr)) {
1305 ThrowNullPointerExceptionFromInterpreter();
1306 HANDLE_PENDING_EXCEPTION();
1307 }
David Srbecky436f6c12019-05-22 13:28:42 +01001308 int32_t index = shadow_frame.GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001309 ObjPtr<mirror::ObjectArray<mirror::Object>> array = a->AsObjectArray<mirror::Object>();
1310 if (array->CheckIsValidIndex(index)) {
David Srbecky436f6c12019-05-22 13:28:42 +01001311 shadow_frame.SetVRegReference(A(), array->GetWithoutChecks(index));
David Srbecky6da82472018-10-23 14:03:08 +01001312 inst = inst->Next_2xx();
1313 } else {
1314 HANDLE_PENDING_EXCEPTION();
1315 }
1316 }
1317
1318 ALWAYS_INLINE void APUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001319 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001320 if (UNLIKELY(a == nullptr)) {
1321 ThrowNullPointerExceptionFromInterpreter();
1322 HANDLE_PENDING_EXCEPTION();
1323 }
David Srbecky436f6c12019-05-22 13:28:42 +01001324 uint8_t val = shadow_frame.GetVReg(A());
1325 int32_t index = shadow_frame.GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001326 ObjPtr<mirror::BooleanArray> array = a->AsBooleanArray();
1327 if (array->CheckIsValidIndex(index)) {
1328 array->SetWithoutChecks<transaction_active>(index, val);
1329 inst = inst->Next_2xx();
1330 } else {
1331 HANDLE_PENDING_EXCEPTION();
1332 }
1333 }
1334
1335 ALWAYS_INLINE void APUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001336 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001337 if (UNLIKELY(a == nullptr)) {
1338 ThrowNullPointerExceptionFromInterpreter();
1339 HANDLE_PENDING_EXCEPTION();
1340 }
David Srbecky436f6c12019-05-22 13:28:42 +01001341 int8_t val = shadow_frame.GetVReg(A());
1342 int32_t index = shadow_frame.GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001343 ObjPtr<mirror::ByteArray> array = a->AsByteArray();
1344 if (array->CheckIsValidIndex(index)) {
1345 array->SetWithoutChecks<transaction_active>(index, val);
1346 inst = inst->Next_2xx();
1347 } else {
1348 HANDLE_PENDING_EXCEPTION();
1349 }
1350 }
1351
1352 ALWAYS_INLINE void APUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001353 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001354 if (UNLIKELY(a == nullptr)) {
1355 ThrowNullPointerExceptionFromInterpreter();
1356 HANDLE_PENDING_EXCEPTION();
1357 }
David Srbecky436f6c12019-05-22 13:28:42 +01001358 uint16_t val = shadow_frame.GetVReg(A());
1359 int32_t index = shadow_frame.GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001360 ObjPtr<mirror::CharArray> array = a->AsCharArray();
1361 if (array->CheckIsValidIndex(index)) {
1362 array->SetWithoutChecks<transaction_active>(index, val);
1363 inst = inst->Next_2xx();
1364 } else {
1365 HANDLE_PENDING_EXCEPTION();
1366 }
1367 }
1368
1369 ALWAYS_INLINE void APUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001370 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001371 if (UNLIKELY(a == nullptr)) {
1372 ThrowNullPointerExceptionFromInterpreter();
1373 HANDLE_PENDING_EXCEPTION();
1374 }
David Srbecky436f6c12019-05-22 13:28:42 +01001375 int16_t val = shadow_frame.GetVReg(A());
1376 int32_t index = shadow_frame.GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001377 ObjPtr<mirror::ShortArray> array = a->AsShortArray();
1378 if (array->CheckIsValidIndex(index)) {
1379 array->SetWithoutChecks<transaction_active>(index, val);
1380 inst = inst->Next_2xx();
1381 } else {
1382 HANDLE_PENDING_EXCEPTION();
1383 }
1384 }
1385
1386 ALWAYS_INLINE void APUT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001387 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001388 if (UNLIKELY(a == nullptr)) {
1389 ThrowNullPointerExceptionFromInterpreter();
1390 HANDLE_PENDING_EXCEPTION();
1391 }
David Srbecky436f6c12019-05-22 13:28:42 +01001392 int32_t val = shadow_frame.GetVReg(A());
1393 int32_t index = shadow_frame.GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001394 DCHECK(a->IsIntArray() || a->IsFloatArray()) << a->PrettyTypeOf();
1395 ObjPtr<mirror::IntArray> array = ObjPtr<mirror::IntArray>::DownCast(a);
1396 if (array->CheckIsValidIndex(index)) {
1397 array->SetWithoutChecks<transaction_active>(index, val);
1398 inst = inst->Next_2xx();
1399 } else {
1400 HANDLE_PENDING_EXCEPTION();
1401 }
1402 }
1403
1404 ALWAYS_INLINE void APUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001405 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001406 if (UNLIKELY(a == nullptr)) {
1407 ThrowNullPointerExceptionFromInterpreter();
1408 HANDLE_PENDING_EXCEPTION();
1409 }
David Srbecky436f6c12019-05-22 13:28:42 +01001410 int64_t val = shadow_frame.GetVRegLong(A());
1411 int32_t index = shadow_frame.GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001412 DCHECK(a->IsLongArray() || a->IsDoubleArray()) << a->PrettyTypeOf();
1413 ObjPtr<mirror::LongArray> array = ObjPtr<mirror::LongArray>::DownCast(a);
1414 if (array->CheckIsValidIndex(index)) {
1415 array->SetWithoutChecks<transaction_active>(index, val);
1416 inst = inst->Next_2xx();
1417 } else {
1418 HANDLE_PENDING_EXCEPTION();
1419 }
1420 }
1421
1422 ALWAYS_INLINE void APUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001423 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001424 if (UNLIKELY(a == nullptr)) {
1425 ThrowNullPointerExceptionFromInterpreter();
1426 HANDLE_PENDING_EXCEPTION();
1427 }
David Srbecky436f6c12019-05-22 13:28:42 +01001428 int32_t index = shadow_frame.GetVReg(C());
1429 ObjPtr<mirror::Object> val = shadow_frame.GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +01001430 ObjPtr<mirror::ObjectArray<mirror::Object>> array = a->AsObjectArray<mirror::Object>();
1431 if (array->CheckIsValidIndex(index) && array->CheckAssignable(val)) {
1432 array->SetWithoutChecks<transaction_active>(index, val);
1433 inst = inst->Next_2xx();
1434 } else {
1435 HANDLE_PENDING_EXCEPTION();
1436 }
1437 }
1438
1439 ALWAYS_INLINE void IGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001440 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimBoolean, do_access_check>(
1441 self, shadow_frame, inst, inst_data);
1442 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1443 }
1444
1445 ALWAYS_INLINE void IGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001446 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimByte, do_access_check>(
1447 self, shadow_frame, inst, inst_data);
1448 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1449 }
1450
1451 ALWAYS_INLINE void IGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001452 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimChar, do_access_check>(
1453 self, shadow_frame, inst, inst_data);
1454 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1455 }
1456
1457 ALWAYS_INLINE void IGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001458 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimShort, do_access_check>(
1459 self, shadow_frame, inst, inst_data);
1460 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1461 }
1462
1463 ALWAYS_INLINE void IGET() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001464 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimInt, do_access_check>(
1465 self, shadow_frame, inst, inst_data);
1466 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1467 }
1468
1469 ALWAYS_INLINE void IGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001470 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimLong, do_access_check>(
1471 self, shadow_frame, inst, inst_data);
1472 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1473 }
1474
1475 ALWAYS_INLINE void IGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001476 bool success = DoFieldGet<InstanceObjectRead, Primitive::kPrimNot, do_access_check>(
1477 self, shadow_frame, inst, inst_data);
1478 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1479 }
1480
1481 ALWAYS_INLINE void IGET_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001482 bool success = DoIGetQuick<Primitive::kPrimInt>(shadow_frame, inst, inst_data);
1483 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1484 }
1485
1486 ALWAYS_INLINE void IGET_WIDE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001487 bool success = DoIGetQuick<Primitive::kPrimLong>(shadow_frame, inst, inst_data);
1488 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1489 }
1490
1491 ALWAYS_INLINE void IGET_OBJECT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001492 bool success = DoIGetQuick<Primitive::kPrimNot>(shadow_frame, inst, inst_data);
1493 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1494 }
1495
1496 ALWAYS_INLINE void IGET_BOOLEAN_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001497 bool success = DoIGetQuick<Primitive::kPrimBoolean>(shadow_frame, inst, inst_data);
1498 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1499 }
1500
1501 ALWAYS_INLINE void IGET_BYTE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001502 bool success = DoIGetQuick<Primitive::kPrimByte>(shadow_frame, inst, inst_data);
1503 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1504 }
1505
1506 ALWAYS_INLINE void IGET_CHAR_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001507 bool success = DoIGetQuick<Primitive::kPrimChar>(shadow_frame, inst, inst_data);
1508 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1509 }
1510
1511 ALWAYS_INLINE void IGET_SHORT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001512 bool success = DoIGetQuick<Primitive::kPrimShort>(shadow_frame, inst, inst_data);
1513 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1514 }
1515
1516 ALWAYS_INLINE void SGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001517 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimBoolean, do_access_check,
1518 transaction_active>(self, shadow_frame, inst, inst_data);
1519 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1520 }
1521
1522 ALWAYS_INLINE void SGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001523 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimByte, do_access_check,
1524 transaction_active>(self, shadow_frame, inst, inst_data);
1525 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1526 }
1527
1528 ALWAYS_INLINE void SGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001529 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimChar, do_access_check,
1530 transaction_active>(self, shadow_frame, inst, inst_data);
1531 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1532 }
1533
1534 ALWAYS_INLINE void SGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001535 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimShort, do_access_check,
1536 transaction_active>(self, shadow_frame, inst, inst_data);
1537 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1538 }
1539
1540 ALWAYS_INLINE void SGET() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001541 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimInt, do_access_check,
1542 transaction_active>(self, shadow_frame, inst, inst_data);
1543 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1544 }
1545
1546 ALWAYS_INLINE void SGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001547 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimLong, do_access_check,
1548 transaction_active>(self, shadow_frame, inst, inst_data);
1549 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1550 }
1551
1552 ALWAYS_INLINE void SGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001553 bool success = DoFieldGet<StaticObjectRead, Primitive::kPrimNot, do_access_check,
1554 transaction_active>(self, shadow_frame, inst, inst_data);
1555 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1556 }
1557
1558 ALWAYS_INLINE void IPUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001559 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimBoolean, do_access_check,
1560 transaction_active>(self, shadow_frame, inst, inst_data);
1561 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1562 }
1563
1564 ALWAYS_INLINE void IPUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001565 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimByte, do_access_check,
1566 transaction_active>(self, shadow_frame, inst, inst_data);
1567 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1568 }
1569
1570 ALWAYS_INLINE void IPUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001571 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimChar, do_access_check,
1572 transaction_active>(self, shadow_frame, inst, inst_data);
1573 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1574 }
1575
1576 ALWAYS_INLINE void IPUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001577 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimShort, do_access_check,
1578 transaction_active>(self, shadow_frame, inst, inst_data);
1579 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1580 }
1581
1582 ALWAYS_INLINE void IPUT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001583 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimInt, do_access_check,
1584 transaction_active>(self, shadow_frame, inst, inst_data);
1585 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1586 }
1587
1588 ALWAYS_INLINE void IPUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001589 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimLong, do_access_check,
1590 transaction_active>(self, shadow_frame, inst, inst_data);
1591 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1592 }
1593
1594 ALWAYS_INLINE void IPUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001595 bool success = DoFieldPut<InstanceObjectWrite, Primitive::kPrimNot, do_access_check,
1596 transaction_active>(self, shadow_frame, inst, inst_data);
1597 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1598 }
1599
1600 ALWAYS_INLINE void IPUT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001601 bool success = DoIPutQuick<Primitive::kPrimInt, transaction_active>(
1602 shadow_frame, inst, inst_data);
1603 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1604 }
1605
1606 ALWAYS_INLINE void IPUT_BOOLEAN_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001607 bool success = DoIPutQuick<Primitive::kPrimBoolean, transaction_active>(
1608 shadow_frame, inst, inst_data);
1609 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1610 }
1611
1612 ALWAYS_INLINE void IPUT_BYTE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001613 bool success = DoIPutQuick<Primitive::kPrimByte, transaction_active>(
1614 shadow_frame, inst, inst_data);
1615 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1616 }
1617
1618 ALWAYS_INLINE void IPUT_CHAR_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001619 bool success = DoIPutQuick<Primitive::kPrimChar, transaction_active>(
1620 shadow_frame, inst, inst_data);
1621 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1622 }
1623
1624 ALWAYS_INLINE void IPUT_SHORT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001625 bool success = DoIPutQuick<Primitive::kPrimShort, transaction_active>(
1626 shadow_frame, inst, inst_data);
1627 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1628 }
1629
1630 ALWAYS_INLINE void IPUT_WIDE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001631 bool success = DoIPutQuick<Primitive::kPrimLong, transaction_active>(
1632 shadow_frame, inst, inst_data);
1633 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1634 }
1635
1636 ALWAYS_INLINE void IPUT_OBJECT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001637 bool success = DoIPutQuick<Primitive::kPrimNot, transaction_active>(
1638 shadow_frame, inst, inst_data);
1639 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1640 }
1641
1642 ALWAYS_INLINE void SPUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001643 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimBoolean, do_access_check,
1644 transaction_active>(self, shadow_frame, inst, inst_data);
1645 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1646 }
1647
1648 ALWAYS_INLINE void SPUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001649 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimByte, do_access_check,
1650 transaction_active>(self, shadow_frame, inst, inst_data);
1651 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1652 }
1653
1654 ALWAYS_INLINE void SPUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001655 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimChar, do_access_check,
1656 transaction_active>(self, shadow_frame, inst, inst_data);
1657 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1658 }
1659
1660 ALWAYS_INLINE void SPUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001661 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimShort, do_access_check,
1662 transaction_active>(self, shadow_frame, inst, inst_data);
1663 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1664 }
1665
1666 ALWAYS_INLINE void SPUT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001667 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimInt, do_access_check,
1668 transaction_active>(self, shadow_frame, inst, inst_data);
1669 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1670 }
1671
1672 ALWAYS_INLINE void SPUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001673 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimLong, do_access_check,
1674 transaction_active>(self, shadow_frame, inst, inst_data);
1675 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1676 }
1677
1678 ALWAYS_INLINE void SPUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001679 bool success = DoFieldPut<StaticObjectWrite, Primitive::kPrimNot, do_access_check,
1680 transaction_active>(self, shadow_frame, inst, inst_data);
1681 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1682 }
1683
1684 ALWAYS_INLINE void INVOKE_VIRTUAL() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001685 bool success = DoInvoke<kVirtual, false, do_access_check, /*is_mterp=*/ false>(
1686 self, shadow_frame, inst, inst_data, ResultRegister());
1687 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1688 }
1689
1690 ALWAYS_INLINE void INVOKE_VIRTUAL_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001691 bool success = DoInvoke<kVirtual, true, do_access_check, /*is_mterp=*/ false>(
1692 self, shadow_frame, inst, inst_data, ResultRegister());
1693 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1694 }
1695
1696 ALWAYS_INLINE void INVOKE_SUPER() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001697 bool success = DoInvoke<kSuper, false, do_access_check, /*is_mterp=*/ false>(
1698 self, shadow_frame, inst, inst_data, ResultRegister());
1699 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1700 }
1701
1702 ALWAYS_INLINE void INVOKE_SUPER_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001703 bool success = DoInvoke<kSuper, true, do_access_check, /*is_mterp=*/ false>(
1704 self, shadow_frame, inst, inst_data, ResultRegister());
1705 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1706 }
1707
1708 ALWAYS_INLINE void INVOKE_DIRECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001709 bool success = DoInvoke<kDirect, false, do_access_check, /*is_mterp=*/ false>(
1710 self, shadow_frame, inst, inst_data, ResultRegister());
1711 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1712 }
1713
1714 ALWAYS_INLINE void INVOKE_DIRECT_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001715 bool success = DoInvoke<kDirect, true, do_access_check, /*is_mterp=*/ false>(
1716 self, shadow_frame, inst, inst_data, ResultRegister());
1717 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1718 }
1719
1720 ALWAYS_INLINE void INVOKE_INTERFACE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001721 bool success = DoInvoke<kInterface, false, do_access_check, /*is_mterp=*/ false>(
1722 self, shadow_frame, inst, inst_data, ResultRegister());
1723 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1724 }
1725
1726 ALWAYS_INLINE void INVOKE_INTERFACE_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001727 bool success = DoInvoke<kInterface, true, do_access_check, /*is_mterp=*/ false>(
1728 self, shadow_frame, inst, inst_data, ResultRegister());
1729 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1730 }
1731
1732 ALWAYS_INLINE void INVOKE_STATIC() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001733 bool success = DoInvoke<kStatic, false, do_access_check, /*is_mterp=*/ false>(
1734 self, shadow_frame, inst, inst_data, ResultRegister());
1735 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1736 }
1737
1738 ALWAYS_INLINE void INVOKE_STATIC_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001739 bool success = DoInvoke<kStatic, true, do_access_check, /*is_mterp=*/ false>(
1740 self, shadow_frame, inst, inst_data, ResultRegister());
1741 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1742 }
1743
1744 ALWAYS_INLINE void INVOKE_VIRTUAL_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001745 bool success = DoInvoke<kVirtual, false, do_access_check, /*is_mterp=*/ false,
1746 /*is_quick=*/ true>(self, shadow_frame, inst, inst_data, ResultRegister());
1747 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1748 }
1749
1750 ALWAYS_INLINE void INVOKE_VIRTUAL_RANGE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001751 bool success = DoInvoke<kVirtual, true, do_access_check, /*is_mterp=*/ false,
1752 /*is_quick=*/ true>(self, shadow_frame, inst, inst_data, ResultRegister());
1753 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1754 }
1755
1756 ALWAYS_INLINE void INVOKE_POLYMORPHIC() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001757 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1758 bool success = DoInvokePolymorphic</* is_range= */ false>(
1759 self, shadow_frame, inst, inst_data, ResultRegister());
1760 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(!success);
1761 }
1762
1763 ALWAYS_INLINE void INVOKE_POLYMORPHIC_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001764 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1765 bool success = DoInvokePolymorphic</* is_range= */ true>(
1766 self, shadow_frame, inst, inst_data, ResultRegister());
1767 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(!success);
1768 }
1769
1770 ALWAYS_INLINE void INVOKE_CUSTOM() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001771 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1772 bool success = DoInvokeCustom</* is_range= */ false>(
1773 self, shadow_frame, inst, inst_data, ResultRegister());
1774 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1775 }
1776
1777 ALWAYS_INLINE void INVOKE_CUSTOM_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001778 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1779 bool success = DoInvokeCustom</* is_range= */ true>(
1780 self, shadow_frame, inst, inst_data, ResultRegister());
1781 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1782 }
1783
1784 ALWAYS_INLINE void NEG_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001785 shadow_frame.SetVReg(
David Srbeckyd6f579c2019-05-29 18:09:30 +01001786 A(), -shadow_frame.GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001787 inst = inst->Next_1xx();
1788 }
1789
1790 ALWAYS_INLINE void NOT_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001791 shadow_frame.SetVReg(
David Srbeckyd6f579c2019-05-29 18:09:30 +01001792 A(), ~shadow_frame.GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001793 inst = inst->Next_1xx();
1794 }
1795
1796 ALWAYS_INLINE void NEG_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001797 shadow_frame.SetVRegLong(
David Srbeckyd6f579c2019-05-29 18:09:30 +01001798 A(), -shadow_frame.GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001799 inst = inst->Next_1xx();
1800 }
1801
1802 ALWAYS_INLINE void NOT_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001803 shadow_frame.SetVRegLong(
David Srbeckyd6f579c2019-05-29 18:09:30 +01001804 A(), ~shadow_frame.GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001805 inst = inst->Next_1xx();
1806 }
1807
1808 ALWAYS_INLINE void NEG_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001809 shadow_frame.SetVRegFloat(
David Srbeckyd6f579c2019-05-29 18:09:30 +01001810 A(), -shadow_frame.GetVRegFloat(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001811 inst = inst->Next_1xx();
1812 }
1813
1814 ALWAYS_INLINE void NEG_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001815 shadow_frame.SetVRegDouble(
David Srbeckyd6f579c2019-05-29 18:09:30 +01001816 A(), -shadow_frame.GetVRegDouble(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001817 inst = inst->Next_1xx();
1818 }
1819
1820 ALWAYS_INLINE void INT_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001821 shadow_frame.SetVRegLong(A(),
1822 shadow_frame.GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001823 inst = inst->Next_1xx();
1824 }
1825
1826 ALWAYS_INLINE void INT_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001827 shadow_frame.SetVRegFloat(A(),
1828 shadow_frame.GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001829 inst = inst->Next_1xx();
1830 }
1831
1832 ALWAYS_INLINE void INT_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001833 shadow_frame.SetVRegDouble(A(),
1834 shadow_frame.GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001835 inst = inst->Next_1xx();
1836 }
1837
1838 ALWAYS_INLINE void LONG_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001839 shadow_frame.SetVReg(A(),
1840 shadow_frame.GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001841 inst = inst->Next_1xx();
1842 }
1843
1844 ALWAYS_INLINE void LONG_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001845 shadow_frame.SetVRegFloat(A(),
1846 shadow_frame.GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001847 inst = inst->Next_1xx();
1848 }
1849
1850 ALWAYS_INLINE void LONG_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001851 shadow_frame.SetVRegDouble(A(),
1852 shadow_frame.GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001853 inst = inst->Next_1xx();
1854 }
1855
1856 ALWAYS_INLINE void FLOAT_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001857 float val = shadow_frame.GetVRegFloat(B());
David Srbecky6da82472018-10-23 14:03:08 +01001858 int32_t result = art_float_to_integral<int32_t, float>(val);
David Srbecky436f6c12019-05-22 13:28:42 +01001859 shadow_frame.SetVReg(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +01001860 inst = inst->Next_1xx();
1861 }
1862
1863 ALWAYS_INLINE void FLOAT_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001864 float val = shadow_frame.GetVRegFloat(B());
David Srbecky6da82472018-10-23 14:03:08 +01001865 int64_t result = art_float_to_integral<int64_t, float>(val);
David Srbecky436f6c12019-05-22 13:28:42 +01001866 shadow_frame.SetVRegLong(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +01001867 inst = inst->Next_1xx();
1868 }
1869
1870 ALWAYS_INLINE void FLOAT_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001871 shadow_frame.SetVRegDouble(A(),
1872 shadow_frame.GetVRegFloat(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001873 inst = inst->Next_1xx();
1874 }
1875
1876 ALWAYS_INLINE void DOUBLE_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001877 double val = shadow_frame.GetVRegDouble(B());
David Srbecky6da82472018-10-23 14:03:08 +01001878 int32_t result = art_float_to_integral<int32_t, double>(val);
David Srbecky436f6c12019-05-22 13:28:42 +01001879 shadow_frame.SetVReg(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +01001880 inst = inst->Next_1xx();
1881 }
1882
1883 ALWAYS_INLINE void DOUBLE_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001884 double val = shadow_frame.GetVRegDouble(B());
David Srbecky6da82472018-10-23 14:03:08 +01001885 int64_t result = art_float_to_integral<int64_t, double>(val);
David Srbecky436f6c12019-05-22 13:28:42 +01001886 shadow_frame.SetVRegLong(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +01001887 inst = inst->Next_1xx();
1888 }
1889
1890 ALWAYS_INLINE void DOUBLE_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001891 shadow_frame.SetVRegFloat(A(),
1892 shadow_frame.GetVRegDouble(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001893 inst = inst->Next_1xx();
1894 }
1895
1896 ALWAYS_INLINE void INT_TO_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001897 shadow_frame.SetVReg(A(), static_cast<int8_t>(
1898 shadow_frame.GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01001899 inst = inst->Next_1xx();
1900 }
1901
1902 ALWAYS_INLINE void INT_TO_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001903 shadow_frame.SetVReg(A(), static_cast<uint16_t>(
1904 shadow_frame.GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01001905 inst = inst->Next_1xx();
1906 }
1907
1908 ALWAYS_INLINE void INT_TO_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001909 shadow_frame.SetVReg(A(), static_cast<int16_t>(
1910 shadow_frame.GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01001911 inst = inst->Next_1xx();
1912 }
1913
1914 ALWAYS_INLINE void ADD_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001915 shadow_frame.SetVReg(A(),
1916 SafeAdd(shadow_frame.GetVReg(B()),
1917 shadow_frame.GetVReg(C())));
David Srbecky6da82472018-10-23 14:03:08 +01001918 inst = inst->Next_2xx();
1919 }
1920
1921 ALWAYS_INLINE void SUB_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001922 shadow_frame.SetVReg(A(),
1923 SafeSub(shadow_frame.GetVReg(B()),
1924 shadow_frame.GetVReg(C())));
David Srbecky6da82472018-10-23 14:03:08 +01001925 inst = inst->Next_2xx();
1926 }
1927
1928 ALWAYS_INLINE void MUL_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001929 shadow_frame.SetVReg(A(),
1930 SafeMul(shadow_frame.GetVReg(B()),
1931 shadow_frame.GetVReg(C())));
David Srbecky6da82472018-10-23 14:03:08 +01001932 inst = inst->Next_2xx();
1933 }
1934
1935 ALWAYS_INLINE void DIV_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001936 bool success = DoIntDivide(shadow_frame, A(),
David Srbecky436f6c12019-05-22 13:28:42 +01001937 shadow_frame.GetVReg(B()),
1938 shadow_frame.GetVReg(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001939 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1940 }
1941
1942 ALWAYS_INLINE void REM_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001943 bool success = DoIntRemainder(shadow_frame, A(),
David Srbecky436f6c12019-05-22 13:28:42 +01001944 shadow_frame.GetVReg(B()),
1945 shadow_frame.GetVReg(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001946 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1947 }
1948
1949 ALWAYS_INLINE void SHL_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001950 shadow_frame.SetVReg(A(),
1951 shadow_frame.GetVReg(B()) <<
1952 (shadow_frame.GetVReg(C()) & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01001953 inst = inst->Next_2xx();
1954 }
1955
1956 ALWAYS_INLINE void SHR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001957 shadow_frame.SetVReg(A(),
1958 shadow_frame.GetVReg(B()) >>
1959 (shadow_frame.GetVReg(C()) & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01001960 inst = inst->Next_2xx();
1961 }
1962
1963 ALWAYS_INLINE void USHR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001964 shadow_frame.SetVReg(A(),
1965 static_cast<uint32_t>(shadow_frame.GetVReg(B())) >>
1966 (shadow_frame.GetVReg(C()) & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01001967 inst = inst->Next_2xx();
1968 }
1969
1970 ALWAYS_INLINE void AND_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001971 shadow_frame.SetVReg(A(),
1972 shadow_frame.GetVReg(B()) &
1973 shadow_frame.GetVReg(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001974 inst = inst->Next_2xx();
1975 }
1976
1977 ALWAYS_INLINE void OR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001978 shadow_frame.SetVReg(A(),
1979 shadow_frame.GetVReg(B()) |
1980 shadow_frame.GetVReg(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001981 inst = inst->Next_2xx();
1982 }
1983
1984 ALWAYS_INLINE void XOR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001985 shadow_frame.SetVReg(A(),
1986 shadow_frame.GetVReg(B()) ^
1987 shadow_frame.GetVReg(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001988 inst = inst->Next_2xx();
1989 }
1990
1991 ALWAYS_INLINE void ADD_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001992 shadow_frame.SetVRegLong(A(),
1993 SafeAdd(shadow_frame.GetVRegLong(B()),
1994 shadow_frame.GetVRegLong(C())));
David Srbecky6da82472018-10-23 14:03:08 +01001995 inst = inst->Next_2xx();
1996 }
1997
1998 ALWAYS_INLINE void SUB_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01001999 shadow_frame.SetVRegLong(A(),
2000 SafeSub(shadow_frame.GetVRegLong(B()),
2001 shadow_frame.GetVRegLong(C())));
David Srbecky6da82472018-10-23 14:03:08 +01002002 inst = inst->Next_2xx();
2003 }
2004
2005 ALWAYS_INLINE void MUL_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002006 shadow_frame.SetVRegLong(A(),
2007 SafeMul(shadow_frame.GetVRegLong(B()),
2008 shadow_frame.GetVRegLong(C())));
David Srbecky6da82472018-10-23 14:03:08 +01002009 inst = inst->Next_2xx();
2010 }
2011
2012 ALWAYS_INLINE void DIV_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002013 DoLongDivide(shadow_frame, A(),
David Srbecky436f6c12019-05-22 13:28:42 +01002014 shadow_frame.GetVRegLong(B()),
2015 shadow_frame.GetVRegLong(C()));
David Srbecky6da82472018-10-23 14:03:08 +01002016 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_2xx);
2017 }
2018
2019 ALWAYS_INLINE void REM_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002020 DoLongRemainder(shadow_frame, A(),
David Srbecky436f6c12019-05-22 13:28:42 +01002021 shadow_frame.GetVRegLong(B()),
2022 shadow_frame.GetVRegLong(C()));
David Srbecky6da82472018-10-23 14:03:08 +01002023 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_2xx);
2024 }
2025
2026 ALWAYS_INLINE void AND_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002027 shadow_frame.SetVRegLong(A(),
2028 shadow_frame.GetVRegLong(B()) &
2029 shadow_frame.GetVRegLong(C()));
David Srbecky6da82472018-10-23 14:03:08 +01002030 inst = inst->Next_2xx();
2031 }
2032
2033 ALWAYS_INLINE void OR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002034 shadow_frame.SetVRegLong(A(),
2035 shadow_frame.GetVRegLong(B()) |
2036 shadow_frame.GetVRegLong(C()));
David Srbecky6da82472018-10-23 14:03:08 +01002037 inst = inst->Next_2xx();
2038 }
2039
2040 ALWAYS_INLINE void XOR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002041 shadow_frame.SetVRegLong(A(),
2042 shadow_frame.GetVRegLong(B()) ^
2043 shadow_frame.GetVRegLong(C()));
David Srbecky6da82472018-10-23 14:03:08 +01002044 inst = inst->Next_2xx();
2045 }
2046
2047 ALWAYS_INLINE void SHL_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002048 shadow_frame.SetVRegLong(A(),
2049 shadow_frame.GetVRegLong(B()) <<
2050 (shadow_frame.GetVReg(C()) & 0x3f));
David Srbecky6da82472018-10-23 14:03:08 +01002051 inst = inst->Next_2xx();
2052 }
2053
2054 ALWAYS_INLINE void SHR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002055 shadow_frame.SetVRegLong(A(),
2056 shadow_frame.GetVRegLong(B()) >>
2057 (shadow_frame.GetVReg(C()) & 0x3f));
David Srbecky6da82472018-10-23 14:03:08 +01002058 inst = inst->Next_2xx();
2059 }
2060
2061 ALWAYS_INLINE void USHR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002062 shadow_frame.SetVRegLong(A(),
2063 static_cast<uint64_t>(shadow_frame.GetVRegLong(B())) >>
2064 (shadow_frame.GetVReg(C()) & 0x3f));
David Srbecky6da82472018-10-23 14:03:08 +01002065 inst = inst->Next_2xx();
2066 }
2067
2068 ALWAYS_INLINE void ADD_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002069 shadow_frame.SetVRegFloat(A(),
2070 shadow_frame.GetVRegFloat(B()) +
2071 shadow_frame.GetVRegFloat(C()));
David Srbecky6da82472018-10-23 14:03:08 +01002072 inst = inst->Next_2xx();
2073 }
2074
2075 ALWAYS_INLINE void SUB_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002076 shadow_frame.SetVRegFloat(A(),
2077 shadow_frame.GetVRegFloat(B()) -
2078 shadow_frame.GetVRegFloat(C()));
David Srbecky6da82472018-10-23 14:03:08 +01002079 inst = inst->Next_2xx();
2080 }
2081
2082 ALWAYS_INLINE void MUL_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002083 shadow_frame.SetVRegFloat(A(),
2084 shadow_frame.GetVRegFloat(B()) *
2085 shadow_frame.GetVRegFloat(C()));
David Srbecky6da82472018-10-23 14:03:08 +01002086 inst = inst->Next_2xx();
2087 }
2088
2089 ALWAYS_INLINE void DIV_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002090 shadow_frame.SetVRegFloat(A(),
2091 shadow_frame.GetVRegFloat(B()) /
2092 shadow_frame.GetVRegFloat(C()));
David Srbecky6da82472018-10-23 14:03:08 +01002093 inst = inst->Next_2xx();
2094 }
2095
2096 ALWAYS_INLINE void REM_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002097 shadow_frame.SetVRegFloat(A(),
2098 fmodf(shadow_frame.GetVRegFloat(B()),
2099 shadow_frame.GetVRegFloat(C())));
David Srbecky6da82472018-10-23 14:03:08 +01002100 inst = inst->Next_2xx();
2101 }
2102
2103 ALWAYS_INLINE void ADD_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002104 shadow_frame.SetVRegDouble(A(),
2105 shadow_frame.GetVRegDouble(B()) +
2106 shadow_frame.GetVRegDouble(C()));
David Srbecky6da82472018-10-23 14:03:08 +01002107 inst = inst->Next_2xx();
2108 }
2109
2110 ALWAYS_INLINE void SUB_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002111 shadow_frame.SetVRegDouble(A(),
2112 shadow_frame.GetVRegDouble(B()) -
2113 shadow_frame.GetVRegDouble(C()));
David Srbecky6da82472018-10-23 14:03:08 +01002114 inst = inst->Next_2xx();
2115 }
2116
2117 ALWAYS_INLINE void MUL_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002118 shadow_frame.SetVRegDouble(A(),
2119 shadow_frame.GetVRegDouble(B()) *
2120 shadow_frame.GetVRegDouble(C()));
David Srbecky6da82472018-10-23 14:03:08 +01002121 inst = inst->Next_2xx();
2122 }
2123
2124 ALWAYS_INLINE void DIV_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002125 shadow_frame.SetVRegDouble(A(),
2126 shadow_frame.GetVRegDouble(B()) /
2127 shadow_frame.GetVRegDouble(C()));
David Srbecky6da82472018-10-23 14:03:08 +01002128 inst = inst->Next_2xx();
2129 }
2130
2131 ALWAYS_INLINE void REM_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002132 shadow_frame.SetVRegDouble(A(),
2133 fmod(shadow_frame.GetVRegDouble(B()),
2134 shadow_frame.GetVRegDouble(C())));
David Srbecky6da82472018-10-23 14:03:08 +01002135 inst = inst->Next_2xx();
2136 }
2137
2138 ALWAYS_INLINE void ADD_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002139 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002140 shadow_frame.SetVReg(vregA, SafeAdd(shadow_frame.GetVReg(vregA),
David Srbecky436f6c12019-05-22 13:28:42 +01002141 shadow_frame.GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002142 inst = inst->Next_1xx();
2143 }
2144
2145 ALWAYS_INLINE void SUB_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002146 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002147 shadow_frame.SetVReg(vregA,
2148 SafeSub(shadow_frame.GetVReg(vregA),
David Srbecky436f6c12019-05-22 13:28:42 +01002149 shadow_frame.GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002150 inst = inst->Next_1xx();
2151 }
2152
2153 ALWAYS_INLINE void MUL_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002154 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002155 shadow_frame.SetVReg(vregA,
2156 SafeMul(shadow_frame.GetVReg(vregA),
David Srbecky436f6c12019-05-22 13:28:42 +01002157 shadow_frame.GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002158 inst = inst->Next_1xx();
2159 }
2160
2161 ALWAYS_INLINE void DIV_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002162 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002163 bool success = DoIntDivide(shadow_frame, vregA, shadow_frame.GetVReg(vregA),
David Srbecky436f6c12019-05-22 13:28:42 +01002164 shadow_frame.GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002165 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_1xx);
2166 }
2167
2168 ALWAYS_INLINE void REM_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002169 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002170 bool success = DoIntRemainder(shadow_frame, vregA, shadow_frame.GetVReg(vregA),
David Srbecky436f6c12019-05-22 13:28:42 +01002171 shadow_frame.GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002172 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_1xx);
2173 }
2174
2175 ALWAYS_INLINE void SHL_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002176 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002177 shadow_frame.SetVReg(vregA,
2178 shadow_frame.GetVReg(vregA) <<
David Srbecky436f6c12019-05-22 13:28:42 +01002179 (shadow_frame.GetVReg(B()) & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01002180 inst = inst->Next_1xx();
2181 }
2182
2183 ALWAYS_INLINE void SHR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002184 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002185 shadow_frame.SetVReg(vregA,
2186 shadow_frame.GetVReg(vregA) >>
David Srbecky436f6c12019-05-22 13:28:42 +01002187 (shadow_frame.GetVReg(B()) & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01002188 inst = inst->Next_1xx();
2189 }
2190
2191 ALWAYS_INLINE void USHR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002192 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002193 shadow_frame.SetVReg(vregA,
2194 static_cast<uint32_t>(shadow_frame.GetVReg(vregA)) >>
David Srbecky436f6c12019-05-22 13:28:42 +01002195 (shadow_frame.GetVReg(B()) & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01002196 inst = inst->Next_1xx();
2197 }
2198
2199 ALWAYS_INLINE void AND_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002200 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002201 shadow_frame.SetVReg(vregA,
2202 shadow_frame.GetVReg(vregA) &
David Srbecky436f6c12019-05-22 13:28:42 +01002203 shadow_frame.GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002204 inst = inst->Next_1xx();
2205 }
2206
2207 ALWAYS_INLINE void OR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002208 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002209 shadow_frame.SetVReg(vregA,
2210 shadow_frame.GetVReg(vregA) |
David Srbecky436f6c12019-05-22 13:28:42 +01002211 shadow_frame.GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002212 inst = inst->Next_1xx();
2213 }
2214
2215 ALWAYS_INLINE void XOR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002216 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002217 shadow_frame.SetVReg(vregA,
2218 shadow_frame.GetVReg(vregA) ^
David Srbecky436f6c12019-05-22 13:28:42 +01002219 shadow_frame.GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002220 inst = inst->Next_1xx();
2221 }
2222
2223 ALWAYS_INLINE void ADD_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002224 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002225 shadow_frame.SetVRegLong(vregA,
2226 SafeAdd(shadow_frame.GetVRegLong(vregA),
David Srbecky436f6c12019-05-22 13:28:42 +01002227 shadow_frame.GetVRegLong(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002228 inst = inst->Next_1xx();
2229 }
2230
2231 ALWAYS_INLINE void SUB_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002232 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002233 shadow_frame.SetVRegLong(vregA,
2234 SafeSub(shadow_frame.GetVRegLong(vregA),
David Srbecky436f6c12019-05-22 13:28:42 +01002235 shadow_frame.GetVRegLong(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002236 inst = inst->Next_1xx();
2237 }
2238
2239 ALWAYS_INLINE void MUL_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002240 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002241 shadow_frame.SetVRegLong(vregA,
2242 SafeMul(shadow_frame.GetVRegLong(vregA),
David Srbecky436f6c12019-05-22 13:28:42 +01002243 shadow_frame.GetVRegLong(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002244 inst = inst->Next_1xx();
2245 }
2246
2247 ALWAYS_INLINE void DIV_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002248 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002249 DoLongDivide(shadow_frame, vregA, shadow_frame.GetVRegLong(vregA),
David Srbecky436f6c12019-05-22 13:28:42 +01002250 shadow_frame.GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002251 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
2252 }
2253
2254 ALWAYS_INLINE void REM_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002255 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002256 DoLongRemainder(shadow_frame, vregA, shadow_frame.GetVRegLong(vregA),
David Srbecky436f6c12019-05-22 13:28:42 +01002257 shadow_frame.GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002258 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
2259 }
2260
2261 ALWAYS_INLINE void AND_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002262 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002263 shadow_frame.SetVRegLong(vregA,
2264 shadow_frame.GetVRegLong(vregA) &
David Srbecky436f6c12019-05-22 13:28:42 +01002265 shadow_frame.GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002266 inst = inst->Next_1xx();
2267 }
2268
2269 ALWAYS_INLINE void OR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002270 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002271 shadow_frame.SetVRegLong(vregA,
2272 shadow_frame.GetVRegLong(vregA) |
David Srbecky436f6c12019-05-22 13:28:42 +01002273 shadow_frame.GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002274 inst = inst->Next_1xx();
2275 }
2276
2277 ALWAYS_INLINE void XOR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002278 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002279 shadow_frame.SetVRegLong(vregA,
2280 shadow_frame.GetVRegLong(vregA) ^
David Srbecky436f6c12019-05-22 13:28:42 +01002281 shadow_frame.GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002282 inst = inst->Next_1xx();
2283 }
2284
2285 ALWAYS_INLINE void SHL_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002286 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002287 shadow_frame.SetVRegLong(vregA,
2288 shadow_frame.GetVRegLong(vregA) <<
David Srbecky436f6c12019-05-22 13:28:42 +01002289 (shadow_frame.GetVReg(B()) & 0x3f));
David Srbecky6da82472018-10-23 14:03:08 +01002290 inst = inst->Next_1xx();
2291 }
2292
2293 ALWAYS_INLINE void SHR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002294 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002295 shadow_frame.SetVRegLong(vregA,
2296 shadow_frame.GetVRegLong(vregA) >>
David Srbecky436f6c12019-05-22 13:28:42 +01002297 (shadow_frame.GetVReg(B()) & 0x3f));
David Srbecky6da82472018-10-23 14:03:08 +01002298 inst = inst->Next_1xx();
2299 }
2300
2301 ALWAYS_INLINE void USHR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002302 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002303 shadow_frame.SetVRegLong(vregA,
2304 static_cast<uint64_t>(shadow_frame.GetVRegLong(vregA)) >>
David Srbecky436f6c12019-05-22 13:28:42 +01002305 (shadow_frame.GetVReg(B()) & 0x3f));
David Srbecky6da82472018-10-23 14:03:08 +01002306 inst = inst->Next_1xx();
2307 }
2308
2309 ALWAYS_INLINE void ADD_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002310 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002311 shadow_frame.SetVRegFloat(vregA,
2312 shadow_frame.GetVRegFloat(vregA) +
David Srbecky436f6c12019-05-22 13:28:42 +01002313 shadow_frame.GetVRegFloat(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002314 inst = inst->Next_1xx();
2315 }
2316
2317 ALWAYS_INLINE void SUB_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002318 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002319 shadow_frame.SetVRegFloat(vregA,
2320 shadow_frame.GetVRegFloat(vregA) -
David Srbecky436f6c12019-05-22 13:28:42 +01002321 shadow_frame.GetVRegFloat(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002322 inst = inst->Next_1xx();
2323 }
2324
2325 ALWAYS_INLINE void MUL_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002326 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002327 shadow_frame.SetVRegFloat(vregA,
2328 shadow_frame.GetVRegFloat(vregA) *
David Srbecky436f6c12019-05-22 13:28:42 +01002329 shadow_frame.GetVRegFloat(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002330 inst = inst->Next_1xx();
2331 }
2332
2333 ALWAYS_INLINE void DIV_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002334 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002335 shadow_frame.SetVRegFloat(vregA,
2336 shadow_frame.GetVRegFloat(vregA) /
David Srbecky436f6c12019-05-22 13:28:42 +01002337 shadow_frame.GetVRegFloat(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002338 inst = inst->Next_1xx();
2339 }
2340
2341 ALWAYS_INLINE void REM_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002342 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002343 shadow_frame.SetVRegFloat(vregA,
2344 fmodf(shadow_frame.GetVRegFloat(vregA),
David Srbecky436f6c12019-05-22 13:28:42 +01002345 shadow_frame.GetVRegFloat(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002346 inst = inst->Next_1xx();
2347 }
2348
2349 ALWAYS_INLINE void ADD_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002350 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002351 shadow_frame.SetVRegDouble(vregA,
2352 shadow_frame.GetVRegDouble(vregA) +
David Srbecky436f6c12019-05-22 13:28:42 +01002353 shadow_frame.GetVRegDouble(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002354 inst = inst->Next_1xx();
2355 }
2356
2357 ALWAYS_INLINE void SUB_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002358 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002359 shadow_frame.SetVRegDouble(vregA,
2360 shadow_frame.GetVRegDouble(vregA) -
David Srbecky436f6c12019-05-22 13:28:42 +01002361 shadow_frame.GetVRegDouble(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002362 inst = inst->Next_1xx();
2363 }
2364
2365 ALWAYS_INLINE void MUL_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002366 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002367 shadow_frame.SetVRegDouble(vregA,
2368 shadow_frame.GetVRegDouble(vregA) *
David Srbecky436f6c12019-05-22 13:28:42 +01002369 shadow_frame.GetVRegDouble(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002370 inst = inst->Next_1xx();
2371 }
2372
2373 ALWAYS_INLINE void DIV_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002374 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002375 shadow_frame.SetVRegDouble(vregA,
2376 shadow_frame.GetVRegDouble(vregA) /
David Srbecky436f6c12019-05-22 13:28:42 +01002377 shadow_frame.GetVRegDouble(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002378 inst = inst->Next_1xx();
2379 }
2380
2381 ALWAYS_INLINE void REM_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002382 uint4_t vregA = A();
David Srbecky6da82472018-10-23 14:03:08 +01002383 shadow_frame.SetVRegDouble(vregA,
2384 fmod(shadow_frame.GetVRegDouble(vregA),
David Srbecky436f6c12019-05-22 13:28:42 +01002385 shadow_frame.GetVRegDouble(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002386 inst = inst->Next_1xx();
2387 }
2388
2389 ALWAYS_INLINE void ADD_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002390 shadow_frame.SetVReg(A(),
2391 SafeAdd(shadow_frame.GetVReg(B()),
David Srbeckyd6f579c2019-05-29 18:09:30 +01002392 C()));
David Srbecky6da82472018-10-23 14:03:08 +01002393 inst = inst->Next_2xx();
2394 }
2395
2396 ALWAYS_INLINE void RSUB_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002397 shadow_frame.SetVReg(A(),
David Srbeckyd6f579c2019-05-29 18:09:30 +01002398 SafeSub(C(),
David Srbecky436f6c12019-05-22 13:28:42 +01002399 shadow_frame.GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002400 inst = inst->Next_2xx();
2401 }
2402
2403 ALWAYS_INLINE void MUL_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002404 shadow_frame.SetVReg(A(),
2405 SafeMul(shadow_frame.GetVReg(B()),
David Srbeckyd6f579c2019-05-29 18:09:30 +01002406 C()));
David Srbecky6da82472018-10-23 14:03:08 +01002407 inst = inst->Next_2xx();
2408 }
2409
2410 ALWAYS_INLINE void DIV_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002411 bool success = DoIntDivide(shadow_frame, A(),
David Srbecky436f6c12019-05-22 13:28:42 +01002412 shadow_frame.GetVReg(B()),
David Srbeckyd6f579c2019-05-29 18:09:30 +01002413 C());
David Srbecky6da82472018-10-23 14:03:08 +01002414 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
2415 }
2416
2417 ALWAYS_INLINE void REM_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002418 bool success = DoIntRemainder(shadow_frame, A(),
David Srbecky436f6c12019-05-22 13:28:42 +01002419 shadow_frame.GetVReg(B()),
David Srbeckyd6f579c2019-05-29 18:09:30 +01002420 C());
David Srbecky6da82472018-10-23 14:03:08 +01002421 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
2422 }
2423
2424 ALWAYS_INLINE void AND_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002425 shadow_frame.SetVReg(A(),
2426 shadow_frame.GetVReg(B()) &
David Srbeckyd6f579c2019-05-29 18:09:30 +01002427 C());
David Srbecky6da82472018-10-23 14:03:08 +01002428 inst = inst->Next_2xx();
2429 }
2430
2431 ALWAYS_INLINE void OR_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002432 shadow_frame.SetVReg(A(),
2433 shadow_frame.GetVReg(B()) |
David Srbeckyd6f579c2019-05-29 18:09:30 +01002434 C());
David Srbecky6da82472018-10-23 14:03:08 +01002435 inst = inst->Next_2xx();
2436 }
2437
2438 ALWAYS_INLINE void XOR_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002439 shadow_frame.SetVReg(A(),
2440 shadow_frame.GetVReg(B()) ^
David Srbeckyd6f579c2019-05-29 18:09:30 +01002441 C());
David Srbecky6da82472018-10-23 14:03:08 +01002442 inst = inst->Next_2xx();
2443 }
2444
2445 ALWAYS_INLINE void ADD_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002446 shadow_frame.SetVReg(A(),
David Srbeckyd6f579c2019-05-29 18:09:30 +01002447 SafeAdd(shadow_frame.GetVReg(B()), C()));
David Srbecky6da82472018-10-23 14:03:08 +01002448 inst = inst->Next_2xx();
2449 }
2450
2451 ALWAYS_INLINE void RSUB_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002452 shadow_frame.SetVReg(A(),
David Srbeckyd6f579c2019-05-29 18:09:30 +01002453 SafeSub(C(), shadow_frame.GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002454 inst = inst->Next_2xx();
2455 }
2456
2457 ALWAYS_INLINE void MUL_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002458 shadow_frame.SetVReg(A(),
David Srbeckyd6f579c2019-05-29 18:09:30 +01002459 SafeMul(shadow_frame.GetVReg(B()), C()));
David Srbecky6da82472018-10-23 14:03:08 +01002460 inst = inst->Next_2xx();
2461 }
2462
2463 ALWAYS_INLINE void DIV_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002464 bool success = DoIntDivide(shadow_frame, A(),
2465 shadow_frame.GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +01002466 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
2467 }
2468
2469 ALWAYS_INLINE void REM_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002470 bool success = DoIntRemainder(shadow_frame, A(),
2471 shadow_frame.GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +01002472 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
2473 }
2474
2475 ALWAYS_INLINE void AND_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002476 shadow_frame.SetVReg(A(),
2477 shadow_frame.GetVReg(B()) &
David Srbeckyd6f579c2019-05-29 18:09:30 +01002478 C());
David Srbecky6da82472018-10-23 14:03:08 +01002479 inst = inst->Next_2xx();
2480 }
2481
2482 ALWAYS_INLINE void OR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002483 shadow_frame.SetVReg(A(),
2484 shadow_frame.GetVReg(B()) |
David Srbeckyd6f579c2019-05-29 18:09:30 +01002485 C());
David Srbecky6da82472018-10-23 14:03:08 +01002486 inst = inst->Next_2xx();
2487 }
2488
2489 ALWAYS_INLINE void XOR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002490 shadow_frame.SetVReg(A(),
2491 shadow_frame.GetVReg(B()) ^
David Srbeckyd6f579c2019-05-29 18:09:30 +01002492 C());
David Srbecky6da82472018-10-23 14:03:08 +01002493 inst = inst->Next_2xx();
2494 }
2495
2496 ALWAYS_INLINE void SHL_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002497 shadow_frame.SetVReg(A(),
2498 shadow_frame.GetVReg(B()) <<
David Srbeckyd6f579c2019-05-29 18:09:30 +01002499 (C() & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01002500 inst = inst->Next_2xx();
2501 }
2502
2503 ALWAYS_INLINE void SHR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002504 shadow_frame.SetVReg(A(),
2505 shadow_frame.GetVReg(B()) >>
David Srbeckyd6f579c2019-05-29 18:09:30 +01002506 (C() & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01002507 inst = inst->Next_2xx();
2508 }
2509
2510 ALWAYS_INLINE void USHR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky436f6c12019-05-22 13:28:42 +01002511 shadow_frame.SetVReg(A(),
2512 static_cast<uint32_t>(shadow_frame.GetVReg(B())) >>
David Srbeckyd6f579c2019-05-29 18:09:30 +01002513 (C() & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01002514 inst = inst->Next_2xx();
2515 }
2516
2517 ALWAYS_INLINE void UNUSED_3E() REQUIRES_SHARED(Locks::mutator_lock_) {
2518 UnexpectedOpcode(inst, shadow_frame);
2519 }
2520
2521 ALWAYS_INLINE void UNUSED_3F() REQUIRES_SHARED(Locks::mutator_lock_) {
2522 UnexpectedOpcode(inst, shadow_frame);
2523 }
2524
2525 ALWAYS_INLINE void UNUSED_40() REQUIRES_SHARED(Locks::mutator_lock_) {
2526 UnexpectedOpcode(inst, shadow_frame);
2527 }
2528
2529 ALWAYS_INLINE void UNUSED_41() REQUIRES_SHARED(Locks::mutator_lock_) {
2530 UnexpectedOpcode(inst, shadow_frame);
2531 }
2532
2533 ALWAYS_INLINE void UNUSED_42() REQUIRES_SHARED(Locks::mutator_lock_) {
2534 UnexpectedOpcode(inst, shadow_frame);
2535 }
2536
2537 ALWAYS_INLINE void UNUSED_43() REQUIRES_SHARED(Locks::mutator_lock_) {
2538 UnexpectedOpcode(inst, shadow_frame);
2539 }
2540
2541 ALWAYS_INLINE void UNUSED_79() REQUIRES_SHARED(Locks::mutator_lock_) {
2542 UnexpectedOpcode(inst, shadow_frame);
2543 }
2544
2545 ALWAYS_INLINE void UNUSED_7A() REQUIRES_SHARED(Locks::mutator_lock_) {
2546 UnexpectedOpcode(inst, shadow_frame);
2547 }
2548
2549 ALWAYS_INLINE void UNUSED_F3() REQUIRES_SHARED(Locks::mutator_lock_) {
2550 UnexpectedOpcode(inst, shadow_frame);
2551 }
2552
2553 ALWAYS_INLINE void UNUSED_F4() REQUIRES_SHARED(Locks::mutator_lock_) {
2554 UnexpectedOpcode(inst, shadow_frame);
2555 }
2556
2557 ALWAYS_INLINE void UNUSED_F5() REQUIRES_SHARED(Locks::mutator_lock_) {
2558 UnexpectedOpcode(inst, shadow_frame);
2559 }
2560
2561 ALWAYS_INLINE void UNUSED_F6() REQUIRES_SHARED(Locks::mutator_lock_) {
2562 UnexpectedOpcode(inst, shadow_frame);
2563 }
2564
2565 ALWAYS_INLINE void UNUSED_F7() REQUIRES_SHARED(Locks::mutator_lock_) {
2566 UnexpectedOpcode(inst, shadow_frame);
2567 }
2568
2569 ALWAYS_INLINE void UNUSED_F8() REQUIRES_SHARED(Locks::mutator_lock_) {
2570 UnexpectedOpcode(inst, shadow_frame);
2571 }
2572
2573 ALWAYS_INLINE void UNUSED_F9() REQUIRES_SHARED(Locks::mutator_lock_) {
2574 UnexpectedOpcode(inst, shadow_frame);
2575 }
2576
2577 ALWAYS_INLINE InstructionHandler(SwitchImplContext* ctx,
2578 const instrumentation::Instrumentation* instrumentation,
2579 Thread* self,
2580 ShadowFrame& shadow_frame,
2581 uint16_t dex_pc,
2582 const Instruction*& inst,
2583 uint16_t inst_data,
2584 bool& exit_interpreter_loop)
2585 : ctx(ctx),
2586 instrumentation(instrumentation),
2587 self(self),
2588 shadow_frame(shadow_frame),
2589 dex_pc(dex_pc),
2590 inst(inst),
2591 inst_data(inst_data),
2592 exit_interpreter_loop(exit_interpreter_loop) {
2593 }
2594
2595 private:
2596 static constexpr bool do_assignability_check = do_access_check;
2597
2598 const CodeItemDataAccessor& Accessor() { return ctx->accessor; }
2599 const uint16_t* Insns() { return ctx->accessor.Insns(); }
2600 JValue* ResultRegister() { return &ctx->result_register; }
2601
David Srbecky436f6c12019-05-22 13:28:42 +01002602 ALWAYS_INLINE int32_t A() { return inst->VRegA(kFormat, inst_data); }
2603 ALWAYS_INLINE int32_t B() { return inst->VRegB(kFormat, inst_data); }
2604 ALWAYS_INLINE int32_t C() { return inst->VRegC(kFormat); }
2605
David Srbecky6da82472018-10-23 14:03:08 +01002606 SwitchImplContext* const ctx;
2607 const instrumentation::Instrumentation* const instrumentation;
2608 Thread* const self;
2609 ShadowFrame& shadow_frame;
2610 uint32_t const dex_pc;
2611 const Instruction*& inst;
2612 uint16_t const inst_data;
2613 bool& exit_interpreter_loop;
2614};
2615
David Srbecky6da82472018-10-23 14:03:08 +01002616#undef BRANCH_INSTRUMENTATION
David Srbecky6da82472018-10-23 14:03:08 +01002617#undef POSSIBLY_HANDLE_PENDING_EXCEPTION
2618#undef POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE
2619#undef POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC
David Srbecky6da82472018-10-23 14:03:08 +01002620#undef HANDLE_PENDING_EXCEPTION
David Srbecky6da82472018-10-23 14:03:08 +01002621
Alex Light6f22e062018-10-05 15:05:12 -07002622// TODO On ASAN builds this function gets a huge stack frame. Since normally we run in the mterp
2623// this shouldn't cause any problems for stack overflow detection. Remove this once b/117341496 is
2624// fixed.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +01002625template<bool do_access_check, bool transaction_active>
Alex Light6f22e062018-10-05 15:05:12 -07002626ATTRIBUTE_NO_SANITIZE_ADDRESS void ExecuteSwitchImplCpp(SwitchImplContext* ctx) {
David Srbecky946bb092018-03-09 17:23:01 +00002627 Thread* self = ctx->self;
2628 const CodeItemDataAccessor& accessor = ctx->accessor;
2629 ShadowFrame& shadow_frame = ctx->shadow_frame;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002630 if (UNLIKELY(!shadow_frame.HasReferenceArray())) {
2631 LOG(FATAL) << "Invalid shadow frame for interpreter use";
David Srbecky946bb092018-03-09 17:23:01 +00002632 ctx->result = JValue();
2633 return;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002634 }
2635 self->VerifyStack();
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002636
2637 uint32_t dex_pc = shadow_frame.GetDexPC();
Mathieu Chartier2cebb242015-04-21 16:50:40 -07002638 const auto* const instrumentation = Runtime::Current()->GetInstrumentation();
Mathieu Chartier808c7a52017-12-15 11:19:33 -08002639 const uint16_t* const insns = accessor.Insns();
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002640 const Instruction* inst = Instruction::At(insns + dex_pc);
Sebastien Hertz3b588e02013-09-11 14:33:18 +02002641 uint16_t inst_data;
Igor Murashkin6918bf12015-09-27 19:19:06 -07002642
Alex Light0aa7a5a2018-10-10 15:58:14 +00002643 DCHECK(!shadow_frame.GetForceRetryInstruction())
2644 << "Entered interpreter from invoke without retry instruction being handled!";
2645
David Srbecky6da82472018-10-23 14:03:08 +01002646 bool const interpret_one_instruction = ctx->interpret_one_instruction;
2647 while (true) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002648 dex_pc = inst->GetDexPc(insns);
2649 shadow_frame.SetDexPC(dex_pc);
Ian Rogerse94652f2014-12-02 11:13:19 -08002650 TraceExecution(shadow_frame, inst, dex_pc);
Sebastien Hertz3b588e02013-09-11 14:33:18 +02002651 inst_data = inst->Fetch16(0);
David Srbeckya4a96af2018-10-31 16:34:58 +00002652 {
2653 bool exit_loop = false;
David Srbecky436f6c12019-05-22 13:28:42 +01002654 InstructionHandler<do_access_check, transaction_active, Instruction::kInvalidFormat> handler(
David Srbeckya4a96af2018-10-31 16:34:58 +00002655 ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, exit_loop);
2656 if (!handler.Preamble()) {
2657 if (UNLIKELY(exit_loop)) {
2658 return;
2659 }
2660 if (UNLIKELY(interpret_one_instruction)) {
2661 break;
2662 }
2663 continue;
2664 }
2665 }
Sebastien Hertz3b588e02013-09-11 14:33:18 +02002666 switch (inst->Opcode(inst_data)) {
David Srbecky436f6c12019-05-22 13:28:42 +01002667#define OPCODE_CASE(OPCODE, OPCODE_NAME, pname, FORMAT, i, a, e, v) \
David Srbecky6da82472018-10-23 14:03:08 +01002668 case OPCODE: { \
2669 bool exit_loop = false; \
David Srbecky436f6c12019-05-22 13:28:42 +01002670 InstructionHandler<do_access_check, transaction_active, Instruction::FORMAT> handler( \
David Srbecky6da82472018-10-23 14:03:08 +01002671 ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, exit_loop); \
David Srbeckya4a96af2018-10-31 16:34:58 +00002672 handler.OPCODE_NAME(); \
David Srbecky6da82472018-10-23 14:03:08 +01002673 /* TODO: Advance 'inst' here, instead of explicitly in each handler */ \
2674 if (UNLIKELY(exit_loop)) { \
2675 return; \
2676 } \
2677 break; \
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002678 }
David Srbecky6da82472018-10-23 14:03:08 +01002679DEX_INSTRUCTION_LIST(OPCODE_CASE)
2680#undef OPCODE_CASE
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002681 }
David Srbecky6da82472018-10-23 14:03:08 +01002682 if (UNLIKELY(interpret_one_instruction)) {
David Srbeckya4a96af2018-10-31 16:34:58 +00002683 break;
David Srbecky6da82472018-10-23 14:03:08 +01002684 }
2685 }
David Srbeckya4a96af2018-10-31 16:34:58 +00002686 // Record where we stopped.
2687 shadow_frame.SetDexPC(inst->GetDexPc(insns));
2688 ctx->result = ctx->result_register;
2689 return;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002690} // NOLINT(readability/fn_size)
2691
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002692} // namespace interpreter
2693} // namespace art
David Srbecky2ee09ff2018-10-24 13:24:22 +01002694
2695#endif // ART_RUNTIME_INTERPRETER_INTERPRETER_SWITCH_IMPL_INL_H_