blob: c584127b3faa19f67bd5268d3149c19154a6dac3 [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 Srbecky6baf6442019-05-30 14:57:43 +0100399 SetVReg(A(), GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100400 inst = inst->Next_1xx();
401 }
402
403 ALWAYS_INLINE void MOVE_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100404 SetVReg(A(), GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100405 inst = inst->Next_2xx();
406 }
407
408 ALWAYS_INLINE void MOVE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100409 SetVReg(A(), GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100410 inst = inst->Next_3xx();
411 }
412
413 ALWAYS_INLINE void MOVE_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100414 SetVRegLong(A(), GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100415 inst = inst->Next_1xx();
416 }
417
418 ALWAYS_INLINE void MOVE_WIDE_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100419 SetVRegLong(A(), GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100420 inst = inst->Next_2xx();
421 }
422
423 ALWAYS_INLINE void MOVE_WIDE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100424 SetVRegLong(A(), GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100425 inst = inst->Next_3xx();
426 }
427
428 ALWAYS_INLINE void MOVE_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100429 SetVRegReference(A(), GetVRegReference(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100430 inst = inst->Next_1xx();
431 }
432
433 ALWAYS_INLINE void MOVE_OBJECT_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100434 SetVRegReference(A(), GetVRegReference(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100435 inst = inst->Next_2xx();
436 }
437
438 ALWAYS_INLINE void MOVE_OBJECT_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100439 SetVRegReference(A(), GetVRegReference(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100440 inst = inst->Next_3xx();
441 }
442
443 ALWAYS_INLINE void MOVE_RESULT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100444 SetVReg(A(), ResultRegister()->GetI());
David Srbecky6da82472018-10-23 14:03:08 +0100445 inst = inst->Next_1xx();
446 }
447
448 ALWAYS_INLINE void MOVE_RESULT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100449 SetVRegLong(A(), ResultRegister()->GetJ());
David Srbecky6da82472018-10-23 14:03:08 +0100450 inst = inst->Next_1xx();
451 }
452
453 ALWAYS_INLINE void MOVE_RESULT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100454 SetVRegReference(A(), ResultRegister()->GetL());
David Srbecky6da82472018-10-23 14:03:08 +0100455 inst = inst->Next_1xx();
456 }
457
458 ALWAYS_INLINE void MOVE_EXCEPTION() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100459 ObjPtr<mirror::Throwable> exception = self->GetException();
460 DCHECK(exception != nullptr) << "No pending exception on MOVE_EXCEPTION instruction";
David Srbecky6baf6442019-05-30 14:57:43 +0100461 SetVRegReference(A(), exception);
David Srbecky6da82472018-10-23 14:03:08 +0100462 self->ClearException();
463 inst = inst->Next_1xx();
464 }
465
466 ALWAYS_INLINE void RETURN_VOID_NO_BARRIER() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100467 JValue result;
468 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000469 if (!HandleMonitorChecks()) {
470 return;
471 }
David Srbecky6da82472018-10-23 14:03:08 +0100472 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
473 !SendMethodExitEvents(self,
474 instrumentation,
475 shadow_frame,
476 shadow_frame.GetThisObject(Accessor().InsSize()),
477 shadow_frame.GetMethod(),
478 inst->GetDexPc(Insns()),
479 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000480 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
481 return;
482 }
David Srbecky6da82472018-10-23 14:03:08 +0100483 }
484 if (ctx->interpret_one_instruction) {
485 /* Signal mterp to return to caller */
486 shadow_frame.SetDexPC(dex::kDexNoIndex);
487 }
488 ctx->result = result;
489 exit_interpreter_loop = true;
490 }
491
492 ALWAYS_INLINE void RETURN_VOID() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100493 QuasiAtomic::ThreadFenceForConstructor();
494 JValue result;
495 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000496 if (!HandleMonitorChecks()) {
497 return;
498 }
David Srbecky6da82472018-10-23 14:03:08 +0100499 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
500 !SendMethodExitEvents(self,
501 instrumentation,
502 shadow_frame,
503 shadow_frame.GetThisObject(Accessor().InsSize()),
504 shadow_frame.GetMethod(),
505 inst->GetDexPc(Insns()),
506 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000507 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
508 return;
509 }
David Srbecky6da82472018-10-23 14:03:08 +0100510 }
511 if (ctx->interpret_one_instruction) {
512 /* Signal mterp to return to caller */
513 shadow_frame.SetDexPC(dex::kDexNoIndex);
514 }
515 ctx->result = result;
516 exit_interpreter_loop = true;
517 }
518
519 ALWAYS_INLINE void RETURN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100520 JValue result;
521 result.SetJ(0);
David Srbecky6baf6442019-05-30 14:57:43 +0100522 result.SetI(GetVReg(A()));
David Srbecky6da82472018-10-23 14:03:08 +0100523 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000524 if (!HandleMonitorChecks()) {
525 return;
526 }
David Srbecky6da82472018-10-23 14:03:08 +0100527 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
528 !SendMethodExitEvents(self,
529 instrumentation,
530 shadow_frame,
531 shadow_frame.GetThisObject(Accessor().InsSize()),
532 shadow_frame.GetMethod(),
533 inst->GetDexPc(Insns()),
534 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000535 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
536 return;
537 }
David Srbecky6da82472018-10-23 14:03:08 +0100538 }
539 if (ctx->interpret_one_instruction) {
540 /* Signal mterp to return to caller */
541 shadow_frame.SetDexPC(dex::kDexNoIndex);
542 }
543 ctx->result = result;
544 exit_interpreter_loop = true;
545 }
546
547 ALWAYS_INLINE void RETURN_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100548 JValue result;
David Srbecky6baf6442019-05-30 14:57:43 +0100549 result.SetJ(GetVRegLong(A()));
David Srbecky6da82472018-10-23 14:03:08 +0100550 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000551 if (!HandleMonitorChecks()) {
552 return;
553 }
David Srbecky6da82472018-10-23 14:03:08 +0100554 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
555 !SendMethodExitEvents(self,
556 instrumentation,
557 shadow_frame,
558 shadow_frame.GetThisObject(Accessor().InsSize()),
559 shadow_frame.GetMethod(),
560 inst->GetDexPc(Insns()),
561 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000562 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
563 return;
564 }
David Srbecky6da82472018-10-23 14:03:08 +0100565 }
566 if (ctx->interpret_one_instruction) {
567 /* Signal mterp to return to caller */
568 shadow_frame.SetDexPC(dex::kDexNoIndex);
569 }
570 ctx->result = result;
571 exit_interpreter_loop = true;
572 }
573
574 ALWAYS_INLINE void RETURN_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100575 JValue result;
576 self->AllowThreadSuspension();
David Srbecky47ad3762018-10-31 12:43:40 +0000577 if (!HandleMonitorChecks()) {
578 return;
579 }
David Srbeckyd6f579c2019-05-29 18:09:30 +0100580 const size_t ref_idx = A();
David Srbecky6baf6442019-05-30 14:57:43 +0100581 ObjPtr<mirror::Object> obj_result = GetVRegReference(ref_idx);
David Srbecky6da82472018-10-23 14:03:08 +0100582 if (do_assignability_check && obj_result != nullptr) {
583 ObjPtr<mirror::Class> return_type = shadow_frame.GetMethod()->ResolveReturnType();
584 // Re-load since it might have moved.
David Srbecky6baf6442019-05-30 14:57:43 +0100585 obj_result = GetVRegReference(ref_idx);
David Srbecky6da82472018-10-23 14:03:08 +0100586 if (return_type == nullptr) {
587 // Return the pending exception.
588 HANDLE_PENDING_EXCEPTION();
589 }
590 if (!obj_result->VerifierInstanceOf(return_type)) {
591 // This should never happen.
592 std::string temp1, temp2;
593 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
594 "Returning '%s' that is not instance of return type '%s'",
595 obj_result->GetClass()->GetDescriptor(&temp1),
596 return_type->GetDescriptor(&temp2));
597 HANDLE_PENDING_EXCEPTION();
598 }
599 }
600 result.SetL(obj_result);
601 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
602 !SendMethodExitEvents(self,
603 instrumentation,
604 shadow_frame,
605 shadow_frame.GetThisObject(Accessor().InsSize()),
606 shadow_frame.GetMethod(),
607 inst->GetDexPc(Insns()),
608 result))) {
David Srbecky47ad3762018-10-31 12:43:40 +0000609 if (!HandlePendingExceptionWithInstrumentation(nullptr)) {
610 return;
611 }
David Srbecky6da82472018-10-23 14:03:08 +0100612 }
613 // Re-load since it might have moved during the MethodExitEvent.
David Srbecky6baf6442019-05-30 14:57:43 +0100614 result.SetL(GetVRegReference(ref_idx));
David Srbecky6da82472018-10-23 14:03:08 +0100615 if (ctx->interpret_one_instruction) {
616 /* Signal mterp to return to caller */
617 shadow_frame.SetDexPC(dex::kDexNoIndex);
618 }
619 ctx->result = result;
620 exit_interpreter_loop = true;
621 }
622
623 ALWAYS_INLINE void CONST_4() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100624 uint4_t dst = inst->VRegA_11n(inst_data);
625 int4_t val = inst->VRegB_11n(inst_data);
David Srbecky6baf6442019-05-30 14:57:43 +0100626 SetVReg(dst, val);
David Srbecky6da82472018-10-23 14:03:08 +0100627 if (val == 0) {
David Srbecky6baf6442019-05-30 14:57:43 +0100628 SetVRegReference(dst, nullptr);
David Srbecky6da82472018-10-23 14:03:08 +0100629 }
630 inst = inst->Next_1xx();
631 }
632
633 ALWAYS_INLINE void CONST_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100634 uint8_t dst = A();
635 int16_t val = B();
David Srbecky6baf6442019-05-30 14:57:43 +0100636 SetVReg(dst, val);
David Srbecky6da82472018-10-23 14:03:08 +0100637 if (val == 0) {
David Srbecky6baf6442019-05-30 14:57:43 +0100638 SetVRegReference(dst, nullptr);
David Srbecky6da82472018-10-23 14:03:08 +0100639 }
640 inst = inst->Next_2xx();
641 }
642
643 ALWAYS_INLINE void CONST() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100644 uint8_t dst = A();
645 int32_t val = B();
David Srbecky6baf6442019-05-30 14:57:43 +0100646 SetVReg(dst, val);
David Srbecky6da82472018-10-23 14:03:08 +0100647 if (val == 0) {
David Srbecky6baf6442019-05-30 14:57:43 +0100648 SetVRegReference(dst, nullptr);
David Srbecky6da82472018-10-23 14:03:08 +0100649 }
650 inst = inst->Next_3xx();
651 }
652
653 ALWAYS_INLINE void CONST_HIGH16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100654 uint8_t dst = A();
655 int32_t val = static_cast<int32_t>(B() << 16);
David Srbecky6baf6442019-05-30 14:57:43 +0100656 SetVReg(dst, val);
David Srbecky6da82472018-10-23 14:03:08 +0100657 if (val == 0) {
David Srbecky6baf6442019-05-30 14:57:43 +0100658 SetVRegReference(dst, nullptr);
David Srbecky6da82472018-10-23 14:03:08 +0100659 }
660 inst = inst->Next_2xx();
661 }
662
663 ALWAYS_INLINE void CONST_WIDE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100664 SetVRegLong(A(), B());
David Srbecky6da82472018-10-23 14:03:08 +0100665 inst = inst->Next_2xx();
666 }
667
668 ALWAYS_INLINE void CONST_WIDE_32() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100669 SetVRegLong(A(), B());
David Srbecky6da82472018-10-23 14:03:08 +0100670 inst = inst->Next_3xx();
671 }
672
673 ALWAYS_INLINE void CONST_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100674 SetVRegLong(A(), inst->WideVRegB());
David Srbecky6da82472018-10-23 14:03:08 +0100675 inst = inst->Next_51l();
676 }
677
678 ALWAYS_INLINE void CONST_WIDE_HIGH16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100679 SetVRegLong(A(), static_cast<uint64_t>(B()) << 48);
David Srbecky6da82472018-10-23 14:03:08 +0100680 inst = inst->Next_2xx();
681 }
682
683 ALWAYS_INLINE void CONST_STRING() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100684 ObjPtr<mirror::String> s = ResolveString(self, shadow_frame, dex::StringIndex(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100685 if (UNLIKELY(s == nullptr)) {
686 HANDLE_PENDING_EXCEPTION();
687 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100688 SetVRegReference(A(), s);
David Srbecky6da82472018-10-23 14:03:08 +0100689 inst = inst->Next_2xx();
690 }
691 }
692
693 ALWAYS_INLINE void CONST_STRING_JUMBO() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100694 ObjPtr<mirror::String> s = ResolveString(self, shadow_frame, dex::StringIndex(B()));
David Srbecky6da82472018-10-23 14:03:08 +0100695 if (UNLIKELY(s == nullptr)) {
696 HANDLE_PENDING_EXCEPTION();
697 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100698 SetVRegReference(A(), s);
David Srbecky6da82472018-10-23 14:03:08 +0100699 inst = inst->Next_3xx();
700 }
701 }
702
703 ALWAYS_INLINE void CONST_CLASS() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100704 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(B()),
David Srbecky6da82472018-10-23 14:03:08 +0100705 shadow_frame.GetMethod(),
706 self,
707 false,
708 do_access_check);
709 if (UNLIKELY(c == nullptr)) {
710 HANDLE_PENDING_EXCEPTION();
711 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100712 SetVRegReference(A(), c);
David Srbecky6da82472018-10-23 14:03:08 +0100713 inst = inst->Next_2xx();
714 }
715 }
716
717 ALWAYS_INLINE void CONST_METHOD_HANDLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100718 ClassLinker* cl = Runtime::Current()->GetClassLinker();
719 ObjPtr<mirror::MethodHandle> mh = cl->ResolveMethodHandle(self,
David Srbeckyd6f579c2019-05-29 18:09:30 +0100720 B(),
David Srbecky6da82472018-10-23 14:03:08 +0100721 shadow_frame.GetMethod());
722 if (UNLIKELY(mh == nullptr)) {
723 HANDLE_PENDING_EXCEPTION();
724 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100725 SetVRegReference(A(), mh);
David Srbecky6da82472018-10-23 14:03:08 +0100726 inst = inst->Next_2xx();
727 }
728 }
729
730 ALWAYS_INLINE void CONST_METHOD_TYPE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100731 ClassLinker* cl = Runtime::Current()->GetClassLinker();
732 ObjPtr<mirror::MethodType> mt = cl->ResolveMethodType(self,
David Srbeckyd6f579c2019-05-29 18:09:30 +0100733 dex::ProtoIndex(B()),
David Srbecky6da82472018-10-23 14:03:08 +0100734 shadow_frame.GetMethod());
735 if (UNLIKELY(mt == nullptr)) {
736 HANDLE_PENDING_EXCEPTION();
737 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100738 SetVRegReference(A(), mt);
David Srbecky6da82472018-10-23 14:03:08 +0100739 inst = inst->Next_2xx();
740 }
741 }
742
743 ALWAYS_INLINE void MONITOR_ENTER() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000744 if (!HandleAsyncException()) {
745 return;
746 }
David Srbecky6baf6442019-05-30 14:57:43 +0100747 ObjPtr<mirror::Object> obj = GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +0100748 if (UNLIKELY(obj == nullptr)) {
749 ThrowNullPointerExceptionFromInterpreter();
750 HANDLE_PENDING_EXCEPTION();
751 } else {
752 DoMonitorEnter<do_assignability_check>(self, &shadow_frame, obj);
753 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
754 }
755 }
756
757 ALWAYS_INLINE void MONITOR_EXIT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000758 if (!HandleAsyncException()) {
759 return;
760 }
David Srbecky6baf6442019-05-30 14:57:43 +0100761 ObjPtr<mirror::Object> obj = GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +0100762 if (UNLIKELY(obj == nullptr)) {
763 ThrowNullPointerExceptionFromInterpreter();
764 HANDLE_PENDING_EXCEPTION();
765 } else {
766 DoMonitorExit<do_assignability_check>(self, &shadow_frame, obj);
767 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
768 }
769 }
770
771 ALWAYS_INLINE void CHECK_CAST() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100772 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(B()),
David Srbecky6da82472018-10-23 14:03:08 +0100773 shadow_frame.GetMethod(),
774 self,
775 false,
776 do_access_check);
777 if (UNLIKELY(c == nullptr)) {
778 HANDLE_PENDING_EXCEPTION();
779 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100780 ObjPtr<mirror::Object> obj = GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +0100781 if (UNLIKELY(obj != nullptr && !obj->InstanceOf(c))) {
782 ThrowClassCastException(c, obj->GetClass());
783 HANDLE_PENDING_EXCEPTION();
784 } else {
785 inst = inst->Next_2xx();
786 }
787 }
788 }
789
790 ALWAYS_INLINE void INSTANCE_OF() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100791 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(C()),
David Srbecky6da82472018-10-23 14:03:08 +0100792 shadow_frame.GetMethod(),
793 self,
794 false,
795 do_access_check);
796 if (UNLIKELY(c == nullptr)) {
797 HANDLE_PENDING_EXCEPTION();
798 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100799 ObjPtr<mirror::Object> obj = GetVRegReference(B());
800 SetVReg(A(), (obj != nullptr && obj->InstanceOf(c)) ? 1 : 0);
David Srbecky6da82472018-10-23 14:03:08 +0100801 inst = inst->Next_2xx();
802 }
803 }
804
805 ALWAYS_INLINE void ARRAY_LENGTH() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100806 ObjPtr<mirror::Object> array = GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +0100807 if (UNLIKELY(array == nullptr)) {
808 ThrowNullPointerExceptionFromInterpreter();
809 HANDLE_PENDING_EXCEPTION();
810 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100811 SetVReg(A(), array->AsArray()->GetLength());
David Srbecky6da82472018-10-23 14:03:08 +0100812 inst = inst->Next_1xx();
813 }
814 }
815
816 ALWAYS_INLINE void NEW_INSTANCE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100817 ObjPtr<mirror::Object> obj = nullptr;
David Srbeckyd6f579c2019-05-29 18:09:30 +0100818 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(B()),
David Srbecky6da82472018-10-23 14:03:08 +0100819 shadow_frame.GetMethod(),
820 self,
821 false,
822 do_access_check);
823 if (LIKELY(c != nullptr)) {
Vladimir Marko9b81ac32019-05-16 16:47:08 +0100824 gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
David Srbecky6da82472018-10-23 14:03:08 +0100825 if (UNLIKELY(c->IsStringClass())) {
Vladimir Marko9b81ac32019-05-16 16:47:08 +0100826 obj = mirror::String::AllocEmptyString(self, allocator_type);
David Srbecky6da82472018-10-23 14:03:08 +0100827 } else {
Vladimir Marko9b81ac32019-05-16 16:47:08 +0100828 obj = AllocObjectFromCode(c, self, allocator_type);
David Srbecky6da82472018-10-23 14:03:08 +0100829 }
830 }
831 if (UNLIKELY(obj == nullptr)) {
832 HANDLE_PENDING_EXCEPTION();
833 } else {
834 obj->GetClass()->AssertInitializedOrInitializingInThread(self);
835 // Don't allow finalizable objects to be allocated during a transaction since these can't
836 // be finalized without a started runtime.
837 if (transaction_active && obj->GetClass()->IsFinalizable()) {
838 AbortTransactionF(self, "Allocating finalizable object in transaction: %s",
839 obj->PrettyTypeOf().c_str());
840 HANDLE_PENDING_EXCEPTION();
841 }
David Srbecky6baf6442019-05-30 14:57:43 +0100842 SetVRegReference(A(), obj);
David Srbecky6da82472018-10-23 14:03:08 +0100843 inst = inst->Next_2xx();
844 }
845 }
846
847 ALWAYS_INLINE void NEW_ARRAY() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100848 int32_t length = GetVReg(B());
Vladimir Marko9b81ac32019-05-16 16:47:08 +0100849 ObjPtr<mirror::Object> obj = AllocArrayFromCode<do_access_check>(
David Srbeckyd6f579c2019-05-29 18:09:30 +0100850 dex::TypeIndex(C()),
David Srbecky6da82472018-10-23 14:03:08 +0100851 length,
852 shadow_frame.GetMethod(),
853 self,
854 Runtime::Current()->GetHeap()->GetCurrentAllocator());
855 if (UNLIKELY(obj == nullptr)) {
856 HANDLE_PENDING_EXCEPTION();
857 } else {
David Srbecky6baf6442019-05-30 14:57:43 +0100858 SetVRegReference(A(), obj);
David Srbecky6da82472018-10-23 14:03:08 +0100859 inst = inst->Next_2xx();
860 }
861 }
862
863 ALWAYS_INLINE void FILLED_NEW_ARRAY() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100864 bool success =
865 DoFilledNewArray<false, do_access_check, transaction_active>(inst, shadow_frame, self,
866 ResultRegister());
867 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
868 }
869
870 ALWAYS_INLINE void FILLED_NEW_ARRAY_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100871 bool success =
872 DoFilledNewArray<true, do_access_check, transaction_active>(inst, shadow_frame,
873 self, ResultRegister());
874 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
875 }
876
877 ALWAYS_INLINE void FILL_ARRAY_DATA() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +0100878 const uint16_t* payload_addr = reinterpret_cast<const uint16_t*>(inst) + B();
David Srbecky6da82472018-10-23 14:03:08 +0100879 const Instruction::ArrayDataPayload* payload =
880 reinterpret_cast<const Instruction::ArrayDataPayload*>(payload_addr);
David Srbecky6baf6442019-05-30 14:57:43 +0100881 ObjPtr<mirror::Object> obj = GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +0100882 bool success = FillArrayData(obj, payload);
883 if (!success) {
884 HANDLE_PENDING_EXCEPTION();
885 }
886 if (transaction_active) {
887 RecordArrayElementsInTransaction(obj->AsArray(), payload->element_count);
888 }
889 inst = inst->Next_3xx();
890 }
891
892 ALWAYS_INLINE void THROW() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000893 if (!HandleAsyncException()) {
894 return;
895 }
David Srbecky6baf6442019-05-30 14:57:43 +0100896 ObjPtr<mirror::Object> exception = GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +0100897 if (UNLIKELY(exception == nullptr)) {
898 ThrowNullPointerException("throw with null exception");
899 } else if (do_assignability_check && !exception->GetClass()->IsThrowableClass()) {
900 // This should never happen.
901 std::string temp;
902 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
903 "Throwing '%s' that is not instance of Throwable",
904 exception->GetClass()->GetDescriptor(&temp));
905 } else {
906 self->SetException(exception->AsThrowable());
907 }
908 HANDLE_PENDING_EXCEPTION();
909 }
910
911 ALWAYS_INLINE void GOTO() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000912 if (!HandleAsyncException()) {
913 return;
914 }
David Srbeckyd6f579c2019-05-29 18:09:30 +0100915 int8_t offset = A();
David Srbecky6da82472018-10-23 14:03:08 +0100916 BRANCH_INSTRUMENTATION(offset);
917 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +0000918 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +0100919 }
920
921 ALWAYS_INLINE void GOTO_16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000922 if (!HandleAsyncException()) {
923 return;
924 }
David Srbeckyd6f579c2019-05-29 18:09:30 +0100925 int16_t offset = A();
David Srbecky6da82472018-10-23 14:03:08 +0100926 BRANCH_INSTRUMENTATION(offset);
927 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +0000928 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +0100929 }
930
931 ALWAYS_INLINE void GOTO_32() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky47ad3762018-10-31 12:43:40 +0000932 if (!HandleAsyncException()) {
933 return;
934 }
David Srbeckyd6f579c2019-05-29 18:09:30 +0100935 int32_t offset = A();
David Srbecky6da82472018-10-23 14:03:08 +0100936 BRANCH_INSTRUMENTATION(offset);
937 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +0000938 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +0100939 }
940
941 ALWAYS_INLINE void PACKED_SWITCH() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100942 int32_t offset = DoPackedSwitch(inst, shadow_frame, inst_data);
943 BRANCH_INSTRUMENTATION(offset);
944 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +0000945 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +0100946 }
947
948 ALWAYS_INLINE void SPARSE_SWITCH() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +0100949 int32_t offset = DoSparseSwitch(inst, shadow_frame, inst_data);
950 BRANCH_INSTRUMENTATION(offset);
951 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +0000952 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +0100953 }
954
955#pragma clang diagnostic push
956#pragma clang diagnostic ignored "-Wfloat-equal"
957
David Srbecky6da82472018-10-23 14:03:08 +0100958 ALWAYS_INLINE void CMPL_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100959 float val1 = GetVRegFloat(B());
960 float val2 = GetVRegFloat(C());
David Srbecky6da82472018-10-23 14:03:08 +0100961 int32_t result;
962 if (val1 > val2) {
963 result = 1;
964 } else if (val1 == val2) {
965 result = 0;
966 } else {
967 result = -1;
968 }
David Srbecky6baf6442019-05-30 14:57:43 +0100969 SetVReg(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +0100970 inst = inst->Next_2xx();
971 }
972
973 ALWAYS_INLINE void CMPG_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100974 float val1 = GetVRegFloat(B());
975 float val2 = GetVRegFloat(C());
David Srbecky6da82472018-10-23 14:03:08 +0100976 int32_t result;
977 if (val1 < val2) {
978 result = -1;
979 } else if (val1 == val2) {
980 result = 0;
981 } else {
982 result = 1;
983 }
David Srbecky6baf6442019-05-30 14:57:43 +0100984 SetVReg(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +0100985 inst = inst->Next_2xx();
986 }
987
988 ALWAYS_INLINE void CMPL_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +0100989 double val1 = GetVRegDouble(B());
990 double val2 = GetVRegDouble(C());
David Srbecky6da82472018-10-23 14:03:08 +0100991 int32_t result;
992 if (val1 > val2) {
993 result = 1;
994 } else if (val1 == val2) {
995 result = 0;
996 } else {
997 result = -1;
998 }
David Srbecky6baf6442019-05-30 14:57:43 +0100999 SetVReg(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +01001000 inst = inst->Next_2xx();
1001 }
1002
David Srbecky6da82472018-10-23 14:03:08 +01001003 ALWAYS_INLINE void CMPG_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001004 double val1 = GetVRegDouble(B());
1005 double val2 = GetVRegDouble(C());
David Srbecky6da82472018-10-23 14:03:08 +01001006 int32_t result;
1007 if (val1 < val2) {
1008 result = -1;
1009 } else if (val1 == val2) {
1010 result = 0;
1011 } else {
1012 result = 1;
1013 }
David Srbecky6baf6442019-05-30 14:57:43 +01001014 SetVReg(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +01001015 inst = inst->Next_2xx();
1016 }
1017
1018#pragma clang diagnostic pop
1019
David Srbecky6da82472018-10-23 14:03:08 +01001020 ALWAYS_INLINE void CMP_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001021 int64_t val1 = GetVRegLong(B());
1022 int64_t val2 = GetVRegLong(C());
David Srbecky6da82472018-10-23 14:03:08 +01001023 int32_t result;
1024 if (val1 > val2) {
1025 result = 1;
1026 } else if (val1 == val2) {
1027 result = 0;
1028 } else {
1029 result = -1;
1030 }
David Srbecky6baf6442019-05-30 14:57:43 +01001031 SetVReg(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +01001032 inst = inst->Next_2xx();
1033 }
1034
1035 ALWAYS_INLINE void IF_EQ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001036 if (GetVReg(A()) == GetVReg(B())) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001037 int16_t offset = C();
David Srbecky6da82472018-10-23 14:03:08 +01001038 BRANCH_INSTRUMENTATION(offset);
1039 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001040 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001041 } else {
1042 BRANCH_INSTRUMENTATION(2);
1043 inst = inst->Next_2xx();
1044 }
1045 }
1046
1047 ALWAYS_INLINE void IF_NE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001048 if (GetVReg(A()) != GetVReg(B())) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001049 int16_t offset = C();
David Srbecky6da82472018-10-23 14:03:08 +01001050 BRANCH_INSTRUMENTATION(offset);
1051 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001052 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001053 } else {
1054 BRANCH_INSTRUMENTATION(2);
1055 inst = inst->Next_2xx();
1056 }
1057 }
1058
1059 ALWAYS_INLINE void IF_LT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001060 if (GetVReg(A()) < GetVReg(B())) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001061 int16_t offset = C();
David Srbecky6da82472018-10-23 14:03:08 +01001062 BRANCH_INSTRUMENTATION(offset);
1063 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001064 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001065 } else {
1066 BRANCH_INSTRUMENTATION(2);
1067 inst = inst->Next_2xx();
1068 }
1069 }
1070
1071 ALWAYS_INLINE void IF_GE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001072 if (GetVReg(A()) >= GetVReg(B())) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001073 int16_t offset = C();
David Srbecky6da82472018-10-23 14:03:08 +01001074 BRANCH_INSTRUMENTATION(offset);
1075 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001076 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001077 } else {
1078 BRANCH_INSTRUMENTATION(2);
1079 inst = inst->Next_2xx();
1080 }
1081 }
1082
1083 ALWAYS_INLINE void IF_GT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001084 if (GetVReg(A()) > GetVReg(B())) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001085 int16_t offset = C();
David Srbecky6da82472018-10-23 14:03:08 +01001086 BRANCH_INSTRUMENTATION(offset);
1087 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001088 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001089 } else {
1090 BRANCH_INSTRUMENTATION(2);
1091 inst = inst->Next_2xx();
1092 }
1093 }
1094
1095 ALWAYS_INLINE void IF_LE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001096 if (GetVReg(A()) <= GetVReg(B())) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001097 int16_t offset = C();
David Srbecky6da82472018-10-23 14:03:08 +01001098 BRANCH_INSTRUMENTATION(offset);
1099 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001100 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001101 } else {
1102 BRANCH_INSTRUMENTATION(2);
1103 inst = inst->Next_2xx();
1104 }
1105 }
1106
1107 ALWAYS_INLINE void IF_EQZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001108 if (GetVReg(A()) == 0) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001109 int16_t offset = B();
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_NEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001120 if (GetVReg(A()) != 0) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001121 int16_t offset = B();
David Srbecky6da82472018-10-23 14:03:08 +01001122 BRANCH_INSTRUMENTATION(offset);
1123 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001124 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001125 } else {
1126 BRANCH_INSTRUMENTATION(2);
1127 inst = inst->Next_2xx();
1128 }
1129 }
1130
1131 ALWAYS_INLINE void IF_LTZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001132 if (GetVReg(A()) < 0) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001133 int16_t offset = B();
David Srbecky6da82472018-10-23 14:03:08 +01001134 BRANCH_INSTRUMENTATION(offset);
1135 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001136 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001137 } else {
1138 BRANCH_INSTRUMENTATION(2);
1139 inst = inst->Next_2xx();
1140 }
1141 }
1142
1143 ALWAYS_INLINE void IF_GEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001144 if (GetVReg(A()) >= 0) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001145 int16_t offset = B();
David Srbecky6da82472018-10-23 14:03:08 +01001146 BRANCH_INSTRUMENTATION(offset);
1147 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001148 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001149 } else {
1150 BRANCH_INSTRUMENTATION(2);
1151 inst = inst->Next_2xx();
1152 }
1153 }
1154
1155 ALWAYS_INLINE void IF_GTZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001156 if (GetVReg(A()) > 0) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001157 int16_t offset = B();
David Srbecky6da82472018-10-23 14:03:08 +01001158 BRANCH_INSTRUMENTATION(offset);
1159 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001160 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001161 } else {
1162 BRANCH_INSTRUMENTATION(2);
1163 inst = inst->Next_2xx();
1164 }
1165 }
1166
1167 ALWAYS_INLINE void IF_LEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001168 if (GetVReg(A()) <= 0) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01001169 int16_t offset = B();
David Srbecky6da82472018-10-23 14:03:08 +01001170 BRANCH_INSTRUMENTATION(offset);
1171 inst = inst->RelativeAt(offset);
David Srbecky47ad3762018-10-31 12:43:40 +00001172 HandleBackwardBranch(offset);
David Srbecky6da82472018-10-23 14:03:08 +01001173 } else {
1174 BRANCH_INSTRUMENTATION(2);
1175 inst = inst->Next_2xx();
1176 }
1177 }
1178
1179 ALWAYS_INLINE void AGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001180 ObjPtr<mirror::Object> a = GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001181 if (UNLIKELY(a == nullptr)) {
1182 ThrowNullPointerExceptionFromInterpreter();
1183 HANDLE_PENDING_EXCEPTION();
1184 }
David Srbecky6baf6442019-05-30 14:57:43 +01001185 int32_t index = GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001186 ObjPtr<mirror::BooleanArray> array = a->AsBooleanArray();
1187 if (array->CheckIsValidIndex(index)) {
David Srbecky6baf6442019-05-30 14:57:43 +01001188 SetVReg(A(), array->GetWithoutChecks(index));
David Srbecky6da82472018-10-23 14:03:08 +01001189 inst = inst->Next_2xx();
1190 } else {
1191 HANDLE_PENDING_EXCEPTION();
1192 }
1193 }
1194
1195 ALWAYS_INLINE void AGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001196 ObjPtr<mirror::Object> a = GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001197 if (UNLIKELY(a == nullptr)) {
1198 ThrowNullPointerExceptionFromInterpreter();
1199 HANDLE_PENDING_EXCEPTION();
1200 }
David Srbecky6baf6442019-05-30 14:57:43 +01001201 int32_t index = GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001202 ObjPtr<mirror::ByteArray> array = a->AsByteArray();
1203 if (array->CheckIsValidIndex(index)) {
David Srbecky6baf6442019-05-30 14:57:43 +01001204 SetVReg(A(), array->GetWithoutChecks(index));
David Srbecky6da82472018-10-23 14:03:08 +01001205 inst = inst->Next_2xx();
1206 } else {
1207 HANDLE_PENDING_EXCEPTION();
1208 }
1209 }
1210
1211 ALWAYS_INLINE void AGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001212 ObjPtr<mirror::Object> a = GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001213 if (UNLIKELY(a == nullptr)) {
1214 ThrowNullPointerExceptionFromInterpreter();
1215 HANDLE_PENDING_EXCEPTION();
1216 }
David Srbecky6baf6442019-05-30 14:57:43 +01001217 int32_t index = GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001218 ObjPtr<mirror::CharArray> array = a->AsCharArray();
1219 if (array->CheckIsValidIndex(index)) {
David Srbecky6baf6442019-05-30 14:57:43 +01001220 SetVReg(A(), array->GetWithoutChecks(index));
David Srbecky6da82472018-10-23 14:03:08 +01001221 inst = inst->Next_2xx();
1222 } else {
1223 HANDLE_PENDING_EXCEPTION();
1224 }
1225 }
1226
1227 ALWAYS_INLINE void AGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001228 ObjPtr<mirror::Object> a = GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001229 if (UNLIKELY(a == nullptr)) {
1230 ThrowNullPointerExceptionFromInterpreter();
1231 HANDLE_PENDING_EXCEPTION();
1232 }
David Srbecky6baf6442019-05-30 14:57:43 +01001233 int32_t index = GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001234 ObjPtr<mirror::ShortArray> array = a->AsShortArray();
1235 if (array->CheckIsValidIndex(index)) {
David Srbecky6baf6442019-05-30 14:57:43 +01001236 SetVReg(A(), array->GetWithoutChecks(index));
David Srbecky6da82472018-10-23 14:03:08 +01001237 inst = inst->Next_2xx();
1238 } else {
1239 HANDLE_PENDING_EXCEPTION();
1240 }
1241 }
1242
1243 ALWAYS_INLINE void AGET() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001244 ObjPtr<mirror::Object> a = GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001245 if (UNLIKELY(a == nullptr)) {
1246 ThrowNullPointerExceptionFromInterpreter();
1247 HANDLE_PENDING_EXCEPTION();
1248 }
David Srbecky6baf6442019-05-30 14:57:43 +01001249 int32_t index = GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001250 DCHECK(a->IsIntArray() || a->IsFloatArray()) << a->PrettyTypeOf();
1251 ObjPtr<mirror::IntArray> array = ObjPtr<mirror::IntArray>::DownCast(a);
1252 if (array->CheckIsValidIndex(index)) {
David Srbecky6baf6442019-05-30 14:57:43 +01001253 SetVReg(A(), array->GetWithoutChecks(index));
David Srbecky6da82472018-10-23 14:03:08 +01001254 inst = inst->Next_2xx();
1255 } else {
1256 HANDLE_PENDING_EXCEPTION();
1257 }
1258 }
1259
1260 ALWAYS_INLINE void AGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001261 ObjPtr<mirror::Object> a = GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001262 if (UNLIKELY(a == nullptr)) {
1263 ThrowNullPointerExceptionFromInterpreter();
1264 HANDLE_PENDING_EXCEPTION();
1265 }
David Srbecky6baf6442019-05-30 14:57:43 +01001266 int32_t index = GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001267 DCHECK(a->IsLongArray() || a->IsDoubleArray()) << a->PrettyTypeOf();
1268 ObjPtr<mirror::LongArray> array = ObjPtr<mirror::LongArray>::DownCast(a);
1269 if (array->CheckIsValidIndex(index)) {
David Srbecky6baf6442019-05-30 14:57:43 +01001270 SetVRegLong(A(), array->GetWithoutChecks(index));
David Srbecky6da82472018-10-23 14:03:08 +01001271 inst = inst->Next_2xx();
1272 } else {
1273 HANDLE_PENDING_EXCEPTION();
1274 }
1275 }
1276
1277 ALWAYS_INLINE void AGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001278 ObjPtr<mirror::Object> a = GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001279 if (UNLIKELY(a == nullptr)) {
1280 ThrowNullPointerExceptionFromInterpreter();
1281 HANDLE_PENDING_EXCEPTION();
1282 }
David Srbecky6baf6442019-05-30 14:57:43 +01001283 int32_t index = GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001284 ObjPtr<mirror::ObjectArray<mirror::Object>> array = a->AsObjectArray<mirror::Object>();
1285 if (array->CheckIsValidIndex(index)) {
David Srbecky6baf6442019-05-30 14:57:43 +01001286 SetVRegReference(A(), array->GetWithoutChecks(index));
David Srbecky6da82472018-10-23 14:03:08 +01001287 inst = inst->Next_2xx();
1288 } else {
1289 HANDLE_PENDING_EXCEPTION();
1290 }
1291 }
1292
1293 ALWAYS_INLINE void APUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001294 ObjPtr<mirror::Object> a = GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001295 if (UNLIKELY(a == nullptr)) {
1296 ThrowNullPointerExceptionFromInterpreter();
1297 HANDLE_PENDING_EXCEPTION();
1298 }
David Srbecky6baf6442019-05-30 14:57:43 +01001299 uint8_t val = GetVReg(A());
1300 int32_t index = GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001301 ObjPtr<mirror::BooleanArray> array = a->AsBooleanArray();
1302 if (array->CheckIsValidIndex(index)) {
1303 array->SetWithoutChecks<transaction_active>(index, val);
1304 inst = inst->Next_2xx();
1305 } else {
1306 HANDLE_PENDING_EXCEPTION();
1307 }
1308 }
1309
1310 ALWAYS_INLINE void APUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001311 ObjPtr<mirror::Object> a = GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001312 if (UNLIKELY(a == nullptr)) {
1313 ThrowNullPointerExceptionFromInterpreter();
1314 HANDLE_PENDING_EXCEPTION();
1315 }
David Srbecky6baf6442019-05-30 14:57:43 +01001316 int8_t val = GetVReg(A());
1317 int32_t index = GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001318 ObjPtr<mirror::ByteArray> array = a->AsByteArray();
1319 if (array->CheckIsValidIndex(index)) {
1320 array->SetWithoutChecks<transaction_active>(index, val);
1321 inst = inst->Next_2xx();
1322 } else {
1323 HANDLE_PENDING_EXCEPTION();
1324 }
1325 }
1326
1327 ALWAYS_INLINE void APUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001328 ObjPtr<mirror::Object> a = GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001329 if (UNLIKELY(a == nullptr)) {
1330 ThrowNullPointerExceptionFromInterpreter();
1331 HANDLE_PENDING_EXCEPTION();
1332 }
David Srbecky6baf6442019-05-30 14:57:43 +01001333 uint16_t val = GetVReg(A());
1334 int32_t index = GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001335 ObjPtr<mirror::CharArray> array = a->AsCharArray();
1336 if (array->CheckIsValidIndex(index)) {
1337 array->SetWithoutChecks<transaction_active>(index, val);
1338 inst = inst->Next_2xx();
1339 } else {
1340 HANDLE_PENDING_EXCEPTION();
1341 }
1342 }
1343
1344 ALWAYS_INLINE void APUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001345 ObjPtr<mirror::Object> a = GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001346 if (UNLIKELY(a == nullptr)) {
1347 ThrowNullPointerExceptionFromInterpreter();
1348 HANDLE_PENDING_EXCEPTION();
1349 }
David Srbecky6baf6442019-05-30 14:57:43 +01001350 int16_t val = GetVReg(A());
1351 int32_t index = GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001352 ObjPtr<mirror::ShortArray> array = a->AsShortArray();
1353 if (array->CheckIsValidIndex(index)) {
1354 array->SetWithoutChecks<transaction_active>(index, val);
1355 inst = inst->Next_2xx();
1356 } else {
1357 HANDLE_PENDING_EXCEPTION();
1358 }
1359 }
1360
1361 ALWAYS_INLINE void APUT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001362 ObjPtr<mirror::Object> a = GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001363 if (UNLIKELY(a == nullptr)) {
1364 ThrowNullPointerExceptionFromInterpreter();
1365 HANDLE_PENDING_EXCEPTION();
1366 }
David Srbecky6baf6442019-05-30 14:57:43 +01001367 int32_t val = GetVReg(A());
1368 int32_t index = GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001369 DCHECK(a->IsIntArray() || a->IsFloatArray()) << a->PrettyTypeOf();
1370 ObjPtr<mirror::IntArray> array = ObjPtr<mirror::IntArray>::DownCast(a);
1371 if (array->CheckIsValidIndex(index)) {
1372 array->SetWithoutChecks<transaction_active>(index, val);
1373 inst = inst->Next_2xx();
1374 } else {
1375 HANDLE_PENDING_EXCEPTION();
1376 }
1377 }
1378
1379 ALWAYS_INLINE void APUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001380 ObjPtr<mirror::Object> a = GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001381 if (UNLIKELY(a == nullptr)) {
1382 ThrowNullPointerExceptionFromInterpreter();
1383 HANDLE_PENDING_EXCEPTION();
1384 }
David Srbecky6baf6442019-05-30 14:57:43 +01001385 int64_t val = GetVRegLong(A());
1386 int32_t index = GetVReg(C());
David Srbecky6da82472018-10-23 14:03:08 +01001387 DCHECK(a->IsLongArray() || a->IsDoubleArray()) << a->PrettyTypeOf();
1388 ObjPtr<mirror::LongArray> array = ObjPtr<mirror::LongArray>::DownCast(a);
1389 if (array->CheckIsValidIndex(index)) {
1390 array->SetWithoutChecks<transaction_active>(index, val);
1391 inst = inst->Next_2xx();
1392 } else {
1393 HANDLE_PENDING_EXCEPTION();
1394 }
1395 }
1396
1397 ALWAYS_INLINE void APUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001398 ObjPtr<mirror::Object> a = GetVRegReference(B());
David Srbecky6da82472018-10-23 14:03:08 +01001399 if (UNLIKELY(a == nullptr)) {
1400 ThrowNullPointerExceptionFromInterpreter();
1401 HANDLE_PENDING_EXCEPTION();
1402 }
David Srbecky6baf6442019-05-30 14:57:43 +01001403 int32_t index = GetVReg(C());
1404 ObjPtr<mirror::Object> val = GetVRegReference(A());
David Srbecky6da82472018-10-23 14:03:08 +01001405 ObjPtr<mirror::ObjectArray<mirror::Object>> array = a->AsObjectArray<mirror::Object>();
1406 if (array->CheckIsValidIndex(index) && array->CheckAssignable(val)) {
1407 array->SetWithoutChecks<transaction_active>(index, val);
1408 inst = inst->Next_2xx();
1409 } else {
1410 HANDLE_PENDING_EXCEPTION();
1411 }
1412 }
1413
1414 ALWAYS_INLINE void IGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001415 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimBoolean, do_access_check>(
1416 self, shadow_frame, inst, inst_data);
1417 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1418 }
1419
1420 ALWAYS_INLINE void IGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001421 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimByte, do_access_check>(
1422 self, shadow_frame, inst, inst_data);
1423 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1424 }
1425
1426 ALWAYS_INLINE void IGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001427 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimChar, do_access_check>(
1428 self, shadow_frame, inst, inst_data);
1429 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1430 }
1431
1432 ALWAYS_INLINE void IGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001433 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimShort, do_access_check>(
1434 self, shadow_frame, inst, inst_data);
1435 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1436 }
1437
1438 ALWAYS_INLINE void IGET() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001439 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimInt, do_access_check>(
1440 self, shadow_frame, inst, inst_data);
1441 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1442 }
1443
1444 ALWAYS_INLINE void IGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001445 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimLong, do_access_check>(
1446 self, shadow_frame, inst, inst_data);
1447 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1448 }
1449
1450 ALWAYS_INLINE void IGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001451 bool success = DoFieldGet<InstanceObjectRead, Primitive::kPrimNot, do_access_check>(
1452 self, shadow_frame, inst, inst_data);
1453 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1454 }
1455
1456 ALWAYS_INLINE void IGET_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001457 bool success = DoIGetQuick<Primitive::kPrimInt>(shadow_frame, inst, inst_data);
1458 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1459 }
1460
1461 ALWAYS_INLINE void IGET_WIDE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001462 bool success = DoIGetQuick<Primitive::kPrimLong>(shadow_frame, inst, inst_data);
1463 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1464 }
1465
1466 ALWAYS_INLINE void IGET_OBJECT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001467 bool success = DoIGetQuick<Primitive::kPrimNot>(shadow_frame, inst, inst_data);
1468 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1469 }
1470
1471 ALWAYS_INLINE void IGET_BOOLEAN_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001472 bool success = DoIGetQuick<Primitive::kPrimBoolean>(shadow_frame, inst, inst_data);
1473 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1474 }
1475
1476 ALWAYS_INLINE void IGET_BYTE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001477 bool success = DoIGetQuick<Primitive::kPrimByte>(shadow_frame, inst, inst_data);
1478 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1479 }
1480
1481 ALWAYS_INLINE void IGET_CHAR_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001482 bool success = DoIGetQuick<Primitive::kPrimChar>(shadow_frame, inst, inst_data);
1483 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1484 }
1485
1486 ALWAYS_INLINE void IGET_SHORT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001487 bool success = DoIGetQuick<Primitive::kPrimShort>(shadow_frame, inst, inst_data);
1488 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1489 }
1490
1491 ALWAYS_INLINE void SGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001492 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimBoolean, do_access_check,
1493 transaction_active>(self, shadow_frame, inst, inst_data);
1494 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1495 }
1496
1497 ALWAYS_INLINE void SGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001498 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimByte, do_access_check,
1499 transaction_active>(self, shadow_frame, inst, inst_data);
1500 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1501 }
1502
1503 ALWAYS_INLINE void SGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001504 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimChar, do_access_check,
1505 transaction_active>(self, shadow_frame, inst, inst_data);
1506 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1507 }
1508
1509 ALWAYS_INLINE void SGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001510 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimShort, do_access_check,
1511 transaction_active>(self, shadow_frame, inst, inst_data);
1512 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1513 }
1514
1515 ALWAYS_INLINE void SGET() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001516 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimInt, do_access_check,
1517 transaction_active>(self, shadow_frame, inst, inst_data);
1518 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1519 }
1520
1521 ALWAYS_INLINE void SGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001522 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimLong, do_access_check,
1523 transaction_active>(self, shadow_frame, inst, inst_data);
1524 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1525 }
1526
1527 ALWAYS_INLINE void SGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001528 bool success = DoFieldGet<StaticObjectRead, Primitive::kPrimNot, do_access_check,
1529 transaction_active>(self, shadow_frame, inst, inst_data);
1530 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1531 }
1532
1533 ALWAYS_INLINE void IPUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001534 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimBoolean, do_access_check,
1535 transaction_active>(self, shadow_frame, inst, inst_data);
1536 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1537 }
1538
1539 ALWAYS_INLINE void IPUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001540 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimByte, do_access_check,
1541 transaction_active>(self, shadow_frame, inst, inst_data);
1542 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1543 }
1544
1545 ALWAYS_INLINE void IPUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001546 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimChar, do_access_check,
1547 transaction_active>(self, shadow_frame, inst, inst_data);
1548 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1549 }
1550
1551 ALWAYS_INLINE void IPUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001552 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimShort, do_access_check,
1553 transaction_active>(self, shadow_frame, inst, inst_data);
1554 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1555 }
1556
1557 ALWAYS_INLINE void IPUT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001558 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimInt, do_access_check,
1559 transaction_active>(self, shadow_frame, inst, inst_data);
1560 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1561 }
1562
1563 ALWAYS_INLINE void IPUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001564 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimLong, do_access_check,
1565 transaction_active>(self, shadow_frame, inst, inst_data);
1566 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1567 }
1568
1569 ALWAYS_INLINE void IPUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001570 bool success = DoFieldPut<InstanceObjectWrite, Primitive::kPrimNot, do_access_check,
1571 transaction_active>(self, shadow_frame, inst, inst_data);
1572 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1573 }
1574
1575 ALWAYS_INLINE void IPUT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001576 bool success = DoIPutQuick<Primitive::kPrimInt, transaction_active>(
1577 shadow_frame, inst, inst_data);
1578 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1579 }
1580
1581 ALWAYS_INLINE void IPUT_BOOLEAN_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001582 bool success = DoIPutQuick<Primitive::kPrimBoolean, transaction_active>(
1583 shadow_frame, inst, inst_data);
1584 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1585 }
1586
1587 ALWAYS_INLINE void IPUT_BYTE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001588 bool success = DoIPutQuick<Primitive::kPrimByte, transaction_active>(
1589 shadow_frame, inst, inst_data);
1590 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1591 }
1592
1593 ALWAYS_INLINE void IPUT_CHAR_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001594 bool success = DoIPutQuick<Primitive::kPrimChar, transaction_active>(
1595 shadow_frame, inst, inst_data);
1596 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1597 }
1598
1599 ALWAYS_INLINE void IPUT_SHORT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001600 bool success = DoIPutQuick<Primitive::kPrimShort, transaction_active>(
1601 shadow_frame, inst, inst_data);
1602 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1603 }
1604
1605 ALWAYS_INLINE void IPUT_WIDE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001606 bool success = DoIPutQuick<Primitive::kPrimLong, transaction_active>(
1607 shadow_frame, inst, inst_data);
1608 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1609 }
1610
1611 ALWAYS_INLINE void IPUT_OBJECT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001612 bool success = DoIPutQuick<Primitive::kPrimNot, transaction_active>(
1613 shadow_frame, inst, inst_data);
1614 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1615 }
1616
1617 ALWAYS_INLINE void SPUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001618 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimBoolean, do_access_check,
1619 transaction_active>(self, shadow_frame, inst, inst_data);
1620 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1621 }
1622
1623 ALWAYS_INLINE void SPUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001624 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimByte, do_access_check,
1625 transaction_active>(self, shadow_frame, inst, inst_data);
1626 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1627 }
1628
1629 ALWAYS_INLINE void SPUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001630 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimChar, do_access_check,
1631 transaction_active>(self, shadow_frame, inst, inst_data);
1632 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1633 }
1634
1635 ALWAYS_INLINE void SPUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001636 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimShort, do_access_check,
1637 transaction_active>(self, shadow_frame, inst, inst_data);
1638 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1639 }
1640
1641 ALWAYS_INLINE void SPUT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001642 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimInt, do_access_check,
1643 transaction_active>(self, shadow_frame, inst, inst_data);
1644 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1645 }
1646
1647 ALWAYS_INLINE void SPUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001648 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimLong, do_access_check,
1649 transaction_active>(self, shadow_frame, inst, inst_data);
1650 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1651 }
1652
1653 ALWAYS_INLINE void SPUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001654 bool success = DoFieldPut<StaticObjectWrite, Primitive::kPrimNot, do_access_check,
1655 transaction_active>(self, shadow_frame, inst, inst_data);
1656 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1657 }
1658
1659 ALWAYS_INLINE void INVOKE_VIRTUAL() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001660 bool success = DoInvoke<kVirtual, false, do_access_check, /*is_mterp=*/ false>(
1661 self, shadow_frame, inst, inst_data, ResultRegister());
1662 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1663 }
1664
1665 ALWAYS_INLINE void INVOKE_VIRTUAL_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001666 bool success = DoInvoke<kVirtual, true, do_access_check, /*is_mterp=*/ false>(
1667 self, shadow_frame, inst, inst_data, ResultRegister());
1668 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1669 }
1670
1671 ALWAYS_INLINE void INVOKE_SUPER() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001672 bool success = DoInvoke<kSuper, false, do_access_check, /*is_mterp=*/ false>(
1673 self, shadow_frame, inst, inst_data, ResultRegister());
1674 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1675 }
1676
1677 ALWAYS_INLINE void INVOKE_SUPER_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001678 bool success = DoInvoke<kSuper, true, do_access_check, /*is_mterp=*/ false>(
1679 self, shadow_frame, inst, inst_data, ResultRegister());
1680 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1681 }
1682
1683 ALWAYS_INLINE void INVOKE_DIRECT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001684 bool success = DoInvoke<kDirect, false, do_access_check, /*is_mterp=*/ false>(
1685 self, shadow_frame, inst, inst_data, ResultRegister());
1686 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1687 }
1688
1689 ALWAYS_INLINE void INVOKE_DIRECT_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001690 bool success = DoInvoke<kDirect, true, do_access_check, /*is_mterp=*/ false>(
1691 self, shadow_frame, inst, inst_data, ResultRegister());
1692 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1693 }
1694
1695 ALWAYS_INLINE void INVOKE_INTERFACE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001696 bool success = DoInvoke<kInterface, false, do_access_check, /*is_mterp=*/ false>(
1697 self, shadow_frame, inst, inst_data, ResultRegister());
1698 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1699 }
1700
1701 ALWAYS_INLINE void INVOKE_INTERFACE_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001702 bool success = DoInvoke<kInterface, true, do_access_check, /*is_mterp=*/ false>(
1703 self, shadow_frame, inst, inst_data, ResultRegister());
1704 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1705 }
1706
1707 ALWAYS_INLINE void INVOKE_STATIC() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001708 bool success = DoInvoke<kStatic, false, do_access_check, /*is_mterp=*/ false>(
1709 self, shadow_frame, inst, inst_data, ResultRegister());
1710 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1711 }
1712
1713 ALWAYS_INLINE void INVOKE_STATIC_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001714 bool success = DoInvoke<kStatic, true, do_access_check, /*is_mterp=*/ false>(
1715 self, shadow_frame, inst, inst_data, ResultRegister());
1716 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1717 }
1718
1719 ALWAYS_INLINE void INVOKE_VIRTUAL_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001720 bool success = DoInvoke<kVirtual, false, do_access_check, /*is_mterp=*/ false,
1721 /*is_quick=*/ true>(self, shadow_frame, inst, inst_data, ResultRegister());
1722 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1723 }
1724
1725 ALWAYS_INLINE void INVOKE_VIRTUAL_RANGE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001726 bool success = DoInvoke<kVirtual, true, do_access_check, /*is_mterp=*/ false,
1727 /*is_quick=*/ true>(self, shadow_frame, inst, inst_data, ResultRegister());
1728 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1729 }
1730
1731 ALWAYS_INLINE void INVOKE_POLYMORPHIC() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001732 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1733 bool success = DoInvokePolymorphic</* is_range= */ false>(
1734 self, shadow_frame, inst, inst_data, ResultRegister());
1735 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(!success);
1736 }
1737
1738 ALWAYS_INLINE void INVOKE_POLYMORPHIC_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001739 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1740 bool success = DoInvokePolymorphic</* is_range= */ true>(
1741 self, shadow_frame, inst, inst_data, ResultRegister());
1742 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(!success);
1743 }
1744
1745 ALWAYS_INLINE void INVOKE_CUSTOM() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001746 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1747 bool success = DoInvokeCustom</* is_range= */ false>(
1748 self, shadow_frame, inst, inst_data, ResultRegister());
1749 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1750 }
1751
1752 ALWAYS_INLINE void INVOKE_CUSTOM_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6da82472018-10-23 14:03:08 +01001753 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1754 bool success = DoInvokeCustom</* is_range= */ true>(
1755 self, shadow_frame, inst, inst_data, ResultRegister());
1756 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1757 }
1758
1759 ALWAYS_INLINE void NEG_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001760 SetVReg(A(), -GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001761 inst = inst->Next_1xx();
1762 }
1763
1764 ALWAYS_INLINE void NOT_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001765 SetVReg(A(), ~GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001766 inst = inst->Next_1xx();
1767 }
1768
1769 ALWAYS_INLINE void NEG_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001770 SetVRegLong(A(), -GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001771 inst = inst->Next_1xx();
1772 }
1773
1774 ALWAYS_INLINE void NOT_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001775 SetVRegLong(A(), ~GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001776 inst = inst->Next_1xx();
1777 }
1778
1779 ALWAYS_INLINE void NEG_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001780 SetVRegFloat(A(), -GetVRegFloat(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001781 inst = inst->Next_1xx();
1782 }
1783
1784 ALWAYS_INLINE void NEG_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001785 SetVRegDouble(A(), -GetVRegDouble(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001786 inst = inst->Next_1xx();
1787 }
1788
1789 ALWAYS_INLINE void INT_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001790 SetVRegLong(A(), GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001791 inst = inst->Next_1xx();
1792 }
1793
1794 ALWAYS_INLINE void INT_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001795 SetVRegFloat(A(), GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001796 inst = inst->Next_1xx();
1797 }
1798
1799 ALWAYS_INLINE void INT_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001800 SetVRegDouble(A(), GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001801 inst = inst->Next_1xx();
1802 }
1803
1804 ALWAYS_INLINE void LONG_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001805 SetVReg(A(), GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001806 inst = inst->Next_1xx();
1807 }
1808
1809 ALWAYS_INLINE void LONG_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001810 SetVRegFloat(A(), GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001811 inst = inst->Next_1xx();
1812 }
1813
1814 ALWAYS_INLINE void LONG_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001815 SetVRegDouble(A(), GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001816 inst = inst->Next_1xx();
1817 }
1818
1819 ALWAYS_INLINE void FLOAT_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001820 float val = GetVRegFloat(B());
David Srbecky6da82472018-10-23 14:03:08 +01001821 int32_t result = art_float_to_integral<int32_t, float>(val);
David Srbecky6baf6442019-05-30 14:57:43 +01001822 SetVReg(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +01001823 inst = inst->Next_1xx();
1824 }
1825
1826 ALWAYS_INLINE void FLOAT_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001827 float val = GetVRegFloat(B());
David Srbecky6da82472018-10-23 14:03:08 +01001828 int64_t result = art_float_to_integral<int64_t, float>(val);
David Srbecky6baf6442019-05-30 14:57:43 +01001829 SetVRegLong(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +01001830 inst = inst->Next_1xx();
1831 }
1832
1833 ALWAYS_INLINE void FLOAT_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001834 SetVRegDouble(A(), GetVRegFloat(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001835 inst = inst->Next_1xx();
1836 }
1837
1838 ALWAYS_INLINE void DOUBLE_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001839 double val = GetVRegDouble(B());
David Srbecky6da82472018-10-23 14:03:08 +01001840 int32_t result = art_float_to_integral<int32_t, double>(val);
David Srbecky6baf6442019-05-30 14:57:43 +01001841 SetVReg(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +01001842 inst = inst->Next_1xx();
1843 }
1844
1845 ALWAYS_INLINE void DOUBLE_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001846 double val = GetVRegDouble(B());
David Srbecky6da82472018-10-23 14:03:08 +01001847 int64_t result = art_float_to_integral<int64_t, double>(val);
David Srbecky6baf6442019-05-30 14:57:43 +01001848 SetVRegLong(A(), result);
David Srbecky6da82472018-10-23 14:03:08 +01001849 inst = inst->Next_1xx();
1850 }
1851
1852 ALWAYS_INLINE void DOUBLE_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001853 SetVRegFloat(A(), GetVRegDouble(B()));
David Srbecky6da82472018-10-23 14:03:08 +01001854 inst = inst->Next_1xx();
1855 }
1856
1857 ALWAYS_INLINE void INT_TO_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001858 SetVReg(A(), static_cast<int8_t>(GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01001859 inst = inst->Next_1xx();
1860 }
1861
1862 ALWAYS_INLINE void INT_TO_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001863 SetVReg(A(), static_cast<uint16_t>(GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01001864 inst = inst->Next_1xx();
1865 }
1866
1867 ALWAYS_INLINE void INT_TO_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001868 SetVReg(A(), static_cast<int16_t>(GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01001869 inst = inst->Next_1xx();
1870 }
1871
1872 ALWAYS_INLINE void ADD_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001873 SetVReg(A(), SafeAdd(GetVReg(B()), GetVReg(C())));
David Srbecky6da82472018-10-23 14:03:08 +01001874 inst = inst->Next_2xx();
1875 }
1876
1877 ALWAYS_INLINE void SUB_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001878 SetVReg(A(), SafeSub(GetVReg(B()), GetVReg(C())));
David Srbecky6da82472018-10-23 14:03:08 +01001879 inst = inst->Next_2xx();
1880 }
1881
1882 ALWAYS_INLINE void MUL_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001883 SetVReg(A(), SafeMul(GetVReg(B()), GetVReg(C())));
David Srbecky6da82472018-10-23 14:03:08 +01001884 inst = inst->Next_2xx();
1885 }
1886
1887 ALWAYS_INLINE void DIV_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001888 bool success = DoIntDivide(shadow_frame, A(), GetVReg(B()), GetVReg(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001889 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1890 }
1891
1892 ALWAYS_INLINE void REM_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001893 bool success = DoIntRemainder(shadow_frame, A(), GetVReg(B()), GetVReg(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001894 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1895 }
1896
1897 ALWAYS_INLINE void SHL_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001898 SetVReg(A(), GetVReg(B()) << (GetVReg(C()) & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01001899 inst = inst->Next_2xx();
1900 }
1901
1902 ALWAYS_INLINE void SHR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001903 SetVReg(A(), GetVReg(B()) >> (GetVReg(C()) & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01001904 inst = inst->Next_2xx();
1905 }
1906
1907 ALWAYS_INLINE void USHR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001908 SetVReg(A(), static_cast<uint32_t>(GetVReg(B())) >> (GetVReg(C()) & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01001909 inst = inst->Next_2xx();
1910 }
1911
1912 ALWAYS_INLINE void AND_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001913 SetVReg(A(), GetVReg(B()) & GetVReg(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001914 inst = inst->Next_2xx();
1915 }
1916
1917 ALWAYS_INLINE void OR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001918 SetVReg(A(), GetVReg(B()) | GetVReg(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001919 inst = inst->Next_2xx();
1920 }
1921
1922 ALWAYS_INLINE void XOR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001923 SetVReg(A(), GetVReg(B()) ^ GetVReg(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001924 inst = inst->Next_2xx();
1925 }
1926
1927 ALWAYS_INLINE void ADD_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001928 SetVRegLong(A(), SafeAdd(GetVRegLong(B()), GetVRegLong(C())));
David Srbecky6da82472018-10-23 14:03:08 +01001929 inst = inst->Next_2xx();
1930 }
1931
1932 ALWAYS_INLINE void SUB_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001933 SetVRegLong(A(), SafeSub(GetVRegLong(B()), GetVRegLong(C())));
David Srbecky6da82472018-10-23 14:03:08 +01001934 inst = inst->Next_2xx();
1935 }
1936
1937 ALWAYS_INLINE void MUL_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001938 SetVRegLong(A(), SafeMul(GetVRegLong(B()), GetVRegLong(C())));
David Srbecky6da82472018-10-23 14:03:08 +01001939 inst = inst->Next_2xx();
1940 }
1941
1942 ALWAYS_INLINE void DIV_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001943 DoLongDivide(shadow_frame, A(), GetVRegLong(B()), GetVRegLong(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001944 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_2xx);
1945 }
1946
1947 ALWAYS_INLINE void REM_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001948 DoLongRemainder(shadow_frame, A(), GetVRegLong(B()), GetVRegLong(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001949 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_2xx);
1950 }
1951
1952 ALWAYS_INLINE void AND_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001953 SetVRegLong(A(), GetVRegLong(B()) & GetVRegLong(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001954 inst = inst->Next_2xx();
1955 }
1956
1957 ALWAYS_INLINE void OR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001958 SetVRegLong(A(), GetVRegLong(B()) | GetVRegLong(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001959 inst = inst->Next_2xx();
1960 }
1961
1962 ALWAYS_INLINE void XOR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001963 SetVRegLong(A(), GetVRegLong(B()) ^ GetVRegLong(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001964 inst = inst->Next_2xx();
1965 }
1966
1967 ALWAYS_INLINE void SHL_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001968 SetVRegLong(A(), GetVRegLong(B()) << (GetVReg(C()) & 0x3f));
David Srbecky6da82472018-10-23 14:03:08 +01001969 inst = inst->Next_2xx();
1970 }
1971
1972 ALWAYS_INLINE void SHR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001973 SetVRegLong(A(), GetVRegLong(B()) >> (GetVReg(C()) & 0x3f));
David Srbecky6da82472018-10-23 14:03:08 +01001974 inst = inst->Next_2xx();
1975 }
1976
1977 ALWAYS_INLINE void USHR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001978 SetVRegLong(A(), static_cast<uint64_t>(GetVRegLong(B())) >> (GetVReg(C()) & 0x3f));
David Srbecky6da82472018-10-23 14:03:08 +01001979 inst = inst->Next_2xx();
1980 }
1981
1982 ALWAYS_INLINE void ADD_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001983 SetVRegFloat(A(), GetVRegFloat(B()) + GetVRegFloat(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001984 inst = inst->Next_2xx();
1985 }
1986
1987 ALWAYS_INLINE void SUB_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001988 SetVRegFloat(A(), GetVRegFloat(B()) - GetVRegFloat(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001989 inst = inst->Next_2xx();
1990 }
1991
1992 ALWAYS_INLINE void MUL_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001993 SetVRegFloat(A(), GetVRegFloat(B()) * GetVRegFloat(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001994 inst = inst->Next_2xx();
1995 }
1996
1997 ALWAYS_INLINE void DIV_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01001998 SetVRegFloat(A(), GetVRegFloat(B()) / GetVRegFloat(C()));
David Srbecky6da82472018-10-23 14:03:08 +01001999 inst = inst->Next_2xx();
2000 }
2001
2002 ALWAYS_INLINE void REM_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002003 SetVRegFloat(A(), fmodf(GetVRegFloat(B()), GetVRegFloat(C())));
David Srbecky6da82472018-10-23 14:03:08 +01002004 inst = inst->Next_2xx();
2005 }
2006
2007 ALWAYS_INLINE void ADD_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002008 SetVRegDouble(A(), GetVRegDouble(B()) + GetVRegDouble(C()));
David Srbecky6da82472018-10-23 14:03:08 +01002009 inst = inst->Next_2xx();
2010 }
2011
2012 ALWAYS_INLINE void SUB_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002013 SetVRegDouble(A(), GetVRegDouble(B()) - GetVRegDouble(C()));
David Srbecky6da82472018-10-23 14:03:08 +01002014 inst = inst->Next_2xx();
2015 }
2016
2017 ALWAYS_INLINE void MUL_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002018 SetVRegDouble(A(), GetVRegDouble(B()) * GetVRegDouble(C()));
David Srbecky6da82472018-10-23 14:03:08 +01002019 inst = inst->Next_2xx();
2020 }
2021
2022 ALWAYS_INLINE void DIV_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002023 SetVRegDouble(A(), GetVRegDouble(B()) / GetVRegDouble(C()));
David Srbecky6da82472018-10-23 14:03:08 +01002024 inst = inst->Next_2xx();
2025 }
2026
2027 ALWAYS_INLINE void REM_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002028 SetVRegDouble(A(), fmod(GetVRegDouble(B()), GetVRegDouble(C())));
David Srbecky6da82472018-10-23 14:03:08 +01002029 inst = inst->Next_2xx();
2030 }
2031
2032 ALWAYS_INLINE void ADD_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002033 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002034 SetVReg(vregA, SafeAdd(GetVReg(vregA), GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002035 inst = inst->Next_1xx();
2036 }
2037
2038 ALWAYS_INLINE void SUB_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002039 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002040 SetVReg(vregA, SafeSub(GetVReg(vregA), GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002041 inst = inst->Next_1xx();
2042 }
2043
2044 ALWAYS_INLINE void MUL_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002045 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002046 SetVReg(vregA, SafeMul(GetVReg(vregA), GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002047 inst = inst->Next_1xx();
2048 }
2049
2050 ALWAYS_INLINE void DIV_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002051 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002052 bool success = DoIntDivide(shadow_frame, vregA, GetVReg(vregA), GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002053 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_1xx);
2054 }
2055
2056 ALWAYS_INLINE void REM_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002057 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002058 bool success = DoIntRemainder(shadow_frame, vregA, GetVReg(vregA), GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002059 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_1xx);
2060 }
2061
2062 ALWAYS_INLINE void SHL_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002063 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002064 SetVReg(vregA, GetVReg(vregA) << (GetVReg(B()) & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01002065 inst = inst->Next_1xx();
2066 }
2067
2068 ALWAYS_INLINE void SHR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002069 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002070 SetVReg(vregA, GetVReg(vregA) >> (GetVReg(B()) & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01002071 inst = inst->Next_1xx();
2072 }
2073
2074 ALWAYS_INLINE void USHR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002075 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002076 SetVReg(vregA, static_cast<uint32_t>(GetVReg(vregA)) >> (GetVReg(B()) & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01002077 inst = inst->Next_1xx();
2078 }
2079
2080 ALWAYS_INLINE void AND_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002081 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002082 SetVReg(vregA, GetVReg(vregA) & GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002083 inst = inst->Next_1xx();
2084 }
2085
2086 ALWAYS_INLINE void OR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002087 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002088 SetVReg(vregA, GetVReg(vregA) | GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002089 inst = inst->Next_1xx();
2090 }
2091
2092 ALWAYS_INLINE void XOR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002093 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002094 SetVReg(vregA, GetVReg(vregA) ^ GetVReg(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002095 inst = inst->Next_1xx();
2096 }
2097
2098 ALWAYS_INLINE void ADD_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002099 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002100 SetVRegLong(vregA, SafeAdd(GetVRegLong(vregA), GetVRegLong(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002101 inst = inst->Next_1xx();
2102 }
2103
2104 ALWAYS_INLINE void SUB_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002105 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002106 SetVRegLong(vregA, SafeSub(GetVRegLong(vregA), GetVRegLong(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002107 inst = inst->Next_1xx();
2108 }
2109
2110 ALWAYS_INLINE void MUL_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002111 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002112 SetVRegLong(vregA, SafeMul(GetVRegLong(vregA), GetVRegLong(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002113 inst = inst->Next_1xx();
2114 }
2115
2116 ALWAYS_INLINE void DIV_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002117 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002118 DoLongDivide(shadow_frame, vregA, GetVRegLong(vregA), GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002119 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
2120 }
2121
2122 ALWAYS_INLINE void REM_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002123 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002124 DoLongRemainder(shadow_frame, vregA, GetVRegLong(vregA), GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002125 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
2126 }
2127
2128 ALWAYS_INLINE void AND_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002129 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002130 SetVRegLong(vregA, GetVRegLong(vregA) & GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002131 inst = inst->Next_1xx();
2132 }
2133
2134 ALWAYS_INLINE void OR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002135 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002136 SetVRegLong(vregA, GetVRegLong(vregA) | GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002137 inst = inst->Next_1xx();
2138 }
2139
2140 ALWAYS_INLINE void XOR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002141 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002142 SetVRegLong(vregA, GetVRegLong(vregA) ^ GetVRegLong(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002143 inst = inst->Next_1xx();
2144 }
2145
2146 ALWAYS_INLINE void SHL_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002147 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002148 SetVRegLong(vregA, GetVRegLong(vregA) << (GetVReg(B()) & 0x3f));
David Srbecky6da82472018-10-23 14:03:08 +01002149 inst = inst->Next_1xx();
2150 }
2151
2152 ALWAYS_INLINE void SHR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002153 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002154 SetVRegLong(vregA, GetVRegLong(vregA) >> (GetVReg(B()) & 0x3f));
David Srbecky6da82472018-10-23 14:03:08 +01002155 inst = inst->Next_1xx();
2156 }
2157
2158 ALWAYS_INLINE void USHR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002159 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002160 SetVRegLong(vregA, static_cast<uint64_t>(GetVRegLong(vregA)) >> (GetVReg(B()) & 0x3f));
David Srbecky6da82472018-10-23 14:03:08 +01002161 inst = inst->Next_1xx();
2162 }
2163
2164 ALWAYS_INLINE void ADD_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002165 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002166 SetVRegFloat(vregA, GetVRegFloat(vregA) + GetVRegFloat(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002167 inst = inst->Next_1xx();
2168 }
2169
2170 ALWAYS_INLINE void SUB_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002171 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002172 SetVRegFloat(vregA, GetVRegFloat(vregA) - GetVRegFloat(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002173 inst = inst->Next_1xx();
2174 }
2175
2176 ALWAYS_INLINE void MUL_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002177 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002178 SetVRegFloat(vregA, GetVRegFloat(vregA) * GetVRegFloat(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002179 inst = inst->Next_1xx();
2180 }
2181
2182 ALWAYS_INLINE void DIV_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002183 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002184 SetVRegFloat(vregA, GetVRegFloat(vregA) / GetVRegFloat(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002185 inst = inst->Next_1xx();
2186 }
2187
2188 ALWAYS_INLINE void REM_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002189 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002190 SetVRegFloat(vregA, fmodf(GetVRegFloat(vregA), GetVRegFloat(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002191 inst = inst->Next_1xx();
2192 }
2193
2194 ALWAYS_INLINE void ADD_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002195 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002196 SetVRegDouble(vregA, GetVRegDouble(vregA) + GetVRegDouble(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002197 inst = inst->Next_1xx();
2198 }
2199
2200 ALWAYS_INLINE void SUB_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002201 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002202 SetVRegDouble(vregA, GetVRegDouble(vregA) - GetVRegDouble(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002203 inst = inst->Next_1xx();
2204 }
2205
2206 ALWAYS_INLINE void MUL_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002207 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002208 SetVRegDouble(vregA, GetVRegDouble(vregA) * GetVRegDouble(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002209 inst = inst->Next_1xx();
2210 }
2211
2212 ALWAYS_INLINE void DIV_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002213 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002214 SetVRegDouble(vregA, GetVRegDouble(vregA) / GetVRegDouble(B()));
David Srbecky6da82472018-10-23 14:03:08 +01002215 inst = inst->Next_1xx();
2216 }
2217
2218 ALWAYS_INLINE void REM_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbeckyd6f579c2019-05-29 18:09:30 +01002219 uint4_t vregA = A();
David Srbecky6baf6442019-05-30 14:57:43 +01002220 SetVRegDouble(vregA, fmod(GetVRegDouble(vregA), GetVRegDouble(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002221 inst = inst->Next_1xx();
2222 }
2223
2224 ALWAYS_INLINE void ADD_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002225 SetVReg(A(), SafeAdd(GetVReg(B()), C()));
David Srbecky6da82472018-10-23 14:03:08 +01002226 inst = inst->Next_2xx();
2227 }
2228
2229 ALWAYS_INLINE void RSUB_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002230 SetVReg(A(), SafeSub(C(), GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002231 inst = inst->Next_2xx();
2232 }
2233
2234 ALWAYS_INLINE void MUL_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002235 SetVReg(A(), SafeMul(GetVReg(B()), C()));
David Srbecky6da82472018-10-23 14:03:08 +01002236 inst = inst->Next_2xx();
2237 }
2238
2239 ALWAYS_INLINE void DIV_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002240 bool success = DoIntDivide(shadow_frame, A(), GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +01002241 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
2242 }
2243
2244 ALWAYS_INLINE void REM_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002245 bool success = DoIntRemainder(shadow_frame, A(), GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +01002246 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
2247 }
2248
2249 ALWAYS_INLINE void AND_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002250 SetVReg(A(), GetVReg(B()) & C());
David Srbecky6da82472018-10-23 14:03:08 +01002251 inst = inst->Next_2xx();
2252 }
2253
2254 ALWAYS_INLINE void OR_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002255 SetVReg(A(), GetVReg(B()) | C());
David Srbecky6da82472018-10-23 14:03:08 +01002256 inst = inst->Next_2xx();
2257 }
2258
2259 ALWAYS_INLINE void XOR_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002260 SetVReg(A(), GetVReg(B()) ^ C());
David Srbecky6da82472018-10-23 14:03:08 +01002261 inst = inst->Next_2xx();
2262 }
2263
2264 ALWAYS_INLINE void ADD_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002265 SetVReg(A(), SafeAdd(GetVReg(B()), C()));
David Srbecky6da82472018-10-23 14:03:08 +01002266 inst = inst->Next_2xx();
2267 }
2268
2269 ALWAYS_INLINE void RSUB_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002270 SetVReg(A(), SafeSub(C(), GetVReg(B())));
David Srbecky6da82472018-10-23 14:03:08 +01002271 inst = inst->Next_2xx();
2272 }
2273
2274 ALWAYS_INLINE void MUL_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002275 SetVReg(A(), SafeMul(GetVReg(B()), C()));
David Srbecky6da82472018-10-23 14:03:08 +01002276 inst = inst->Next_2xx();
2277 }
2278
2279 ALWAYS_INLINE void DIV_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002280 bool success = DoIntDivide(shadow_frame, A(), GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +01002281 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
2282 }
2283
2284 ALWAYS_INLINE void REM_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002285 bool success = DoIntRemainder(shadow_frame, A(), GetVReg(B()), C());
David Srbecky6da82472018-10-23 14:03:08 +01002286 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
2287 }
2288
2289 ALWAYS_INLINE void AND_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002290 SetVReg(A(), GetVReg(B()) & C());
David Srbecky6da82472018-10-23 14:03:08 +01002291 inst = inst->Next_2xx();
2292 }
2293
2294 ALWAYS_INLINE void OR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002295 SetVReg(A(), GetVReg(B()) | C());
David Srbecky6da82472018-10-23 14:03:08 +01002296 inst = inst->Next_2xx();
2297 }
2298
2299 ALWAYS_INLINE void XOR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002300 SetVReg(A(), GetVReg(B()) ^ C());
David Srbecky6da82472018-10-23 14:03:08 +01002301 inst = inst->Next_2xx();
2302 }
2303
2304 ALWAYS_INLINE void SHL_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002305 SetVReg(A(), GetVReg(B()) << (C() & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01002306 inst = inst->Next_2xx();
2307 }
2308
2309 ALWAYS_INLINE void SHR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002310 SetVReg(A(), GetVReg(B()) >> (C() & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01002311 inst = inst->Next_2xx();
2312 }
2313
2314 ALWAYS_INLINE void USHR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
David Srbecky6baf6442019-05-30 14:57:43 +01002315 SetVReg(A(), static_cast<uint32_t>(GetVReg(B())) >> (C() & 0x1f));
David Srbecky6da82472018-10-23 14:03:08 +01002316 inst = inst->Next_2xx();
2317 }
2318
2319 ALWAYS_INLINE void UNUSED_3E() REQUIRES_SHARED(Locks::mutator_lock_) {
2320 UnexpectedOpcode(inst, shadow_frame);
2321 }
2322
2323 ALWAYS_INLINE void UNUSED_3F() REQUIRES_SHARED(Locks::mutator_lock_) {
2324 UnexpectedOpcode(inst, shadow_frame);
2325 }
2326
2327 ALWAYS_INLINE void UNUSED_40() REQUIRES_SHARED(Locks::mutator_lock_) {
2328 UnexpectedOpcode(inst, shadow_frame);
2329 }
2330
2331 ALWAYS_INLINE void UNUSED_41() REQUIRES_SHARED(Locks::mutator_lock_) {
2332 UnexpectedOpcode(inst, shadow_frame);
2333 }
2334
2335 ALWAYS_INLINE void UNUSED_42() REQUIRES_SHARED(Locks::mutator_lock_) {
2336 UnexpectedOpcode(inst, shadow_frame);
2337 }
2338
2339 ALWAYS_INLINE void UNUSED_43() REQUIRES_SHARED(Locks::mutator_lock_) {
2340 UnexpectedOpcode(inst, shadow_frame);
2341 }
2342
2343 ALWAYS_INLINE void UNUSED_79() REQUIRES_SHARED(Locks::mutator_lock_) {
2344 UnexpectedOpcode(inst, shadow_frame);
2345 }
2346
2347 ALWAYS_INLINE void UNUSED_7A() REQUIRES_SHARED(Locks::mutator_lock_) {
2348 UnexpectedOpcode(inst, shadow_frame);
2349 }
2350
2351 ALWAYS_INLINE void UNUSED_F3() REQUIRES_SHARED(Locks::mutator_lock_) {
2352 UnexpectedOpcode(inst, shadow_frame);
2353 }
2354
2355 ALWAYS_INLINE void UNUSED_F4() REQUIRES_SHARED(Locks::mutator_lock_) {
2356 UnexpectedOpcode(inst, shadow_frame);
2357 }
2358
2359 ALWAYS_INLINE void UNUSED_F5() REQUIRES_SHARED(Locks::mutator_lock_) {
2360 UnexpectedOpcode(inst, shadow_frame);
2361 }
2362
2363 ALWAYS_INLINE void UNUSED_F6() REQUIRES_SHARED(Locks::mutator_lock_) {
2364 UnexpectedOpcode(inst, shadow_frame);
2365 }
2366
2367 ALWAYS_INLINE void UNUSED_F7() REQUIRES_SHARED(Locks::mutator_lock_) {
2368 UnexpectedOpcode(inst, shadow_frame);
2369 }
2370
2371 ALWAYS_INLINE void UNUSED_F8() REQUIRES_SHARED(Locks::mutator_lock_) {
2372 UnexpectedOpcode(inst, shadow_frame);
2373 }
2374
2375 ALWAYS_INLINE void UNUSED_F9() REQUIRES_SHARED(Locks::mutator_lock_) {
2376 UnexpectedOpcode(inst, shadow_frame);
2377 }
2378
2379 ALWAYS_INLINE InstructionHandler(SwitchImplContext* ctx,
2380 const instrumentation::Instrumentation* instrumentation,
2381 Thread* self,
2382 ShadowFrame& shadow_frame,
2383 uint16_t dex_pc,
2384 const Instruction*& inst,
2385 uint16_t inst_data,
2386 bool& exit_interpreter_loop)
2387 : ctx(ctx),
2388 instrumentation(instrumentation),
2389 self(self),
2390 shadow_frame(shadow_frame),
2391 dex_pc(dex_pc),
2392 inst(inst),
2393 inst_data(inst_data),
2394 exit_interpreter_loop(exit_interpreter_loop) {
2395 }
2396
2397 private:
2398 static constexpr bool do_assignability_check = do_access_check;
2399
2400 const CodeItemDataAccessor& Accessor() { return ctx->accessor; }
2401 const uint16_t* Insns() { return ctx->accessor.Insns(); }
2402 JValue* ResultRegister() { return &ctx->result_register; }
2403
David Srbecky436f6c12019-05-22 13:28:42 +01002404 ALWAYS_INLINE int32_t A() { return inst->VRegA(kFormat, inst_data); }
2405 ALWAYS_INLINE int32_t B() { return inst->VRegB(kFormat, inst_data); }
2406 ALWAYS_INLINE int32_t C() { return inst->VRegC(kFormat); }
2407
David Srbecky6baf6442019-05-30 14:57:43 +01002408 int32_t GetVReg(size_t i) const { return shadow_frame.GetVReg(i); }
2409 int64_t GetVRegLong(size_t i) const { return shadow_frame.GetVRegLong(i); }
2410 float GetVRegFloat(size_t i) const { return shadow_frame.GetVRegFloat(i); }
2411 double GetVRegDouble(size_t i) const { return shadow_frame.GetVRegDouble(i); }
2412 ObjPtr<mirror::Object> GetVRegReference(size_t i) const REQUIRES_SHARED(Locks::mutator_lock_) {
2413 return shadow_frame.GetVRegReference(i);
2414 }
2415
2416 void SetVReg(size_t i, int32_t val) { shadow_frame.SetVReg(i, val); }
2417 void SetVRegLong(size_t i, int64_t val) { shadow_frame.SetVRegLong(i, val); }
2418 void SetVRegFloat(size_t i, float val) { shadow_frame.SetVRegFloat(i, val); }
2419 void SetVRegDouble(size_t i, double val) { shadow_frame.SetVRegDouble(i, val); }
2420 void SetVRegReference(size_t i, ObjPtr<mirror::Object> val)
2421 REQUIRES_SHARED(Locks::mutator_lock_) {
2422 shadow_frame.SetVRegReference(i, val);
2423 }
2424
David Srbecky6da82472018-10-23 14:03:08 +01002425 SwitchImplContext* const ctx;
2426 const instrumentation::Instrumentation* const instrumentation;
2427 Thread* const self;
2428 ShadowFrame& shadow_frame;
2429 uint32_t const dex_pc;
2430 const Instruction*& inst;
2431 uint16_t const inst_data;
2432 bool& exit_interpreter_loop;
2433};
2434
David Srbecky6da82472018-10-23 14:03:08 +01002435#undef BRANCH_INSTRUMENTATION
David Srbecky6da82472018-10-23 14:03:08 +01002436#undef POSSIBLY_HANDLE_PENDING_EXCEPTION
2437#undef POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE
2438#undef POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC
David Srbecky6da82472018-10-23 14:03:08 +01002439#undef HANDLE_PENDING_EXCEPTION
David Srbecky6da82472018-10-23 14:03:08 +01002440
Alex Light6f22e062018-10-05 15:05:12 -07002441// TODO On ASAN builds this function gets a huge stack frame. Since normally we run in the mterp
2442// this shouldn't cause any problems for stack overflow detection. Remove this once b/117341496 is
2443// fixed.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +01002444template<bool do_access_check, bool transaction_active>
Alex Light6f22e062018-10-05 15:05:12 -07002445ATTRIBUTE_NO_SANITIZE_ADDRESS void ExecuteSwitchImplCpp(SwitchImplContext* ctx) {
David Srbecky946bb092018-03-09 17:23:01 +00002446 Thread* self = ctx->self;
2447 const CodeItemDataAccessor& accessor = ctx->accessor;
2448 ShadowFrame& shadow_frame = ctx->shadow_frame;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002449 if (UNLIKELY(!shadow_frame.HasReferenceArray())) {
2450 LOG(FATAL) << "Invalid shadow frame for interpreter use";
David Srbecky946bb092018-03-09 17:23:01 +00002451 ctx->result = JValue();
2452 return;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002453 }
2454 self->VerifyStack();
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002455
2456 uint32_t dex_pc = shadow_frame.GetDexPC();
Mathieu Chartier2cebb242015-04-21 16:50:40 -07002457 const auto* const instrumentation = Runtime::Current()->GetInstrumentation();
Mathieu Chartier808c7a52017-12-15 11:19:33 -08002458 const uint16_t* const insns = accessor.Insns();
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002459 const Instruction* inst = Instruction::At(insns + dex_pc);
Sebastien Hertz3b588e02013-09-11 14:33:18 +02002460 uint16_t inst_data;
Igor Murashkin6918bf12015-09-27 19:19:06 -07002461
Alex Light0aa7a5a2018-10-10 15:58:14 +00002462 DCHECK(!shadow_frame.GetForceRetryInstruction())
2463 << "Entered interpreter from invoke without retry instruction being handled!";
2464
David Srbecky6da82472018-10-23 14:03:08 +01002465 bool const interpret_one_instruction = ctx->interpret_one_instruction;
2466 while (true) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002467 dex_pc = inst->GetDexPc(insns);
2468 shadow_frame.SetDexPC(dex_pc);
Ian Rogerse94652f2014-12-02 11:13:19 -08002469 TraceExecution(shadow_frame, inst, dex_pc);
Sebastien Hertz3b588e02013-09-11 14:33:18 +02002470 inst_data = inst->Fetch16(0);
David Srbeckya4a96af2018-10-31 16:34:58 +00002471 {
2472 bool exit_loop = false;
David Srbecky436f6c12019-05-22 13:28:42 +01002473 InstructionHandler<do_access_check, transaction_active, Instruction::kInvalidFormat> handler(
David Srbeckya4a96af2018-10-31 16:34:58 +00002474 ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, exit_loop);
2475 if (!handler.Preamble()) {
2476 if (UNLIKELY(exit_loop)) {
2477 return;
2478 }
2479 if (UNLIKELY(interpret_one_instruction)) {
2480 break;
2481 }
2482 continue;
2483 }
2484 }
Sebastien Hertz3b588e02013-09-11 14:33:18 +02002485 switch (inst->Opcode(inst_data)) {
David Srbecky436f6c12019-05-22 13:28:42 +01002486#define OPCODE_CASE(OPCODE, OPCODE_NAME, pname, FORMAT, i, a, e, v) \
David Srbecky6da82472018-10-23 14:03:08 +01002487 case OPCODE: { \
2488 bool exit_loop = false; \
David Srbecky436f6c12019-05-22 13:28:42 +01002489 InstructionHandler<do_access_check, transaction_active, Instruction::FORMAT> handler( \
David Srbecky6da82472018-10-23 14:03:08 +01002490 ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, exit_loop); \
David Srbeckya4a96af2018-10-31 16:34:58 +00002491 handler.OPCODE_NAME(); \
David Srbecky6da82472018-10-23 14:03:08 +01002492 /* TODO: Advance 'inst' here, instead of explicitly in each handler */ \
2493 if (UNLIKELY(exit_loop)) { \
2494 return; \
2495 } \
2496 break; \
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002497 }
David Srbecky6da82472018-10-23 14:03:08 +01002498DEX_INSTRUCTION_LIST(OPCODE_CASE)
2499#undef OPCODE_CASE
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002500 }
David Srbecky6da82472018-10-23 14:03:08 +01002501 if (UNLIKELY(interpret_one_instruction)) {
David Srbeckya4a96af2018-10-31 16:34:58 +00002502 break;
David Srbecky6da82472018-10-23 14:03:08 +01002503 }
2504 }
David Srbeckya4a96af2018-10-31 16:34:58 +00002505 // Record where we stopped.
2506 shadow_frame.SetDexPC(inst->GetDexPc(insns));
2507 ctx->result = ctx->result_register;
2508 return;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002509} // NOLINT(readability/fn_size)
2510
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002511} // namespace interpreter
2512} // namespace art
David Srbecky2ee09ff2018-10-24 13:24:22 +01002513
2514#endif // ART_RUNTIME_INTERPRETER_INTERPRETER_SWITCH_IMPL_INL_H_