blob: 71b2336cb02b8d4624e6ceeee7fa2bc5b2c4c301 [file] [log] [blame]
Sebastien Hertz8ece0502013-08-07 11:26:41 +02001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
David Srbecky2ee09ff2018-10-24 13:24:22 +010017#ifndef ART_RUNTIME_INTERPRETER_INTERPRETER_SWITCH_IMPL_INL_H_
18#define ART_RUNTIME_INTERPRETER_INTERPRETER_SWITCH_IMPL_INL_H_
19
Andreas Gampe5e26eb12016-08-22 17:54:17 -070020#include "interpreter_switch_impl.h"
21
Andreas Gampe542451c2016-07-26 09:02:02 -070022#include "base/enums.h"
Alex Light6f22e062018-10-05 15:05:12 -070023#include "base/memory_tool.h"
David Sehrc431b9d2018-03-02 12:01:51 -080024#include "base/quasi_atomic.h"
David Sehr9e734c72018-01-04 17:56:19 -080025#include "dex/dex_file_types.h"
David Srbecky6da82472018-10-23 14:03:08 +010026#include "dex/dex_instruction_list.h"
Alex Lighteb7c1442015-08-31 13:17:42 -070027#include "experimental_flags.h"
Sebastien Hertz8ece0502013-08-07 11:26:41 +020028#include "interpreter_common.h"
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +000029#include "jit/jit.h"
Mathieu Chartier28bd2e42016-10-04 13:54:57 -070030#include "jvalue-inl.h"
Andreas Gampefd63bbf2018-10-29 12:55:35 -070031#include "mirror/string-alloc-inl.h"
Alex Light0aa7a5a2018-10-10 15:58:14 +000032#include "nth_caller_visitor.h"
Ian Rogersf72a11d2014-10-30 15:41:08 -070033#include "safe_math.h"
Vladimir Marko6ec2a1b2018-05-22 15:33:48 +010034#include "shadow_frame-inl.h"
Alex Light0aa7a5a2018-10-10 15:58:14 +000035#include "thread.h"
Sebastien Hertz8ece0502013-08-07 11:26:41 +020036
37namespace art {
38namespace interpreter {
39
David Srbecky6da82472018-10-23 14:03:08 +010040// TODO: Replace macros with member functions.
Alex Light0aa7a5a2018-10-10 15:58:14 +000041#define CHECK_FORCE_RETURN() \
David Srbecky30232c42018-10-26 18:56:01 +010042 { \
Alex Light0aa7a5a2018-10-10 15:58:14 +000043 if (UNLIKELY(shadow_frame.GetForcePopFrame())) { \
44 DCHECK(PrevFrameWillRetry(self, shadow_frame)) \
45 << "Pop frame forced without previous frame ready to retry instruction!"; \
46 DCHECK(Runtime::Current()->AreNonStandardExitsEnabled()); \
47 if (UNLIKELY(NeedsMethodExitEvent(instrumentation))) { \
48 SendMethodExitEvents(self, \
49 instrumentation, \
50 shadow_frame, \
David Srbecky6da82472018-10-23 14:03:08 +010051 shadow_frame.GetThisObject(Accessor().InsSize()), \
Alex Light0aa7a5a2018-10-10 15:58:14 +000052 shadow_frame.GetMethod(), \
David Srbecky6da82472018-10-23 14:03:08 +010053 inst->GetDexPc(Insns()), \
Alex Light0aa7a5a2018-10-10 15:58:14 +000054 JValue()); \
55 } \
56 ctx->result = JValue(); /* Handled in caller. */ \
David Srbecky6da82472018-10-23 14:03:08 +010057 exit_interpreter_loop = true; \
Alex Light0aa7a5a2018-10-10 15:58:14 +000058 return; \
59 } \
David Srbecky30232c42018-10-26 18:56:01 +010060 } \
61 do {} while (false)
Alex Light0aa7a5a2018-10-10 15:58:14 +000062
Alex Lightb7edcda2017-04-27 13:20:31 -070063#define HANDLE_PENDING_EXCEPTION_WITH_INSTRUMENTATION(instr) \
David Srbecky30232c42018-10-26 18:56:01 +010064 { \
Sebastien Hertz82aeddb2014-05-20 20:09:45 +020065 DCHECK(self->IsExceptionPending()); \
Ian Rogers7b078e82014-09-10 14:44:24 -070066 self->AllowThreadSuspension(); \
Alex Light0aa7a5a2018-10-10 15:58:14 +000067 CHECK_FORCE_RETURN(); \
Alex Light9fb1ab12017-09-05 09:32:49 -070068 if (!MoveToExceptionHandler(self, shadow_frame, instr)) { \
Andreas Gampe03ec9302015-08-27 17:41:47 -070069 /* Structured locking is to be enforced for abnormal termination, too. */ \
Andreas Gampe56fdd0e2016-04-28 14:56:54 -070070 DoMonitorCheckOnExit<do_assignability_check>(self, &shadow_frame); \
David Srbecky6da82472018-10-23 14:03:08 +010071 if (ctx->interpret_one_instruction) { \
buzbee93e94f22016-04-07 13:52:48 -070072 /* Signal mterp to return to caller */ \
Andreas Gampee2abbc62017-09-15 11:59:26 -070073 shadow_frame.SetDexPC(dex::kDexNoIndex); \
buzbee1452bee2015-03-06 14:43:04 -080074 } \
David Srbecky946bb092018-03-09 17:23:01 +000075 ctx->result = JValue(); /* Handled in caller. */ \
David Srbecky6da82472018-10-23 14:03:08 +010076 exit_interpreter_loop = true; \
David Srbecky946bb092018-03-09 17:23:01 +000077 return; \
Sebastien Hertz8ece0502013-08-07 11:26:41 +020078 } else { \
Alex Light0aa7a5a2018-10-10 15:58:14 +000079 CHECK_FORCE_RETURN(); \
Alex Light9fb1ab12017-09-05 09:32:49 -070080 int32_t displacement = \
81 static_cast<int32_t>(shadow_frame.GetDexPC()) - static_cast<int32_t>(dex_pc); \
Sebastien Hertz8ece0502013-08-07 11:26:41 +020082 inst = inst->RelativeAt(displacement); \
David Srbecky6da82472018-10-23 14:03:08 +010083 return; /* Stop executing this opcode and continue in the exception handler. */ \
Sebastien Hertz8ece0502013-08-07 11:26:41 +020084 } \
David Srbecky30232c42018-10-26 18:56:01 +010085 } \
86 do {} while (false)
Sebastien Hertz8ece0502013-08-07 11:26:41 +020087
Alex Lightb7edcda2017-04-27 13:20:31 -070088#define HANDLE_PENDING_EXCEPTION() HANDLE_PENDING_EXCEPTION_WITH_INSTRUMENTATION(instrumentation)
89
Alex Light0aa7a5a2018-10-10 15:58:14 +000090#define POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_IMPL(_is_exception_pending, _next_function) \
David Srbecky30232c42018-10-26 18:56:01 +010091 { \
Alex Light0aa7a5a2018-10-10 15:58:14 +000092 if (UNLIKELY(shadow_frame.GetForceRetryInstruction())) { \
93 /* Don't need to do anything except clear the flag and exception. We leave the */ \
94 /* instruction the same so it will be re-executed on the next go-around. */ \
95 DCHECK(inst->IsInvoke()); \
96 shadow_frame.SetForceRetryInstruction(false); \
97 if (UNLIKELY(_is_exception_pending)) { \
98 DCHECK(self->IsExceptionPending()); \
99 if (kIsDebugBuild) { \
100 LOG(WARNING) << "Suppressing exception for instruction-retry: " \
101 << self->GetException()->Dump(); \
102 } \
103 self->ClearException(); \
104 } \
105 } else if (UNLIKELY(_is_exception_pending)) { \
106 /* Should have succeeded. */ \
107 DCHECK(!shadow_frame.GetForceRetryInstruction()); \
108 HANDLE_PENDING_EXCEPTION(); \
109 } else { \
110 inst = inst->_next_function(); \
111 } \
David Srbecky30232c42018-10-26 18:56:01 +0100112 } \
113 do {} while (false)
Alex Light0aa7a5a2018-10-10 15:58:14 +0000114
115#define POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(_is_exception_pending) \
116 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_IMPL(_is_exception_pending, Next_4xx)
117#define POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(_is_exception_pending) \
118 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_IMPL(_is_exception_pending, Next_3xx)
119
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200120#define POSSIBLY_HANDLE_PENDING_EXCEPTION(_is_exception_pending, _next_function) \
David Srbecky30232c42018-10-26 18:56:01 +0100121 { \
Alex Light0aa7a5a2018-10-10 15:58:14 +0000122 /* Should only be on invoke instructions. */ \
123 DCHECK(!shadow_frame.GetForceRetryInstruction()); \
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200124 if (UNLIKELY(_is_exception_pending)) { \
125 HANDLE_PENDING_EXCEPTION(); \
126 } else { \
127 inst = inst->_next_function(); \
128 } \
David Srbecky30232c42018-10-26 18:56:01 +0100129 } \
130 do {} while (false)
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200131
Andreas Gampe03ec9302015-08-27 17:41:47 -0700132#define HANDLE_MONITOR_CHECKS() \
Andreas Gampe56fdd0e2016-04-28 14:56:54 -0700133 if (!DoMonitorCheckOnExit<do_assignability_check>(self, &shadow_frame)) { \
Andreas Gampe03ec9302015-08-27 17:41:47 -0700134 HANDLE_PENDING_EXCEPTION(); \
135 }
136
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200137// Code to run before each dex instruction.
Alex Light0aa7a5a2018-10-10 15:58:14 +0000138#define PREAMBLE_SAVE(save_ref) \
Alex Lightfc905672017-06-27 17:53:15 -0700139 { \
Alex Light0aa7a5a2018-10-10 15:58:14 +0000140 /* We need to put this before & after the instrumentation to avoid having to put in a */ \
141 /* post-script macro. */ \
142 CHECK_FORCE_RETURN(); \
143 if (UNLIKELY(instrumentation->HasDexPcListeners())) { \
144 if (UNLIKELY(!DoDexPcMoveEvent(self, \
David Srbecky6da82472018-10-23 14:03:08 +0100145 Accessor(), \
Alex Light0aa7a5a2018-10-10 15:58:14 +0000146 shadow_frame, \
147 dex_pc, \
148 instrumentation, \
149 save_ref))) { \
150 HANDLE_PENDING_EXCEPTION(); \
Alex Light0aa7a5a2018-10-10 15:58:14 +0000151 } \
152 CHECK_FORCE_RETURN(); \
Sebastien Hertz8379b222014-02-24 17:38:15 +0100153 } \
Alex Lightfc905672017-06-27 17:53:15 -0700154 } \
155 do {} while (false)
156
157#define PREAMBLE() PREAMBLE_SAVE(nullptr)
Sebastien Hertz8ece0502013-08-07 11:26:41 +0200158
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +0000159#define BRANCH_INSTRUMENTATION(offset) \
David Srbecky30232c42018-10-26 18:56:01 +0100160 { \
Nicolas Geoffray274fe4a2016-04-12 16:33:24 +0100161 if (UNLIKELY(instrumentation->HasBranchListeners())) { \
Alex Lightcc917d92018-02-22 13:28:28 -0800162 instrumentation->Branch(self, shadow_frame.GetMethod(), dex_pc, offset); \
Nicolas Geoffray274fe4a2016-04-12 16:33:24 +0100163 } \
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +0000164 JValue result; \
Alex Lightcc917d92018-02-22 13:28:28 -0800165 if (jit::Jit::MaybeDoOnStackReplacement(self, \
166 shadow_frame.GetMethod(), \
167 dex_pc, \
168 offset, \
169 &result)) { \
David Srbecky6da82472018-10-23 14:03:08 +0100170 if (ctx->interpret_one_instruction) { \
buzbee93e94f22016-04-07 13:52:48 -0700171 /* OSR has completed execution of the method. Signal mterp to return to caller */ \
Andreas Gampee2abbc62017-09-15 11:59:26 -0700172 shadow_frame.SetDexPC(dex::kDexNoIndex); \
buzbee93e94f22016-04-07 13:52:48 -0700173 } \
David Srbecky946bb092018-03-09 17:23:01 +0000174 ctx->result = result; \
David Srbecky6da82472018-10-23 14:03:08 +0100175 exit_interpreter_loop = true; \
David Srbecky946bb092018-03-09 17:23:01 +0000176 return; \
Nicolas Geoffrayb331feb2016-02-05 16:51:53 +0000177 } \
David Srbecky30232c42018-10-26 18:56:01 +0100178 } \
179 do {} while (false)
Nicolas Geoffray3108daf2015-11-24 16:32:33 +0000180
Bill Buzbee1d011d92016-04-04 16:59:29 +0000181#define HOTNESS_UPDATE() \
David Srbecky30232c42018-10-26 18:56:01 +0100182 { \
David Srbecky6da82472018-10-23 14:03:08 +0100183 jit::Jit* jit = Runtime::Current()->GetJit(); \
Nicolas Geoffray274fe4a2016-04-12 16:33:24 +0100184 if (jit != nullptr) { \
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700185 jit->AddSamples(self, shadow_frame.GetMethod(), 1, /*with_backedges=*/ true); \
Bill Buzbee1d011d92016-04-04 16:59:29 +0000186 } \
David Srbecky30232c42018-10-26 18:56:01 +0100187 } \
188 do {} while (false)
Bill Buzbee1d011d92016-04-04 16:59:29 +0000189
Alex Light848574c2017-09-25 16:59:39 -0700190#define HANDLE_ASYNC_EXCEPTION() \
191 if (UNLIKELY(self->ObserveAsyncException())) { \
192 HANDLE_PENDING_EXCEPTION(); \
Alex Light848574c2017-09-25 16:59:39 -0700193 } \
194 do {} while (false)
195
Andreas Gampef4f76372016-12-13 14:43:58 -0800196#define HANDLE_BACKWARD_BRANCH(offset) \
David Srbecky30232c42018-10-26 18:56:01 +0100197 { \
Andreas Gampef4f76372016-12-13 14:43:58 -0800198 if (IsBackwardBranch(offset)) { \
199 HOTNESS_UPDATE(); \
200 /* Record new dex pc early to have consistent suspend point at loop header. */ \
David Srbecky6da82472018-10-23 14:03:08 +0100201 shadow_frame.SetDexPC(inst->GetDexPc(Insns())); \
Andreas Gampef4f76372016-12-13 14:43:58 -0800202 self->AllowThreadSuspension(); \
203 } \
David Srbecky30232c42018-10-26 18:56:01 +0100204 } \
205 do {} while (false)
Andreas Gampef4f76372016-12-13 14:43:58 -0800206
Alex Lightfc905672017-06-27 17:53:15 -0700207// Unlike most other events the DexPcMovedEvent can be sent when there is a pending exception (if
208// the next instruction is MOVE_EXCEPTION). This means it needs to be handled carefully to be able
209// to detect exceptions thrown by the DexPcMovedEvent itself. These exceptions could be thrown by
210// jvmti-agents while handling breakpoint or single step events. We had to move this into its own
211// function because it was making ExecuteSwitchImpl have too large a stack.
Alex Light2989a4a2017-06-29 09:44:57 -0700212NO_INLINE static bool DoDexPcMoveEvent(Thread* self,
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800213 const CodeItemDataAccessor& accessor,
Alex Light2989a4a2017-06-29 09:44:57 -0700214 const ShadowFrame& shadow_frame,
215 uint32_t dex_pc,
216 const instrumentation::Instrumentation* instrumentation,
217 JValue* save_ref)
Alex Lightfc905672017-06-27 17:53:15 -0700218 REQUIRES_SHARED(Locks::mutator_lock_) {
219 DCHECK(instrumentation->HasDexPcListeners());
220 StackHandleScope<2> hs(self);
221 Handle<mirror::Throwable> thr(hs.NewHandle(self->GetException()));
222 mirror::Object* null_obj = nullptr;
223 HandleWrapper<mirror::Object> h(
224 hs.NewHandleWrapper(LIKELY(save_ref == nullptr) ? &null_obj : save_ref->GetGCRoot()));
225 self->ClearException();
226 instrumentation->DexPcMovedEvent(self,
Mathieu Chartier808c7a52017-12-15 11:19:33 -0800227 shadow_frame.GetThisObject(accessor.InsSize()),
Alex Lightfc905672017-06-27 17:53:15 -0700228 shadow_frame.GetMethod(),
229 dex_pc);
230 if (UNLIKELY(self->IsExceptionPending())) {
231 // We got a new exception in the dex-pc-moved event. We just let this exception replace the old
232 // one.
233 // TODO It would be good to add the old exception to the suppressed exceptions of the new one if
234 // possible.
235 return false;
236 } else {
237 if (UNLIKELY(!thr.IsNull())) {
238 self->SetException(thr.Get());
239 }
240 return true;
241 }
242}
243
Alex Lighte814f9d2017-07-31 16:14:39 -0700244static bool NeedsMethodExitEvent(const instrumentation::Instrumentation* ins)
245 REQUIRES_SHARED(Locks::mutator_lock_) {
246 return ins->HasMethodExitListeners() || ins->HasWatchedFramePopListeners();
247}
248
249// Sends the normal method exit event. Returns true if the events succeeded and false if there is a
250// pending exception.
251NO_INLINE static bool SendMethodExitEvents(Thread* self,
252 const instrumentation::Instrumentation* instrumentation,
253 const ShadowFrame& frame,
254 ObjPtr<mirror::Object> thiz,
255 ArtMethod* method,
256 uint32_t dex_pc,
257 const JValue& result)
258 REQUIRES_SHARED(Locks::mutator_lock_) {
259 bool had_event = false;
Alex Light0aa7a5a2018-10-10 15:58:14 +0000260 // We don't send method-exit if it's a pop-frame. We still send frame_popped though.
261 if (UNLIKELY(instrumentation->HasMethodExitListeners() && !frame.GetForcePopFrame())) {
Alex Lighte814f9d2017-07-31 16:14:39 -0700262 had_event = true;
263 instrumentation->MethodExitEvent(self, thiz.Ptr(), method, dex_pc, result);
264 }
265 if (UNLIKELY(frame.NeedsNotifyPop() && instrumentation->HasWatchedFramePopListeners())) {
266 had_event = true;
267 instrumentation->WatchedFramePopped(self, frame);
268 }
269 if (UNLIKELY(had_event)) {
270 return !self->IsExceptionPending();
271 } else {
272 return true;
273 }
274}
275
David Srbecky6da82472018-10-23 14:03:08 +0100276// Short-lived helper class which executes single DEX bytecode. It is inlined by compiler.
277//
278// The function names must match the names from dex_instruction_list.h and have no arguments.
279//
280// Any relevant execution information is stored in the fields - it should be kept to minimum.
281//
282template<bool do_access_check, bool transaction_active>
283class InstructionHandler {
284 public:
285 ALWAYS_INLINE void NOP() REQUIRES_SHARED(Locks::mutator_lock_) {
286 PREAMBLE();
287 inst = inst->Next_1xx();
288 }
289
290 ALWAYS_INLINE void MOVE() REQUIRES_SHARED(Locks::mutator_lock_) {
291 PREAMBLE();
292 shadow_frame.SetVReg(inst->VRegA_12x(inst_data),
293 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
294 inst = inst->Next_1xx();
295 }
296
297 ALWAYS_INLINE void MOVE_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
298 PREAMBLE();
299 shadow_frame.SetVReg(inst->VRegA_22x(inst_data),
300 shadow_frame.GetVReg(inst->VRegB_22x()));
301 inst = inst->Next_2xx();
302 }
303
304 ALWAYS_INLINE void MOVE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
305 PREAMBLE();
306 shadow_frame.SetVReg(inst->VRegA_32x(),
307 shadow_frame.GetVReg(inst->VRegB_32x()));
308 inst = inst->Next_3xx();
309 }
310
311 ALWAYS_INLINE void MOVE_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
312 PREAMBLE();
313 shadow_frame.SetVRegLong(inst->VRegA_12x(inst_data),
314 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
315 inst = inst->Next_1xx();
316 }
317
318 ALWAYS_INLINE void MOVE_WIDE_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
319 PREAMBLE();
320 shadow_frame.SetVRegLong(inst->VRegA_22x(inst_data),
321 shadow_frame.GetVRegLong(inst->VRegB_22x()));
322 inst = inst->Next_2xx();
323 }
324
325 ALWAYS_INLINE void MOVE_WIDE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
326 PREAMBLE();
327 shadow_frame.SetVRegLong(inst->VRegA_32x(),
328 shadow_frame.GetVRegLong(inst->VRegB_32x()));
329 inst = inst->Next_3xx();
330 }
331
332 ALWAYS_INLINE void MOVE_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
333 PREAMBLE();
334 shadow_frame.SetVRegReference(inst->VRegA_12x(inst_data),
335 shadow_frame.GetVRegReference(inst->VRegB_12x(inst_data)));
336 inst = inst->Next_1xx();
337 }
338
339 ALWAYS_INLINE void MOVE_OBJECT_FROM16() REQUIRES_SHARED(Locks::mutator_lock_) {
340 PREAMBLE();
341 shadow_frame.SetVRegReference(inst->VRegA_22x(inst_data),
342 shadow_frame.GetVRegReference(inst->VRegB_22x()));
343 inst = inst->Next_2xx();
344 }
345
346 ALWAYS_INLINE void MOVE_OBJECT_16() REQUIRES_SHARED(Locks::mutator_lock_) {
347 PREAMBLE();
348 shadow_frame.SetVRegReference(inst->VRegA_32x(),
349 shadow_frame.GetVRegReference(inst->VRegB_32x()));
350 inst = inst->Next_3xx();
351 }
352
353 ALWAYS_INLINE void MOVE_RESULT() REQUIRES_SHARED(Locks::mutator_lock_) {
354 PREAMBLE();
355 shadow_frame.SetVReg(inst->VRegA_11x(inst_data), ResultRegister()->GetI());
356 inst = inst->Next_1xx();
357 }
358
359 ALWAYS_INLINE void MOVE_RESULT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
360 PREAMBLE();
361 shadow_frame.SetVRegLong(inst->VRegA_11x(inst_data), ResultRegister()->GetJ());
362 inst = inst->Next_1xx();
363 }
364
365 ALWAYS_INLINE void MOVE_RESULT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
366 PREAMBLE_SAVE(ResultRegister());
367 shadow_frame.SetVRegReference(inst->VRegA_11x(inst_data), ResultRegister()->GetL());
368 inst = inst->Next_1xx();
369 }
370
371 ALWAYS_INLINE void MOVE_EXCEPTION() REQUIRES_SHARED(Locks::mutator_lock_) {
372 PREAMBLE();
373 ObjPtr<mirror::Throwable> exception = self->GetException();
374 DCHECK(exception != nullptr) << "No pending exception on MOVE_EXCEPTION instruction";
375 shadow_frame.SetVRegReference(inst->VRegA_11x(inst_data), exception);
376 self->ClearException();
377 inst = inst->Next_1xx();
378 }
379
380 ALWAYS_INLINE void RETURN_VOID_NO_BARRIER() REQUIRES_SHARED(Locks::mutator_lock_) {
381 PREAMBLE();
382 JValue result;
383 self->AllowThreadSuspension();
384 HANDLE_MONITOR_CHECKS();
385 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
386 !SendMethodExitEvents(self,
387 instrumentation,
388 shadow_frame,
389 shadow_frame.GetThisObject(Accessor().InsSize()),
390 shadow_frame.GetMethod(),
391 inst->GetDexPc(Insns()),
392 result))) {
393 HANDLE_PENDING_EXCEPTION_WITH_INSTRUMENTATION(nullptr);
394 }
395 if (ctx->interpret_one_instruction) {
396 /* Signal mterp to return to caller */
397 shadow_frame.SetDexPC(dex::kDexNoIndex);
398 }
399 ctx->result = result;
400 exit_interpreter_loop = true;
401 }
402
403 ALWAYS_INLINE void RETURN_VOID() REQUIRES_SHARED(Locks::mutator_lock_) {
404 PREAMBLE();
405 QuasiAtomic::ThreadFenceForConstructor();
406 JValue result;
407 self->AllowThreadSuspension();
408 HANDLE_MONITOR_CHECKS();
409 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
410 !SendMethodExitEvents(self,
411 instrumentation,
412 shadow_frame,
413 shadow_frame.GetThisObject(Accessor().InsSize()),
414 shadow_frame.GetMethod(),
415 inst->GetDexPc(Insns()),
416 result))) {
417 HANDLE_PENDING_EXCEPTION_WITH_INSTRUMENTATION(nullptr);
418 }
419 if (ctx->interpret_one_instruction) {
420 /* Signal mterp to return to caller */
421 shadow_frame.SetDexPC(dex::kDexNoIndex);
422 }
423 ctx->result = result;
424 exit_interpreter_loop = true;
425 }
426
427 ALWAYS_INLINE void RETURN() REQUIRES_SHARED(Locks::mutator_lock_) {
428 PREAMBLE();
429 JValue result;
430 result.SetJ(0);
431 result.SetI(shadow_frame.GetVReg(inst->VRegA_11x(inst_data)));
432 self->AllowThreadSuspension();
433 HANDLE_MONITOR_CHECKS();
434 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
435 !SendMethodExitEvents(self,
436 instrumentation,
437 shadow_frame,
438 shadow_frame.GetThisObject(Accessor().InsSize()),
439 shadow_frame.GetMethod(),
440 inst->GetDexPc(Insns()),
441 result))) {
442 HANDLE_PENDING_EXCEPTION_WITH_INSTRUMENTATION(nullptr);
443 }
444 if (ctx->interpret_one_instruction) {
445 /* Signal mterp to return to caller */
446 shadow_frame.SetDexPC(dex::kDexNoIndex);
447 }
448 ctx->result = result;
449 exit_interpreter_loop = true;
450 }
451
452 ALWAYS_INLINE void RETURN_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
453 PREAMBLE();
454 JValue result;
455 result.SetJ(shadow_frame.GetVRegLong(inst->VRegA_11x(inst_data)));
456 self->AllowThreadSuspension();
457 HANDLE_MONITOR_CHECKS();
458 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
459 !SendMethodExitEvents(self,
460 instrumentation,
461 shadow_frame,
462 shadow_frame.GetThisObject(Accessor().InsSize()),
463 shadow_frame.GetMethod(),
464 inst->GetDexPc(Insns()),
465 result))) {
466 HANDLE_PENDING_EXCEPTION_WITH_INSTRUMENTATION(nullptr);
467 }
468 if (ctx->interpret_one_instruction) {
469 /* Signal mterp to return to caller */
470 shadow_frame.SetDexPC(dex::kDexNoIndex);
471 }
472 ctx->result = result;
473 exit_interpreter_loop = true;
474 }
475
476 ALWAYS_INLINE void RETURN_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
477 PREAMBLE();
478 JValue result;
479 self->AllowThreadSuspension();
480 HANDLE_MONITOR_CHECKS();
481 const size_t ref_idx = inst->VRegA_11x(inst_data);
482 ObjPtr<mirror::Object> obj_result = shadow_frame.GetVRegReference(ref_idx);
483 if (do_assignability_check && obj_result != nullptr) {
484 ObjPtr<mirror::Class> return_type = shadow_frame.GetMethod()->ResolveReturnType();
485 // Re-load since it might have moved.
486 obj_result = shadow_frame.GetVRegReference(ref_idx);
487 if (return_type == nullptr) {
488 // Return the pending exception.
489 HANDLE_PENDING_EXCEPTION();
490 }
491 if (!obj_result->VerifierInstanceOf(return_type)) {
492 // This should never happen.
493 std::string temp1, temp2;
494 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
495 "Returning '%s' that is not instance of return type '%s'",
496 obj_result->GetClass()->GetDescriptor(&temp1),
497 return_type->GetDescriptor(&temp2));
498 HANDLE_PENDING_EXCEPTION();
499 }
500 }
501 result.SetL(obj_result);
502 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
503 !SendMethodExitEvents(self,
504 instrumentation,
505 shadow_frame,
506 shadow_frame.GetThisObject(Accessor().InsSize()),
507 shadow_frame.GetMethod(),
508 inst->GetDexPc(Insns()),
509 result))) {
510 HANDLE_PENDING_EXCEPTION_WITH_INSTRUMENTATION(nullptr);
511 }
512 // Re-load since it might have moved during the MethodExitEvent.
513 result.SetL(shadow_frame.GetVRegReference(ref_idx));
514 if (ctx->interpret_one_instruction) {
515 /* Signal mterp to return to caller */
516 shadow_frame.SetDexPC(dex::kDexNoIndex);
517 }
518 ctx->result = result;
519 exit_interpreter_loop = true;
520 }
521
522 ALWAYS_INLINE void CONST_4() REQUIRES_SHARED(Locks::mutator_lock_) {
523 PREAMBLE();
524 uint4_t dst = inst->VRegA_11n(inst_data);
525 int4_t val = inst->VRegB_11n(inst_data);
526 shadow_frame.SetVReg(dst, val);
527 if (val == 0) {
528 shadow_frame.SetVRegReference(dst, nullptr);
529 }
530 inst = inst->Next_1xx();
531 }
532
533 ALWAYS_INLINE void CONST_16() REQUIRES_SHARED(Locks::mutator_lock_) {
534 PREAMBLE();
535 uint8_t dst = inst->VRegA_21s(inst_data);
536 int16_t val = inst->VRegB_21s();
537 shadow_frame.SetVReg(dst, val);
538 if (val == 0) {
539 shadow_frame.SetVRegReference(dst, nullptr);
540 }
541 inst = inst->Next_2xx();
542 }
543
544 ALWAYS_INLINE void CONST() REQUIRES_SHARED(Locks::mutator_lock_) {
545 PREAMBLE();
546 uint8_t dst = inst->VRegA_31i(inst_data);
547 int32_t val = inst->VRegB_31i();
548 shadow_frame.SetVReg(dst, val);
549 if (val == 0) {
550 shadow_frame.SetVRegReference(dst, nullptr);
551 }
552 inst = inst->Next_3xx();
553 }
554
555 ALWAYS_INLINE void CONST_HIGH16() REQUIRES_SHARED(Locks::mutator_lock_) {
556 PREAMBLE();
557 uint8_t dst = inst->VRegA_21h(inst_data);
558 int32_t val = static_cast<int32_t>(inst->VRegB_21h() << 16);
559 shadow_frame.SetVReg(dst, val);
560 if (val == 0) {
561 shadow_frame.SetVRegReference(dst, nullptr);
562 }
563 inst = inst->Next_2xx();
564 }
565
566 ALWAYS_INLINE void CONST_WIDE_16() REQUIRES_SHARED(Locks::mutator_lock_) {
567 PREAMBLE();
568 shadow_frame.SetVRegLong(inst->VRegA_21s(inst_data), inst->VRegB_21s());
569 inst = inst->Next_2xx();
570 }
571
572 ALWAYS_INLINE void CONST_WIDE_32() REQUIRES_SHARED(Locks::mutator_lock_) {
573 PREAMBLE();
574 shadow_frame.SetVRegLong(inst->VRegA_31i(inst_data), inst->VRegB_31i());
575 inst = inst->Next_3xx();
576 }
577
578 ALWAYS_INLINE void CONST_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
579 PREAMBLE();
580 shadow_frame.SetVRegLong(inst->VRegA_51l(inst_data), inst->VRegB_51l());
581 inst = inst->Next_51l();
582 }
583
584 ALWAYS_INLINE void CONST_WIDE_HIGH16() REQUIRES_SHARED(Locks::mutator_lock_) {
585 PREAMBLE();
586 shadow_frame.SetVRegLong(inst->VRegA_21h(inst_data),
587 static_cast<uint64_t>(inst->VRegB_21h()) << 48);
588 inst = inst->Next_2xx();
589 }
590
591 ALWAYS_INLINE void CONST_STRING() REQUIRES_SHARED(Locks::mutator_lock_) {
592 PREAMBLE();
593 ObjPtr<mirror::String> s = ResolveString(self,
594 shadow_frame,
595 dex::StringIndex(inst->VRegB_21c()));
596 if (UNLIKELY(s == nullptr)) {
597 HANDLE_PENDING_EXCEPTION();
598 } else {
599 shadow_frame.SetVRegReference(inst->VRegA_21c(inst_data), s);
600 inst = inst->Next_2xx();
601 }
602 }
603
604 ALWAYS_INLINE void CONST_STRING_JUMBO() REQUIRES_SHARED(Locks::mutator_lock_) {
605 PREAMBLE();
606 ObjPtr<mirror::String> s = ResolveString(self,
607 shadow_frame,
608 dex::StringIndex(inst->VRegB_31c()));
609 if (UNLIKELY(s == nullptr)) {
610 HANDLE_PENDING_EXCEPTION();
611 } else {
612 shadow_frame.SetVRegReference(inst->VRegA_31c(inst_data), s);
613 inst = inst->Next_3xx();
614 }
615 }
616
617 ALWAYS_INLINE void CONST_CLASS() REQUIRES_SHARED(Locks::mutator_lock_) {
618 PREAMBLE();
619 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(inst->VRegB_21c()),
620 shadow_frame.GetMethod(),
621 self,
622 false,
623 do_access_check);
624 if (UNLIKELY(c == nullptr)) {
625 HANDLE_PENDING_EXCEPTION();
626 } else {
627 shadow_frame.SetVRegReference(inst->VRegA_21c(inst_data), c);
628 inst = inst->Next_2xx();
629 }
630 }
631
632 ALWAYS_INLINE void CONST_METHOD_HANDLE() REQUIRES_SHARED(Locks::mutator_lock_) {
633 PREAMBLE();
634 ClassLinker* cl = Runtime::Current()->GetClassLinker();
635 ObjPtr<mirror::MethodHandle> mh = cl->ResolveMethodHandle(self,
636 inst->VRegB_21c(),
637 shadow_frame.GetMethod());
638 if (UNLIKELY(mh == nullptr)) {
639 HANDLE_PENDING_EXCEPTION();
640 } else {
641 shadow_frame.SetVRegReference(inst->VRegA_21c(inst_data), mh);
642 inst = inst->Next_2xx();
643 }
644 }
645
646 ALWAYS_INLINE void CONST_METHOD_TYPE() REQUIRES_SHARED(Locks::mutator_lock_) {
647 PREAMBLE();
648 ClassLinker* cl = Runtime::Current()->GetClassLinker();
649 ObjPtr<mirror::MethodType> mt = cl->ResolveMethodType(self,
650 dex::ProtoIndex(inst->VRegB_21c()),
651 shadow_frame.GetMethod());
652 if (UNLIKELY(mt == nullptr)) {
653 HANDLE_PENDING_EXCEPTION();
654 } else {
655 shadow_frame.SetVRegReference(inst->VRegA_21c(inst_data), mt);
656 inst = inst->Next_2xx();
657 }
658 }
659
660 ALWAYS_INLINE void MONITOR_ENTER() REQUIRES_SHARED(Locks::mutator_lock_) {
661 PREAMBLE();
662 HANDLE_ASYNC_EXCEPTION();
663 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data));
664 if (UNLIKELY(obj == nullptr)) {
665 ThrowNullPointerExceptionFromInterpreter();
666 HANDLE_PENDING_EXCEPTION();
667 } else {
668 DoMonitorEnter<do_assignability_check>(self, &shadow_frame, obj);
669 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
670 }
671 }
672
673 ALWAYS_INLINE void MONITOR_EXIT() REQUIRES_SHARED(Locks::mutator_lock_) {
674 PREAMBLE();
675 HANDLE_ASYNC_EXCEPTION();
676 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data));
677 if (UNLIKELY(obj == nullptr)) {
678 ThrowNullPointerExceptionFromInterpreter();
679 HANDLE_PENDING_EXCEPTION();
680 } else {
681 DoMonitorExit<do_assignability_check>(self, &shadow_frame, obj);
682 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
683 }
684 }
685
686 ALWAYS_INLINE void CHECK_CAST() REQUIRES_SHARED(Locks::mutator_lock_) {
687 PREAMBLE();
688 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(inst->VRegB_21c()),
689 shadow_frame.GetMethod(),
690 self,
691 false,
692 do_access_check);
693 if (UNLIKELY(c == nullptr)) {
694 HANDLE_PENDING_EXCEPTION();
695 } else {
696 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(inst->VRegA_21c(inst_data));
697 if (UNLIKELY(obj != nullptr && !obj->InstanceOf(c))) {
698 ThrowClassCastException(c, obj->GetClass());
699 HANDLE_PENDING_EXCEPTION();
700 } else {
701 inst = inst->Next_2xx();
702 }
703 }
704 }
705
706 ALWAYS_INLINE void INSTANCE_OF() REQUIRES_SHARED(Locks::mutator_lock_) {
707 PREAMBLE();
708 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(inst->VRegC_22c()),
709 shadow_frame.GetMethod(),
710 self,
711 false,
712 do_access_check);
713 if (UNLIKELY(c == nullptr)) {
714 HANDLE_PENDING_EXCEPTION();
715 } else {
716 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data));
717 shadow_frame.SetVReg(inst->VRegA_22c(inst_data),
718 (obj != nullptr && obj->InstanceOf(c)) ? 1 : 0);
719 inst = inst->Next_2xx();
720 }
721 }
722
723 ALWAYS_INLINE void ARRAY_LENGTH() REQUIRES_SHARED(Locks::mutator_lock_) {
724 PREAMBLE();
725 ObjPtr<mirror::Object> array = shadow_frame.GetVRegReference(inst->VRegB_12x(inst_data));
726 if (UNLIKELY(array == nullptr)) {
727 ThrowNullPointerExceptionFromInterpreter();
728 HANDLE_PENDING_EXCEPTION();
729 } else {
730 shadow_frame.SetVReg(inst->VRegA_12x(inst_data), array->AsArray()->GetLength());
731 inst = inst->Next_1xx();
732 }
733 }
734
735 ALWAYS_INLINE void NEW_INSTANCE() REQUIRES_SHARED(Locks::mutator_lock_) {
736 PREAMBLE();
737 ObjPtr<mirror::Object> obj = nullptr;
738 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(inst->VRegB_21c()),
739 shadow_frame.GetMethod(),
740 self,
741 false,
742 do_access_check);
743 if (LIKELY(c != nullptr)) {
744 if (UNLIKELY(c->IsStringClass())) {
745 gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
746 obj = mirror::String::AllocEmptyString<true>(self, allocator_type);
747 } else {
748 obj = AllocObjectFromCode<true>(
749 c.Ptr(),
750 self,
751 Runtime::Current()->GetHeap()->GetCurrentAllocator());
752 }
753 }
754 if (UNLIKELY(obj == nullptr)) {
755 HANDLE_PENDING_EXCEPTION();
756 } else {
757 obj->GetClass()->AssertInitializedOrInitializingInThread(self);
758 // Don't allow finalizable objects to be allocated during a transaction since these can't
759 // be finalized without a started runtime.
760 if (transaction_active && obj->GetClass()->IsFinalizable()) {
761 AbortTransactionF(self, "Allocating finalizable object in transaction: %s",
762 obj->PrettyTypeOf().c_str());
763 HANDLE_PENDING_EXCEPTION();
764 }
765 shadow_frame.SetVRegReference(inst->VRegA_21c(inst_data), obj);
766 inst = inst->Next_2xx();
767 }
768 }
769
770 ALWAYS_INLINE void NEW_ARRAY() REQUIRES_SHARED(Locks::mutator_lock_) {
771 PREAMBLE();
772 int32_t length = shadow_frame.GetVReg(inst->VRegB_22c(inst_data));
773 ObjPtr<mirror::Object> obj = AllocArrayFromCode<do_access_check, true>(
774 dex::TypeIndex(inst->VRegC_22c()),
775 length,
776 shadow_frame.GetMethod(),
777 self,
778 Runtime::Current()->GetHeap()->GetCurrentAllocator());
779 if (UNLIKELY(obj == nullptr)) {
780 HANDLE_PENDING_EXCEPTION();
781 } else {
782 shadow_frame.SetVRegReference(inst->VRegA_22c(inst_data), obj);
783 inst = inst->Next_2xx();
784 }
785 }
786
787 ALWAYS_INLINE void FILLED_NEW_ARRAY() REQUIRES_SHARED(Locks::mutator_lock_) {
788 PREAMBLE();
789 bool success =
790 DoFilledNewArray<false, do_access_check, transaction_active>(inst, shadow_frame, self,
791 ResultRegister());
792 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
793 }
794
795 ALWAYS_INLINE void FILLED_NEW_ARRAY_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
796 PREAMBLE();
797 bool success =
798 DoFilledNewArray<true, do_access_check, transaction_active>(inst, shadow_frame,
799 self, ResultRegister());
800 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_3xx);
801 }
802
803 ALWAYS_INLINE void FILL_ARRAY_DATA() REQUIRES_SHARED(Locks::mutator_lock_) {
804 PREAMBLE();
805 const uint16_t* payload_addr = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
806 const Instruction::ArrayDataPayload* payload =
807 reinterpret_cast<const Instruction::ArrayDataPayload*>(payload_addr);
808 ObjPtr<mirror::Object> obj = shadow_frame.GetVRegReference(inst->VRegA_31t(inst_data));
809 bool success = FillArrayData(obj, payload);
810 if (!success) {
811 HANDLE_PENDING_EXCEPTION();
812 }
813 if (transaction_active) {
814 RecordArrayElementsInTransaction(obj->AsArray(), payload->element_count);
815 }
816 inst = inst->Next_3xx();
817 }
818
819 ALWAYS_INLINE void THROW() REQUIRES_SHARED(Locks::mutator_lock_) {
820 PREAMBLE();
821 HANDLE_ASYNC_EXCEPTION();
822 ObjPtr<mirror::Object> exception =
823 shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data));
824 if (UNLIKELY(exception == nullptr)) {
825 ThrowNullPointerException("throw with null exception");
826 } else if (do_assignability_check && !exception->GetClass()->IsThrowableClass()) {
827 // This should never happen.
828 std::string temp;
829 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
830 "Throwing '%s' that is not instance of Throwable",
831 exception->GetClass()->GetDescriptor(&temp));
832 } else {
833 self->SetException(exception->AsThrowable());
834 }
835 HANDLE_PENDING_EXCEPTION();
836 }
837
838 ALWAYS_INLINE void GOTO() REQUIRES_SHARED(Locks::mutator_lock_) {
839 PREAMBLE();
840 HANDLE_ASYNC_EXCEPTION();
841 int8_t offset = inst->VRegA_10t(inst_data);
842 BRANCH_INSTRUMENTATION(offset);
843 inst = inst->RelativeAt(offset);
844 HANDLE_BACKWARD_BRANCH(offset);
845 }
846
847 ALWAYS_INLINE void GOTO_16() REQUIRES_SHARED(Locks::mutator_lock_) {
848 PREAMBLE();
849 HANDLE_ASYNC_EXCEPTION();
850 int16_t offset = inst->VRegA_20t();
851 BRANCH_INSTRUMENTATION(offset);
852 inst = inst->RelativeAt(offset);
853 HANDLE_BACKWARD_BRANCH(offset);
854 }
855
856 ALWAYS_INLINE void GOTO_32() REQUIRES_SHARED(Locks::mutator_lock_) {
857 PREAMBLE();
858 HANDLE_ASYNC_EXCEPTION();
859 int32_t offset = inst->VRegA_30t();
860 BRANCH_INSTRUMENTATION(offset);
861 inst = inst->RelativeAt(offset);
862 HANDLE_BACKWARD_BRANCH(offset);
863 }
864
865 ALWAYS_INLINE void PACKED_SWITCH() REQUIRES_SHARED(Locks::mutator_lock_) {
866 PREAMBLE();
867 int32_t offset = DoPackedSwitch(inst, shadow_frame, inst_data);
868 BRANCH_INSTRUMENTATION(offset);
869 inst = inst->RelativeAt(offset);
870 HANDLE_BACKWARD_BRANCH(offset);
871 }
872
873 ALWAYS_INLINE void SPARSE_SWITCH() REQUIRES_SHARED(Locks::mutator_lock_) {
874 PREAMBLE();
875 int32_t offset = DoSparseSwitch(inst, shadow_frame, inst_data);
876 BRANCH_INSTRUMENTATION(offset);
877 inst = inst->RelativeAt(offset);
878 HANDLE_BACKWARD_BRANCH(offset);
879 }
880
881#pragma clang diagnostic push
882#pragma clang diagnostic ignored "-Wfloat-equal"
883
884
885 ALWAYS_INLINE void CMPL_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
886 PREAMBLE();
887 float val1 = shadow_frame.GetVRegFloat(inst->VRegB_23x());
888 float val2 = shadow_frame.GetVRegFloat(inst->VRegC_23x());
889 int32_t result;
890 if (val1 > val2) {
891 result = 1;
892 } else if (val1 == val2) {
893 result = 0;
894 } else {
895 result = -1;
896 }
897 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), result);
898 inst = inst->Next_2xx();
899 }
900
901 ALWAYS_INLINE void CMPG_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
902 PREAMBLE();
903 float val1 = shadow_frame.GetVRegFloat(inst->VRegB_23x());
904 float val2 = shadow_frame.GetVRegFloat(inst->VRegC_23x());
905 int32_t result;
906 if (val1 < val2) {
907 result = -1;
908 } else if (val1 == val2) {
909 result = 0;
910 } else {
911 result = 1;
912 }
913 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), result);
914 inst = inst->Next_2xx();
915 }
916
917 ALWAYS_INLINE void CMPL_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
918 PREAMBLE();
919 double val1 = shadow_frame.GetVRegDouble(inst->VRegB_23x());
920 double val2 = shadow_frame.GetVRegDouble(inst->VRegC_23x());
921 int32_t result;
922 if (val1 > val2) {
923 result = 1;
924 } else if (val1 == val2) {
925 result = 0;
926 } else {
927 result = -1;
928 }
929 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), result);
930 inst = inst->Next_2xx();
931 }
932
933
934 ALWAYS_INLINE void CMPG_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
935 PREAMBLE();
936 double val1 = shadow_frame.GetVRegDouble(inst->VRegB_23x());
937 double val2 = shadow_frame.GetVRegDouble(inst->VRegC_23x());
938 int32_t result;
939 if (val1 < val2) {
940 result = -1;
941 } else if (val1 == val2) {
942 result = 0;
943 } else {
944 result = 1;
945 }
946 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), result);
947 inst = inst->Next_2xx();
948 }
949
950#pragma clang diagnostic pop
951
952
953 ALWAYS_INLINE void CMP_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
954 PREAMBLE();
955 int64_t val1 = shadow_frame.GetVRegLong(inst->VRegB_23x());
956 int64_t val2 = shadow_frame.GetVRegLong(inst->VRegC_23x());
957 int32_t result;
958 if (val1 > val2) {
959 result = 1;
960 } else if (val1 == val2) {
961 result = 0;
962 } else {
963 result = -1;
964 }
965 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), result);
966 inst = inst->Next_2xx();
967 }
968
969 ALWAYS_INLINE void IF_EQ() REQUIRES_SHARED(Locks::mutator_lock_) {
970 PREAMBLE();
971 if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) ==
972 shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
973 int16_t offset = inst->VRegC_22t();
974 BRANCH_INSTRUMENTATION(offset);
975 inst = inst->RelativeAt(offset);
976 HANDLE_BACKWARD_BRANCH(offset);
977 } else {
978 BRANCH_INSTRUMENTATION(2);
979 inst = inst->Next_2xx();
980 }
981 }
982
983 ALWAYS_INLINE void IF_NE() REQUIRES_SHARED(Locks::mutator_lock_) {
984 PREAMBLE();
985 if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) !=
986 shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
987 int16_t offset = inst->VRegC_22t();
988 BRANCH_INSTRUMENTATION(offset);
989 inst = inst->RelativeAt(offset);
990 HANDLE_BACKWARD_BRANCH(offset);
991 } else {
992 BRANCH_INSTRUMENTATION(2);
993 inst = inst->Next_2xx();
994 }
995 }
996
997 ALWAYS_INLINE void IF_LT() REQUIRES_SHARED(Locks::mutator_lock_) {
998 PREAMBLE();
999 if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) <
1000 shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
1001 int16_t offset = inst->VRegC_22t();
1002 BRANCH_INSTRUMENTATION(offset);
1003 inst = inst->RelativeAt(offset);
1004 HANDLE_BACKWARD_BRANCH(offset);
1005 } else {
1006 BRANCH_INSTRUMENTATION(2);
1007 inst = inst->Next_2xx();
1008 }
1009 }
1010
1011 ALWAYS_INLINE void IF_GE() REQUIRES_SHARED(Locks::mutator_lock_) {
1012 PREAMBLE();
1013 if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) >=
1014 shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
1015 int16_t offset = inst->VRegC_22t();
1016 BRANCH_INSTRUMENTATION(offset);
1017 inst = inst->RelativeAt(offset);
1018 HANDLE_BACKWARD_BRANCH(offset);
1019 } else {
1020 BRANCH_INSTRUMENTATION(2);
1021 inst = inst->Next_2xx();
1022 }
1023 }
1024
1025 ALWAYS_INLINE void IF_GT() REQUIRES_SHARED(Locks::mutator_lock_) {
1026 PREAMBLE();
1027 if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) >
1028 shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
1029 int16_t offset = inst->VRegC_22t();
1030 BRANCH_INSTRUMENTATION(offset);
1031 inst = inst->RelativeAt(offset);
1032 HANDLE_BACKWARD_BRANCH(offset);
1033 } else {
1034 BRANCH_INSTRUMENTATION(2);
1035 inst = inst->Next_2xx();
1036 }
1037 }
1038
1039 ALWAYS_INLINE void IF_LE() REQUIRES_SHARED(Locks::mutator_lock_) {
1040 PREAMBLE();
1041 if (shadow_frame.GetVReg(inst->VRegA_22t(inst_data)) <=
1042 shadow_frame.GetVReg(inst->VRegB_22t(inst_data))) {
1043 int16_t offset = inst->VRegC_22t();
1044 BRANCH_INSTRUMENTATION(offset);
1045 inst = inst->RelativeAt(offset);
1046 HANDLE_BACKWARD_BRANCH(offset);
1047 } else {
1048 BRANCH_INSTRUMENTATION(2);
1049 inst = inst->Next_2xx();
1050 }
1051 }
1052
1053 ALWAYS_INLINE void IF_EQZ() REQUIRES_SHARED(Locks::mutator_lock_) {
1054 PREAMBLE();
1055 if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) == 0) {
1056 int16_t offset = inst->VRegB_21t();
1057 BRANCH_INSTRUMENTATION(offset);
1058 inst = inst->RelativeAt(offset);
1059 HANDLE_BACKWARD_BRANCH(offset);
1060 } else {
1061 BRANCH_INSTRUMENTATION(2);
1062 inst = inst->Next_2xx();
1063 }
1064 }
1065
1066 ALWAYS_INLINE void IF_NEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
1067 PREAMBLE();
1068 if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) != 0) {
1069 int16_t offset = inst->VRegB_21t();
1070 BRANCH_INSTRUMENTATION(offset);
1071 inst = inst->RelativeAt(offset);
1072 HANDLE_BACKWARD_BRANCH(offset);
1073 } else {
1074 BRANCH_INSTRUMENTATION(2);
1075 inst = inst->Next_2xx();
1076 }
1077 }
1078
1079 ALWAYS_INLINE void IF_LTZ() REQUIRES_SHARED(Locks::mutator_lock_) {
1080 PREAMBLE();
1081 if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) < 0) {
1082 int16_t offset = inst->VRegB_21t();
1083 BRANCH_INSTRUMENTATION(offset);
1084 inst = inst->RelativeAt(offset);
1085 HANDLE_BACKWARD_BRANCH(offset);
1086 } else {
1087 BRANCH_INSTRUMENTATION(2);
1088 inst = inst->Next_2xx();
1089 }
1090 }
1091
1092 ALWAYS_INLINE void IF_GEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
1093 PREAMBLE();
1094 if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) >= 0) {
1095 int16_t offset = inst->VRegB_21t();
1096 BRANCH_INSTRUMENTATION(offset);
1097 inst = inst->RelativeAt(offset);
1098 HANDLE_BACKWARD_BRANCH(offset);
1099 } else {
1100 BRANCH_INSTRUMENTATION(2);
1101 inst = inst->Next_2xx();
1102 }
1103 }
1104
1105 ALWAYS_INLINE void IF_GTZ() REQUIRES_SHARED(Locks::mutator_lock_) {
1106 PREAMBLE();
1107 if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) > 0) {
1108 int16_t offset = inst->VRegB_21t();
1109 BRANCH_INSTRUMENTATION(offset);
1110 inst = inst->RelativeAt(offset);
1111 HANDLE_BACKWARD_BRANCH(offset);
1112 } else {
1113 BRANCH_INSTRUMENTATION(2);
1114 inst = inst->Next_2xx();
1115 }
1116 }
1117
1118 ALWAYS_INLINE void IF_LEZ() REQUIRES_SHARED(Locks::mutator_lock_) {
1119 PREAMBLE();
1120 if (shadow_frame.GetVReg(inst->VRegA_21t(inst_data)) <= 0) {
1121 int16_t offset = inst->VRegB_21t();
1122 BRANCH_INSTRUMENTATION(offset);
1123 inst = inst->RelativeAt(offset);
1124 HANDLE_BACKWARD_BRANCH(offset);
1125 } else {
1126 BRANCH_INSTRUMENTATION(2);
1127 inst = inst->Next_2xx();
1128 }
1129 }
1130
1131 ALWAYS_INLINE void AGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
1132 PREAMBLE();
1133 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1134 if (UNLIKELY(a == nullptr)) {
1135 ThrowNullPointerExceptionFromInterpreter();
1136 HANDLE_PENDING_EXCEPTION();
1137 }
1138 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1139 ObjPtr<mirror::BooleanArray> array = a->AsBooleanArray();
1140 if (array->CheckIsValidIndex(index)) {
1141 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
1142 inst = inst->Next_2xx();
1143 } else {
1144 HANDLE_PENDING_EXCEPTION();
1145 }
1146 }
1147
1148 ALWAYS_INLINE void AGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
1149 PREAMBLE();
1150 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1151 if (UNLIKELY(a == nullptr)) {
1152 ThrowNullPointerExceptionFromInterpreter();
1153 HANDLE_PENDING_EXCEPTION();
1154 }
1155 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1156 ObjPtr<mirror::ByteArray> array = a->AsByteArray();
1157 if (array->CheckIsValidIndex(index)) {
1158 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
1159 inst = inst->Next_2xx();
1160 } else {
1161 HANDLE_PENDING_EXCEPTION();
1162 }
1163 }
1164
1165 ALWAYS_INLINE void AGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
1166 PREAMBLE();
1167 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1168 if (UNLIKELY(a == nullptr)) {
1169 ThrowNullPointerExceptionFromInterpreter();
1170 HANDLE_PENDING_EXCEPTION();
1171 }
1172 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1173 ObjPtr<mirror::CharArray> array = a->AsCharArray();
1174 if (array->CheckIsValidIndex(index)) {
1175 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
1176 inst = inst->Next_2xx();
1177 } else {
1178 HANDLE_PENDING_EXCEPTION();
1179 }
1180 }
1181
1182 ALWAYS_INLINE void AGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
1183 PREAMBLE();
1184 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1185 if (UNLIKELY(a == nullptr)) {
1186 ThrowNullPointerExceptionFromInterpreter();
1187 HANDLE_PENDING_EXCEPTION();
1188 }
1189 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1190 ObjPtr<mirror::ShortArray> array = a->AsShortArray();
1191 if (array->CheckIsValidIndex(index)) {
1192 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
1193 inst = inst->Next_2xx();
1194 } else {
1195 HANDLE_PENDING_EXCEPTION();
1196 }
1197 }
1198
1199 ALWAYS_INLINE void AGET() REQUIRES_SHARED(Locks::mutator_lock_) {
1200 PREAMBLE();
1201 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1202 if (UNLIKELY(a == nullptr)) {
1203 ThrowNullPointerExceptionFromInterpreter();
1204 HANDLE_PENDING_EXCEPTION();
1205 }
1206 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1207 DCHECK(a->IsIntArray() || a->IsFloatArray()) << a->PrettyTypeOf();
1208 ObjPtr<mirror::IntArray> array = ObjPtr<mirror::IntArray>::DownCast(a);
1209 if (array->CheckIsValidIndex(index)) {
1210 shadow_frame.SetVReg(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
1211 inst = inst->Next_2xx();
1212 } else {
1213 HANDLE_PENDING_EXCEPTION();
1214 }
1215 }
1216
1217 ALWAYS_INLINE void AGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
1218 PREAMBLE();
1219 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1220 if (UNLIKELY(a == nullptr)) {
1221 ThrowNullPointerExceptionFromInterpreter();
1222 HANDLE_PENDING_EXCEPTION();
1223 }
1224 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1225 DCHECK(a->IsLongArray() || a->IsDoubleArray()) << a->PrettyTypeOf();
1226 ObjPtr<mirror::LongArray> array = ObjPtr<mirror::LongArray>::DownCast(a);
1227 if (array->CheckIsValidIndex(index)) {
1228 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
1229 inst = inst->Next_2xx();
1230 } else {
1231 HANDLE_PENDING_EXCEPTION();
1232 }
1233 }
1234
1235 ALWAYS_INLINE void AGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
1236 PREAMBLE();
1237 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1238 if (UNLIKELY(a == nullptr)) {
1239 ThrowNullPointerExceptionFromInterpreter();
1240 HANDLE_PENDING_EXCEPTION();
1241 }
1242 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1243 ObjPtr<mirror::ObjectArray<mirror::Object>> array = a->AsObjectArray<mirror::Object>();
1244 if (array->CheckIsValidIndex(index)) {
1245 shadow_frame.SetVRegReference(inst->VRegA_23x(inst_data), array->GetWithoutChecks(index));
1246 inst = inst->Next_2xx();
1247 } else {
1248 HANDLE_PENDING_EXCEPTION();
1249 }
1250 }
1251
1252 ALWAYS_INLINE void APUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
1253 PREAMBLE();
1254 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1255 if (UNLIKELY(a == nullptr)) {
1256 ThrowNullPointerExceptionFromInterpreter();
1257 HANDLE_PENDING_EXCEPTION();
1258 }
1259 uint8_t val = shadow_frame.GetVReg(inst->VRegA_23x(inst_data));
1260 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1261 ObjPtr<mirror::BooleanArray> array = a->AsBooleanArray();
1262 if (array->CheckIsValidIndex(index)) {
1263 array->SetWithoutChecks<transaction_active>(index, val);
1264 inst = inst->Next_2xx();
1265 } else {
1266 HANDLE_PENDING_EXCEPTION();
1267 }
1268 }
1269
1270 ALWAYS_INLINE void APUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
1271 PREAMBLE();
1272 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1273 if (UNLIKELY(a == nullptr)) {
1274 ThrowNullPointerExceptionFromInterpreter();
1275 HANDLE_PENDING_EXCEPTION();
1276 }
1277 int8_t val = shadow_frame.GetVReg(inst->VRegA_23x(inst_data));
1278 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1279 ObjPtr<mirror::ByteArray> array = a->AsByteArray();
1280 if (array->CheckIsValidIndex(index)) {
1281 array->SetWithoutChecks<transaction_active>(index, val);
1282 inst = inst->Next_2xx();
1283 } else {
1284 HANDLE_PENDING_EXCEPTION();
1285 }
1286 }
1287
1288 ALWAYS_INLINE void APUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
1289 PREAMBLE();
1290 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1291 if (UNLIKELY(a == nullptr)) {
1292 ThrowNullPointerExceptionFromInterpreter();
1293 HANDLE_PENDING_EXCEPTION();
1294 }
1295 uint16_t val = shadow_frame.GetVReg(inst->VRegA_23x(inst_data));
1296 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1297 ObjPtr<mirror::CharArray> array = a->AsCharArray();
1298 if (array->CheckIsValidIndex(index)) {
1299 array->SetWithoutChecks<transaction_active>(index, val);
1300 inst = inst->Next_2xx();
1301 } else {
1302 HANDLE_PENDING_EXCEPTION();
1303 }
1304 }
1305
1306 ALWAYS_INLINE void APUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
1307 PREAMBLE();
1308 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1309 if (UNLIKELY(a == nullptr)) {
1310 ThrowNullPointerExceptionFromInterpreter();
1311 HANDLE_PENDING_EXCEPTION();
1312 }
1313 int16_t val = shadow_frame.GetVReg(inst->VRegA_23x(inst_data));
1314 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1315 ObjPtr<mirror::ShortArray> array = a->AsShortArray();
1316 if (array->CheckIsValidIndex(index)) {
1317 array->SetWithoutChecks<transaction_active>(index, val);
1318 inst = inst->Next_2xx();
1319 } else {
1320 HANDLE_PENDING_EXCEPTION();
1321 }
1322 }
1323
1324 ALWAYS_INLINE void APUT() REQUIRES_SHARED(Locks::mutator_lock_) {
1325 PREAMBLE();
1326 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1327 if (UNLIKELY(a == nullptr)) {
1328 ThrowNullPointerExceptionFromInterpreter();
1329 HANDLE_PENDING_EXCEPTION();
1330 }
1331 int32_t val = shadow_frame.GetVReg(inst->VRegA_23x(inst_data));
1332 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1333 DCHECK(a->IsIntArray() || a->IsFloatArray()) << a->PrettyTypeOf();
1334 ObjPtr<mirror::IntArray> array = ObjPtr<mirror::IntArray>::DownCast(a);
1335 if (array->CheckIsValidIndex(index)) {
1336 array->SetWithoutChecks<transaction_active>(index, val);
1337 inst = inst->Next_2xx();
1338 } else {
1339 HANDLE_PENDING_EXCEPTION();
1340 }
1341 }
1342
1343 ALWAYS_INLINE void APUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
1344 PREAMBLE();
1345 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1346 if (UNLIKELY(a == nullptr)) {
1347 ThrowNullPointerExceptionFromInterpreter();
1348 HANDLE_PENDING_EXCEPTION();
1349 }
1350 int64_t val = shadow_frame.GetVRegLong(inst->VRegA_23x(inst_data));
1351 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1352 DCHECK(a->IsLongArray() || a->IsDoubleArray()) << a->PrettyTypeOf();
1353 ObjPtr<mirror::LongArray> array = ObjPtr<mirror::LongArray>::DownCast(a);
1354 if (array->CheckIsValidIndex(index)) {
1355 array->SetWithoutChecks<transaction_active>(index, val);
1356 inst = inst->Next_2xx();
1357 } else {
1358 HANDLE_PENDING_EXCEPTION();
1359 }
1360 }
1361
1362 ALWAYS_INLINE void APUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
1363 PREAMBLE();
1364 ObjPtr<mirror::Object> a = shadow_frame.GetVRegReference(inst->VRegB_23x());
1365 if (UNLIKELY(a == nullptr)) {
1366 ThrowNullPointerExceptionFromInterpreter();
1367 HANDLE_PENDING_EXCEPTION();
1368 }
1369 int32_t index = shadow_frame.GetVReg(inst->VRegC_23x());
1370 ObjPtr<mirror::Object> val = shadow_frame.GetVRegReference(inst->VRegA_23x(inst_data));
1371 ObjPtr<mirror::ObjectArray<mirror::Object>> array = a->AsObjectArray<mirror::Object>();
1372 if (array->CheckIsValidIndex(index) && array->CheckAssignable(val)) {
1373 array->SetWithoutChecks<transaction_active>(index, val);
1374 inst = inst->Next_2xx();
1375 } else {
1376 HANDLE_PENDING_EXCEPTION();
1377 }
1378 }
1379
1380 ALWAYS_INLINE void IGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
1381 PREAMBLE();
1382 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimBoolean, do_access_check>(
1383 self, shadow_frame, inst, inst_data);
1384 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1385 }
1386
1387 ALWAYS_INLINE void IGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
1388 PREAMBLE();
1389 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimByte, do_access_check>(
1390 self, shadow_frame, inst, inst_data);
1391 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1392 }
1393
1394 ALWAYS_INLINE void IGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
1395 PREAMBLE();
1396 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimChar, do_access_check>(
1397 self, shadow_frame, inst, inst_data);
1398 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1399 }
1400
1401 ALWAYS_INLINE void IGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
1402 PREAMBLE();
1403 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimShort, do_access_check>(
1404 self, shadow_frame, inst, inst_data);
1405 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1406 }
1407
1408 ALWAYS_INLINE void IGET() REQUIRES_SHARED(Locks::mutator_lock_) {
1409 PREAMBLE();
1410 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimInt, do_access_check>(
1411 self, shadow_frame, inst, inst_data);
1412 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1413 }
1414
1415 ALWAYS_INLINE void IGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
1416 PREAMBLE();
1417 bool success = DoFieldGet<InstancePrimitiveRead, Primitive::kPrimLong, do_access_check>(
1418 self, shadow_frame, inst, inst_data);
1419 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1420 }
1421
1422 ALWAYS_INLINE void IGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
1423 PREAMBLE();
1424 bool success = DoFieldGet<InstanceObjectRead, Primitive::kPrimNot, do_access_check>(
1425 self, shadow_frame, inst, inst_data);
1426 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1427 }
1428
1429 ALWAYS_INLINE void IGET_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
1430 PREAMBLE();
1431 bool success = DoIGetQuick<Primitive::kPrimInt>(shadow_frame, inst, inst_data);
1432 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1433 }
1434
1435 ALWAYS_INLINE void IGET_WIDE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
1436 PREAMBLE();
1437 bool success = DoIGetQuick<Primitive::kPrimLong>(shadow_frame, inst, inst_data);
1438 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1439 }
1440
1441 ALWAYS_INLINE void IGET_OBJECT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
1442 PREAMBLE();
1443 bool success = DoIGetQuick<Primitive::kPrimNot>(shadow_frame, inst, inst_data);
1444 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1445 }
1446
1447 ALWAYS_INLINE void IGET_BOOLEAN_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
1448 PREAMBLE();
1449 bool success = DoIGetQuick<Primitive::kPrimBoolean>(shadow_frame, inst, inst_data);
1450 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1451 }
1452
1453 ALWAYS_INLINE void IGET_BYTE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
1454 PREAMBLE();
1455 bool success = DoIGetQuick<Primitive::kPrimByte>(shadow_frame, inst, inst_data);
1456 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1457 }
1458
1459 ALWAYS_INLINE void IGET_CHAR_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
1460 PREAMBLE();
1461 bool success = DoIGetQuick<Primitive::kPrimChar>(shadow_frame, inst, inst_data);
1462 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1463 }
1464
1465 ALWAYS_INLINE void IGET_SHORT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
1466 PREAMBLE();
1467 bool success = DoIGetQuick<Primitive::kPrimShort>(shadow_frame, inst, inst_data);
1468 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1469 }
1470
1471 ALWAYS_INLINE void SGET_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
1472 PREAMBLE();
1473 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimBoolean, do_access_check,
1474 transaction_active>(self, shadow_frame, inst, inst_data);
1475 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1476 }
1477
1478 ALWAYS_INLINE void SGET_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
1479 PREAMBLE();
1480 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimByte, do_access_check,
1481 transaction_active>(self, shadow_frame, inst, inst_data);
1482 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1483 }
1484
1485 ALWAYS_INLINE void SGET_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
1486 PREAMBLE();
1487 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimChar, do_access_check,
1488 transaction_active>(self, shadow_frame, inst, inst_data);
1489 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1490 }
1491
1492 ALWAYS_INLINE void SGET_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
1493 PREAMBLE();
1494 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimShort, do_access_check,
1495 transaction_active>(self, shadow_frame, inst, inst_data);
1496 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1497 }
1498
1499 ALWAYS_INLINE void SGET() REQUIRES_SHARED(Locks::mutator_lock_) {
1500 PREAMBLE();
1501 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimInt, do_access_check,
1502 transaction_active>(self, shadow_frame, inst, inst_data);
1503 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1504 }
1505
1506 ALWAYS_INLINE void SGET_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
1507 PREAMBLE();
1508 bool success = DoFieldGet<StaticPrimitiveRead, Primitive::kPrimLong, do_access_check,
1509 transaction_active>(self, shadow_frame, inst, inst_data);
1510 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1511 }
1512
1513 ALWAYS_INLINE void SGET_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
1514 PREAMBLE();
1515 bool success = DoFieldGet<StaticObjectRead, Primitive::kPrimNot, do_access_check,
1516 transaction_active>(self, shadow_frame, inst, inst_data);
1517 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1518 }
1519
1520 ALWAYS_INLINE void IPUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
1521 PREAMBLE();
1522 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimBoolean, 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 IPUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
1528 PREAMBLE();
1529 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimByte, do_access_check,
1530 transaction_active>(self, shadow_frame, inst, inst_data);
1531 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1532 }
1533
1534 ALWAYS_INLINE void IPUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
1535 PREAMBLE();
1536 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimChar, do_access_check,
1537 transaction_active>(self, shadow_frame, inst, inst_data);
1538 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1539 }
1540
1541 ALWAYS_INLINE void IPUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
1542 PREAMBLE();
1543 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimShort, do_access_check,
1544 transaction_active>(self, shadow_frame, inst, inst_data);
1545 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1546 }
1547
1548 ALWAYS_INLINE void IPUT() REQUIRES_SHARED(Locks::mutator_lock_) {
1549 PREAMBLE();
1550 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimInt, do_access_check,
1551 transaction_active>(self, shadow_frame, inst, inst_data);
1552 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1553 }
1554
1555 ALWAYS_INLINE void IPUT_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
1556 PREAMBLE();
1557 bool success = DoFieldPut<InstancePrimitiveWrite, Primitive::kPrimLong, do_access_check,
1558 transaction_active>(self, shadow_frame, inst, inst_data);
1559 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1560 }
1561
1562 ALWAYS_INLINE void IPUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
1563 PREAMBLE();
1564 bool success = DoFieldPut<InstanceObjectWrite, Primitive::kPrimNot, 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_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
1570 PREAMBLE();
1571 bool success = DoIPutQuick<Primitive::kPrimInt, transaction_active>(
1572 shadow_frame, inst, inst_data);
1573 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1574 }
1575
1576 ALWAYS_INLINE void IPUT_BOOLEAN_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
1577 PREAMBLE();
1578 bool success = DoIPutQuick<Primitive::kPrimBoolean, transaction_active>(
1579 shadow_frame, inst, inst_data);
1580 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1581 }
1582
1583 ALWAYS_INLINE void IPUT_BYTE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
1584 PREAMBLE();
1585 bool success = DoIPutQuick<Primitive::kPrimByte, transaction_active>(
1586 shadow_frame, inst, inst_data);
1587 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1588 }
1589
1590 ALWAYS_INLINE void IPUT_CHAR_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
1591 PREAMBLE();
1592 bool success = DoIPutQuick<Primitive::kPrimChar, transaction_active>(
1593 shadow_frame, inst, inst_data);
1594 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1595 }
1596
1597 ALWAYS_INLINE void IPUT_SHORT_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
1598 PREAMBLE();
1599 bool success = DoIPutQuick<Primitive::kPrimShort, transaction_active>(
1600 shadow_frame, inst, inst_data);
1601 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1602 }
1603
1604 ALWAYS_INLINE void IPUT_WIDE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
1605 PREAMBLE();
1606 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_) {
1612 PREAMBLE();
1613 bool success = DoIPutQuick<Primitive::kPrimNot, transaction_active>(
1614 shadow_frame, inst, inst_data);
1615 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1616 }
1617
1618 ALWAYS_INLINE void SPUT_BOOLEAN() REQUIRES_SHARED(Locks::mutator_lock_) {
1619 PREAMBLE();
1620 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimBoolean, do_access_check,
1621 transaction_active>(self, shadow_frame, inst, inst_data);
1622 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1623 }
1624
1625 ALWAYS_INLINE void SPUT_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
1626 PREAMBLE();
1627 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimByte, do_access_check,
1628 transaction_active>(self, shadow_frame, inst, inst_data);
1629 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1630 }
1631
1632 ALWAYS_INLINE void SPUT_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
1633 PREAMBLE();
1634 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimChar, do_access_check,
1635 transaction_active>(self, shadow_frame, inst, inst_data);
1636 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1637 }
1638
1639 ALWAYS_INLINE void SPUT_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
1640 PREAMBLE();
1641 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimShort, do_access_check,
1642 transaction_active>(self, shadow_frame, inst, inst_data);
1643 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1644 }
1645
1646 ALWAYS_INLINE void SPUT() REQUIRES_SHARED(Locks::mutator_lock_) {
1647 PREAMBLE();
1648 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimInt, 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_WIDE() REQUIRES_SHARED(Locks::mutator_lock_) {
1654 PREAMBLE();
1655 bool success = DoFieldPut<StaticPrimitiveWrite, Primitive::kPrimLong, do_access_check,
1656 transaction_active>(self, shadow_frame, inst, inst_data);
1657 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1658 }
1659
1660 ALWAYS_INLINE void SPUT_OBJECT() REQUIRES_SHARED(Locks::mutator_lock_) {
1661 PREAMBLE();
1662 bool success = DoFieldPut<StaticObjectWrite, Primitive::kPrimNot, do_access_check,
1663 transaction_active>(self, shadow_frame, inst, inst_data);
1664 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1665 }
1666
1667 ALWAYS_INLINE void INVOKE_VIRTUAL() REQUIRES_SHARED(Locks::mutator_lock_) {
1668 PREAMBLE();
1669 bool success = DoInvoke<kVirtual, false, do_access_check, /*is_mterp=*/ false>(
1670 self, shadow_frame, inst, inst_data, ResultRegister());
1671 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1672 }
1673
1674 ALWAYS_INLINE void INVOKE_VIRTUAL_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
1675 PREAMBLE();
1676 bool success = DoInvoke<kVirtual, true, do_access_check, /*is_mterp=*/ false>(
1677 self, shadow_frame, inst, inst_data, ResultRegister());
1678 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1679 }
1680
1681 ALWAYS_INLINE void INVOKE_SUPER() REQUIRES_SHARED(Locks::mutator_lock_) {
1682 PREAMBLE();
1683 bool success = DoInvoke<kSuper, false, do_access_check, /*is_mterp=*/ false>(
1684 self, shadow_frame, inst, inst_data, ResultRegister());
1685 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1686 }
1687
1688 ALWAYS_INLINE void INVOKE_SUPER_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
1689 PREAMBLE();
1690 bool success = DoInvoke<kSuper, 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_DIRECT() REQUIRES_SHARED(Locks::mutator_lock_) {
1696 PREAMBLE();
1697 bool success = DoInvoke<kDirect, false, do_access_check, /*is_mterp=*/ false>(
1698 self, shadow_frame, inst, inst_data, ResultRegister());
1699 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1700 }
1701
1702 ALWAYS_INLINE void INVOKE_DIRECT_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
1703 PREAMBLE();
1704 bool success = DoInvoke<kDirect, true, do_access_check, /*is_mterp=*/ false>(
1705 self, shadow_frame, inst, inst_data, ResultRegister());
1706 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1707 }
1708
1709 ALWAYS_INLINE void INVOKE_INTERFACE() REQUIRES_SHARED(Locks::mutator_lock_) {
1710 PREAMBLE();
1711 bool success = DoInvoke<kInterface, false, do_access_check, /*is_mterp=*/ false>(
1712 self, shadow_frame, inst, inst_data, ResultRegister());
1713 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1714 }
1715
1716 ALWAYS_INLINE void INVOKE_INTERFACE_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
1717 PREAMBLE();
1718 bool success = DoInvoke<kInterface, true, do_access_check, /*is_mterp=*/ false>(
1719 self, shadow_frame, inst, inst_data, ResultRegister());
1720 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1721 }
1722
1723 ALWAYS_INLINE void INVOKE_STATIC() REQUIRES_SHARED(Locks::mutator_lock_) {
1724 PREAMBLE();
1725 bool success = DoInvoke<kStatic, false, do_access_check, /*is_mterp=*/ false>(
1726 self, shadow_frame, inst, inst_data, ResultRegister());
1727 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1728 }
1729
1730 ALWAYS_INLINE void INVOKE_STATIC_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
1731 PREAMBLE();
1732 bool success = DoInvoke<kStatic, true, do_access_check, /*is_mterp=*/ false>(
1733 self, shadow_frame, inst, inst_data, ResultRegister());
1734 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1735 }
1736
1737 ALWAYS_INLINE void INVOKE_VIRTUAL_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
1738 PREAMBLE();
1739 bool success = DoInvoke<kVirtual, false, do_access_check, /*is_mterp=*/ false,
1740 /*is_quick=*/ true>(self, shadow_frame, inst, inst_data, ResultRegister());
1741 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1742 }
1743
1744 ALWAYS_INLINE void INVOKE_VIRTUAL_RANGE_QUICK() REQUIRES_SHARED(Locks::mutator_lock_) {
1745 PREAMBLE();
1746 bool success = DoInvoke<kVirtual, true, do_access_check, /*is_mterp=*/ false,
1747 /*is_quick=*/ true>(self, shadow_frame, inst, inst_data, ResultRegister());
1748 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1749 }
1750
1751 ALWAYS_INLINE void INVOKE_POLYMORPHIC() REQUIRES_SHARED(Locks::mutator_lock_) {
1752 PREAMBLE();
1753 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1754 bool success = DoInvokePolymorphic</* is_range= */ false>(
1755 self, shadow_frame, inst, inst_data, ResultRegister());
1756 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(!success);
1757 }
1758
1759 ALWAYS_INLINE void INVOKE_POLYMORPHIC_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
1760 PREAMBLE();
1761 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1762 bool success = DoInvokePolymorphic</* is_range= */ true>(
1763 self, shadow_frame, inst, inst_data, ResultRegister());
1764 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC(!success);
1765 }
1766
1767 ALWAYS_INLINE void INVOKE_CUSTOM() REQUIRES_SHARED(Locks::mutator_lock_) {
1768 PREAMBLE();
1769 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1770 bool success = DoInvokeCustom</* is_range= */ false>(
1771 self, shadow_frame, inst, inst_data, ResultRegister());
1772 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1773 }
1774
1775 ALWAYS_INLINE void INVOKE_CUSTOM_RANGE() REQUIRES_SHARED(Locks::mutator_lock_) {
1776 PREAMBLE();
1777 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1778 bool success = DoInvokeCustom</* is_range= */ true>(
1779 self, shadow_frame, inst, inst_data, ResultRegister());
1780 POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE(!success);
1781 }
1782
1783 ALWAYS_INLINE void NEG_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
1784 PREAMBLE();
1785 shadow_frame.SetVReg(
1786 inst->VRegA_12x(inst_data), -shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
1787 inst = inst->Next_1xx();
1788 }
1789
1790 ALWAYS_INLINE void NOT_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
1791 PREAMBLE();
1792 shadow_frame.SetVReg(
1793 inst->VRegA_12x(inst_data), ~shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
1794 inst = inst->Next_1xx();
1795 }
1796
1797 ALWAYS_INLINE void NEG_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
1798 PREAMBLE();
1799 shadow_frame.SetVRegLong(
1800 inst->VRegA_12x(inst_data), -shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
1801 inst = inst->Next_1xx();
1802 }
1803
1804 ALWAYS_INLINE void NOT_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
1805 PREAMBLE();
1806 shadow_frame.SetVRegLong(
1807 inst->VRegA_12x(inst_data), ~shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
1808 inst = inst->Next_1xx();
1809 }
1810
1811 ALWAYS_INLINE void NEG_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
1812 PREAMBLE();
1813 shadow_frame.SetVRegFloat(
1814 inst->VRegA_12x(inst_data), -shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
1815 inst = inst->Next_1xx();
1816 }
1817
1818 ALWAYS_INLINE void NEG_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
1819 PREAMBLE();
1820 shadow_frame.SetVRegDouble(
1821 inst->VRegA_12x(inst_data), -shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
1822 inst = inst->Next_1xx();
1823 }
1824
1825 ALWAYS_INLINE void INT_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
1826 PREAMBLE();
1827 shadow_frame.SetVRegLong(inst->VRegA_12x(inst_data),
1828 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
1829 inst = inst->Next_1xx();
1830 }
1831
1832 ALWAYS_INLINE void INT_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
1833 PREAMBLE();
1834 shadow_frame.SetVRegFloat(inst->VRegA_12x(inst_data),
1835 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
1836 inst = inst->Next_1xx();
1837 }
1838
1839 ALWAYS_INLINE void INT_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
1840 PREAMBLE();
1841 shadow_frame.SetVRegDouble(inst->VRegA_12x(inst_data),
1842 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
1843 inst = inst->Next_1xx();
1844 }
1845
1846 ALWAYS_INLINE void LONG_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
1847 PREAMBLE();
1848 shadow_frame.SetVReg(inst->VRegA_12x(inst_data),
1849 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
1850 inst = inst->Next_1xx();
1851 }
1852
1853 ALWAYS_INLINE void LONG_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
1854 PREAMBLE();
1855 shadow_frame.SetVRegFloat(inst->VRegA_12x(inst_data),
1856 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
1857 inst = inst->Next_1xx();
1858 }
1859
1860 ALWAYS_INLINE void LONG_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
1861 PREAMBLE();
1862 shadow_frame.SetVRegDouble(inst->VRegA_12x(inst_data),
1863 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
1864 inst = inst->Next_1xx();
1865 }
1866
1867 ALWAYS_INLINE void FLOAT_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
1868 PREAMBLE();
1869 float val = shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data));
1870 int32_t result = art_float_to_integral<int32_t, float>(val);
1871 shadow_frame.SetVReg(inst->VRegA_12x(inst_data), result);
1872 inst = inst->Next_1xx();
1873 }
1874
1875 ALWAYS_INLINE void FLOAT_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
1876 PREAMBLE();
1877 float val = shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data));
1878 int64_t result = art_float_to_integral<int64_t, float>(val);
1879 shadow_frame.SetVRegLong(inst->VRegA_12x(inst_data), result);
1880 inst = inst->Next_1xx();
1881 }
1882
1883 ALWAYS_INLINE void FLOAT_TO_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
1884 PREAMBLE();
1885 shadow_frame.SetVRegDouble(inst->VRegA_12x(inst_data),
1886 shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
1887 inst = inst->Next_1xx();
1888 }
1889
1890 ALWAYS_INLINE void DOUBLE_TO_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
1891 PREAMBLE();
1892 double val = shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data));
1893 int32_t result = art_float_to_integral<int32_t, double>(val);
1894 shadow_frame.SetVReg(inst->VRegA_12x(inst_data), result);
1895 inst = inst->Next_1xx();
1896 }
1897
1898 ALWAYS_INLINE void DOUBLE_TO_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
1899 PREAMBLE();
1900 double val = shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data));
1901 int64_t result = art_float_to_integral<int64_t, double>(val);
1902 shadow_frame.SetVRegLong(inst->VRegA_12x(inst_data), result);
1903 inst = inst->Next_1xx();
1904 }
1905
1906 ALWAYS_INLINE void DOUBLE_TO_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
1907 PREAMBLE();
1908 shadow_frame.SetVRegFloat(inst->VRegA_12x(inst_data),
1909 shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
1910 inst = inst->Next_1xx();
1911 }
1912
1913 ALWAYS_INLINE void INT_TO_BYTE() REQUIRES_SHARED(Locks::mutator_lock_) {
1914 PREAMBLE();
1915 shadow_frame.SetVReg(inst->VRegA_12x(inst_data), static_cast<int8_t>(
1916 shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
1917 inst = inst->Next_1xx();
1918 }
1919
1920 ALWAYS_INLINE void INT_TO_CHAR() REQUIRES_SHARED(Locks::mutator_lock_) {
1921 PREAMBLE();
1922 shadow_frame.SetVReg(inst->VRegA_12x(inst_data), static_cast<uint16_t>(
1923 shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
1924 inst = inst->Next_1xx();
1925 }
1926
1927 ALWAYS_INLINE void INT_TO_SHORT() REQUIRES_SHARED(Locks::mutator_lock_) {
1928 PREAMBLE();
1929 shadow_frame.SetVReg(inst->VRegA_12x(inst_data), static_cast<int16_t>(
1930 shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
1931 inst = inst->Next_1xx();
1932 }
1933
1934 ALWAYS_INLINE void ADD_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
1935 PREAMBLE();
1936 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1937 SafeAdd(shadow_frame.GetVReg(inst->VRegB_23x()),
1938 shadow_frame.GetVReg(inst->VRegC_23x())));
1939 inst = inst->Next_2xx();
1940 }
1941
1942 ALWAYS_INLINE void SUB_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
1943 PREAMBLE();
1944 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1945 SafeSub(shadow_frame.GetVReg(inst->VRegB_23x()),
1946 shadow_frame.GetVReg(inst->VRegC_23x())));
1947 inst = inst->Next_2xx();
1948 }
1949
1950 ALWAYS_INLINE void MUL_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
1951 PREAMBLE();
1952 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1953 SafeMul(shadow_frame.GetVReg(inst->VRegB_23x()),
1954 shadow_frame.GetVReg(inst->VRegC_23x())));
1955 inst = inst->Next_2xx();
1956 }
1957
1958 ALWAYS_INLINE void DIV_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
1959 PREAMBLE();
1960 bool success = DoIntDivide(shadow_frame, inst->VRegA_23x(inst_data),
1961 shadow_frame.GetVReg(inst->VRegB_23x()),
1962 shadow_frame.GetVReg(inst->VRegC_23x()));
1963 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1964 }
1965
1966 ALWAYS_INLINE void REM_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
1967 PREAMBLE();
1968 bool success = DoIntRemainder(shadow_frame, inst->VRegA_23x(inst_data),
1969 shadow_frame.GetVReg(inst->VRegB_23x()),
1970 shadow_frame.GetVReg(inst->VRegC_23x()));
1971 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
1972 }
1973
1974 ALWAYS_INLINE void SHL_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
1975 PREAMBLE();
1976 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1977 shadow_frame.GetVReg(inst->VRegB_23x()) <<
1978 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x1f));
1979 inst = inst->Next_2xx();
1980 }
1981
1982 ALWAYS_INLINE void SHR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
1983 PREAMBLE();
1984 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1985 shadow_frame.GetVReg(inst->VRegB_23x()) >>
1986 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x1f));
1987 inst = inst->Next_2xx();
1988 }
1989
1990 ALWAYS_INLINE void USHR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
1991 PREAMBLE();
1992 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
1993 static_cast<uint32_t>(shadow_frame.GetVReg(inst->VRegB_23x())) >>
1994 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x1f));
1995 inst = inst->Next_2xx();
1996 }
1997
1998 ALWAYS_INLINE void AND_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
1999 PREAMBLE();
2000 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
2001 shadow_frame.GetVReg(inst->VRegB_23x()) &
2002 shadow_frame.GetVReg(inst->VRegC_23x()));
2003 inst = inst->Next_2xx();
2004 }
2005
2006 ALWAYS_INLINE void OR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
2007 PREAMBLE();
2008 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
2009 shadow_frame.GetVReg(inst->VRegB_23x()) |
2010 shadow_frame.GetVReg(inst->VRegC_23x()));
2011 inst = inst->Next_2xx();
2012 }
2013
2014 ALWAYS_INLINE void XOR_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
2015 PREAMBLE();
2016 shadow_frame.SetVReg(inst->VRegA_23x(inst_data),
2017 shadow_frame.GetVReg(inst->VRegB_23x()) ^
2018 shadow_frame.GetVReg(inst->VRegC_23x()));
2019 inst = inst->Next_2xx();
2020 }
2021
2022 ALWAYS_INLINE void ADD_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
2023 PREAMBLE();
2024 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
2025 SafeAdd(shadow_frame.GetVRegLong(inst->VRegB_23x()),
2026 shadow_frame.GetVRegLong(inst->VRegC_23x())));
2027 inst = inst->Next_2xx();
2028 }
2029
2030 ALWAYS_INLINE void SUB_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
2031 PREAMBLE();
2032 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
2033 SafeSub(shadow_frame.GetVRegLong(inst->VRegB_23x()),
2034 shadow_frame.GetVRegLong(inst->VRegC_23x())));
2035 inst = inst->Next_2xx();
2036 }
2037
2038 ALWAYS_INLINE void MUL_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
2039 PREAMBLE();
2040 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
2041 SafeMul(shadow_frame.GetVRegLong(inst->VRegB_23x()),
2042 shadow_frame.GetVRegLong(inst->VRegC_23x())));
2043 inst = inst->Next_2xx();
2044 }
2045
2046 ALWAYS_INLINE void DIV_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
2047 PREAMBLE();
2048 DoLongDivide(shadow_frame, inst->VRegA_23x(inst_data),
2049 shadow_frame.GetVRegLong(inst->VRegB_23x()),
2050 shadow_frame.GetVRegLong(inst->VRegC_23x()));
2051 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_2xx);
2052 }
2053
2054 ALWAYS_INLINE void REM_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
2055 PREAMBLE();
2056 DoLongRemainder(shadow_frame, inst->VRegA_23x(inst_data),
2057 shadow_frame.GetVRegLong(inst->VRegB_23x()),
2058 shadow_frame.GetVRegLong(inst->VRegC_23x()));
2059 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_2xx);
2060 }
2061
2062 ALWAYS_INLINE void AND_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
2063 PREAMBLE();
2064 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
2065 shadow_frame.GetVRegLong(inst->VRegB_23x()) &
2066 shadow_frame.GetVRegLong(inst->VRegC_23x()));
2067 inst = inst->Next_2xx();
2068 }
2069
2070 ALWAYS_INLINE void OR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
2071 PREAMBLE();
2072 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
2073 shadow_frame.GetVRegLong(inst->VRegB_23x()) |
2074 shadow_frame.GetVRegLong(inst->VRegC_23x()));
2075 inst = inst->Next_2xx();
2076 }
2077
2078 ALWAYS_INLINE void XOR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
2079 PREAMBLE();
2080 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
2081 shadow_frame.GetVRegLong(inst->VRegB_23x()) ^
2082 shadow_frame.GetVRegLong(inst->VRegC_23x()));
2083 inst = inst->Next_2xx();
2084 }
2085
2086 ALWAYS_INLINE void SHL_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
2087 PREAMBLE();
2088 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
2089 shadow_frame.GetVRegLong(inst->VRegB_23x()) <<
2090 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x3f));
2091 inst = inst->Next_2xx();
2092 }
2093
2094 ALWAYS_INLINE void SHR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
2095 PREAMBLE();
2096 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
2097 shadow_frame.GetVRegLong(inst->VRegB_23x()) >>
2098 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x3f));
2099 inst = inst->Next_2xx();
2100 }
2101
2102 ALWAYS_INLINE void USHR_LONG() REQUIRES_SHARED(Locks::mutator_lock_) {
2103 PREAMBLE();
2104 shadow_frame.SetVRegLong(inst->VRegA_23x(inst_data),
2105 static_cast<uint64_t>(shadow_frame.GetVRegLong(inst->VRegB_23x())) >>
2106 (shadow_frame.GetVReg(inst->VRegC_23x()) & 0x3f));
2107 inst = inst->Next_2xx();
2108 }
2109
2110 ALWAYS_INLINE void ADD_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
2111 PREAMBLE();
2112 shadow_frame.SetVRegFloat(inst->VRegA_23x(inst_data),
2113 shadow_frame.GetVRegFloat(inst->VRegB_23x()) +
2114 shadow_frame.GetVRegFloat(inst->VRegC_23x()));
2115 inst = inst->Next_2xx();
2116 }
2117
2118 ALWAYS_INLINE void SUB_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
2119 PREAMBLE();
2120 shadow_frame.SetVRegFloat(inst->VRegA_23x(inst_data),
2121 shadow_frame.GetVRegFloat(inst->VRegB_23x()) -
2122 shadow_frame.GetVRegFloat(inst->VRegC_23x()));
2123 inst = inst->Next_2xx();
2124 }
2125
2126 ALWAYS_INLINE void MUL_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
2127 PREAMBLE();
2128 shadow_frame.SetVRegFloat(inst->VRegA_23x(inst_data),
2129 shadow_frame.GetVRegFloat(inst->VRegB_23x()) *
2130 shadow_frame.GetVRegFloat(inst->VRegC_23x()));
2131 inst = inst->Next_2xx();
2132 }
2133
2134 ALWAYS_INLINE void DIV_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
2135 PREAMBLE();
2136 shadow_frame.SetVRegFloat(inst->VRegA_23x(inst_data),
2137 shadow_frame.GetVRegFloat(inst->VRegB_23x()) /
2138 shadow_frame.GetVRegFloat(inst->VRegC_23x()));
2139 inst = inst->Next_2xx();
2140 }
2141
2142 ALWAYS_INLINE void REM_FLOAT() REQUIRES_SHARED(Locks::mutator_lock_) {
2143 PREAMBLE();
2144 shadow_frame.SetVRegFloat(inst->VRegA_23x(inst_data),
2145 fmodf(shadow_frame.GetVRegFloat(inst->VRegB_23x()),
2146 shadow_frame.GetVRegFloat(inst->VRegC_23x())));
2147 inst = inst->Next_2xx();
2148 }
2149
2150 ALWAYS_INLINE void ADD_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
2151 PREAMBLE();
2152 shadow_frame.SetVRegDouble(inst->VRegA_23x(inst_data),
2153 shadow_frame.GetVRegDouble(inst->VRegB_23x()) +
2154 shadow_frame.GetVRegDouble(inst->VRegC_23x()));
2155 inst = inst->Next_2xx();
2156 }
2157
2158 ALWAYS_INLINE void SUB_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
2159 PREAMBLE();
2160 shadow_frame.SetVRegDouble(inst->VRegA_23x(inst_data),
2161 shadow_frame.GetVRegDouble(inst->VRegB_23x()) -
2162 shadow_frame.GetVRegDouble(inst->VRegC_23x()));
2163 inst = inst->Next_2xx();
2164 }
2165
2166 ALWAYS_INLINE void MUL_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
2167 PREAMBLE();
2168 shadow_frame.SetVRegDouble(inst->VRegA_23x(inst_data),
2169 shadow_frame.GetVRegDouble(inst->VRegB_23x()) *
2170 shadow_frame.GetVRegDouble(inst->VRegC_23x()));
2171 inst = inst->Next_2xx();
2172 }
2173
2174 ALWAYS_INLINE void DIV_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
2175 PREAMBLE();
2176 shadow_frame.SetVRegDouble(inst->VRegA_23x(inst_data),
2177 shadow_frame.GetVRegDouble(inst->VRegB_23x()) /
2178 shadow_frame.GetVRegDouble(inst->VRegC_23x()));
2179 inst = inst->Next_2xx();
2180 }
2181
2182 ALWAYS_INLINE void REM_DOUBLE() REQUIRES_SHARED(Locks::mutator_lock_) {
2183 PREAMBLE();
2184 shadow_frame.SetVRegDouble(inst->VRegA_23x(inst_data),
2185 fmod(shadow_frame.GetVRegDouble(inst->VRegB_23x()),
2186 shadow_frame.GetVRegDouble(inst->VRegC_23x())));
2187 inst = inst->Next_2xx();
2188 }
2189
2190 ALWAYS_INLINE void ADD_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2191 PREAMBLE();
2192 uint4_t vregA = inst->VRegA_12x(inst_data);
2193 shadow_frame.SetVReg(vregA, SafeAdd(shadow_frame.GetVReg(vregA),
2194 shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
2195 inst = inst->Next_1xx();
2196 }
2197
2198 ALWAYS_INLINE void SUB_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2199 PREAMBLE();
2200 uint4_t vregA = inst->VRegA_12x(inst_data);
2201 shadow_frame.SetVReg(vregA,
2202 SafeSub(shadow_frame.GetVReg(vregA),
2203 shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
2204 inst = inst->Next_1xx();
2205 }
2206
2207 ALWAYS_INLINE void MUL_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2208 PREAMBLE();
2209 uint4_t vregA = inst->VRegA_12x(inst_data);
2210 shadow_frame.SetVReg(vregA,
2211 SafeMul(shadow_frame.GetVReg(vregA),
2212 shadow_frame.GetVReg(inst->VRegB_12x(inst_data))));
2213 inst = inst->Next_1xx();
2214 }
2215
2216 ALWAYS_INLINE void DIV_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2217 PREAMBLE();
2218 uint4_t vregA = inst->VRegA_12x(inst_data);
2219 bool success = DoIntDivide(shadow_frame, vregA, shadow_frame.GetVReg(vregA),
2220 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
2221 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_1xx);
2222 }
2223
2224 ALWAYS_INLINE void REM_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2225 PREAMBLE();
2226 uint4_t vregA = inst->VRegA_12x(inst_data);
2227 bool success = DoIntRemainder(shadow_frame, vregA, shadow_frame.GetVReg(vregA),
2228 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
2229 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_1xx);
2230 }
2231
2232 ALWAYS_INLINE void SHL_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2233 PREAMBLE();
2234 uint4_t vregA = inst->VRegA_12x(inst_data);
2235 shadow_frame.SetVReg(vregA,
2236 shadow_frame.GetVReg(vregA) <<
2237 (shadow_frame.GetVReg(inst->VRegB_12x(inst_data)) & 0x1f));
2238 inst = inst->Next_1xx();
2239 }
2240
2241 ALWAYS_INLINE void SHR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2242 PREAMBLE();
2243 uint4_t vregA = inst->VRegA_12x(inst_data);
2244 shadow_frame.SetVReg(vregA,
2245 shadow_frame.GetVReg(vregA) >>
2246 (shadow_frame.GetVReg(inst->VRegB_12x(inst_data)) & 0x1f));
2247 inst = inst->Next_1xx();
2248 }
2249
2250 ALWAYS_INLINE void USHR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2251 PREAMBLE();
2252 uint4_t vregA = inst->VRegA_12x(inst_data);
2253 shadow_frame.SetVReg(vregA,
2254 static_cast<uint32_t>(shadow_frame.GetVReg(vregA)) >>
2255 (shadow_frame.GetVReg(inst->VRegB_12x(inst_data)) & 0x1f));
2256 inst = inst->Next_1xx();
2257 }
2258
2259 ALWAYS_INLINE void AND_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2260 PREAMBLE();
2261 uint4_t vregA = inst->VRegA_12x(inst_data);
2262 shadow_frame.SetVReg(vregA,
2263 shadow_frame.GetVReg(vregA) &
2264 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
2265 inst = inst->Next_1xx();
2266 }
2267
2268 ALWAYS_INLINE void OR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2269 PREAMBLE();
2270 uint4_t vregA = inst->VRegA_12x(inst_data);
2271 shadow_frame.SetVReg(vregA,
2272 shadow_frame.GetVReg(vregA) |
2273 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
2274 inst = inst->Next_1xx();
2275 }
2276
2277 ALWAYS_INLINE void XOR_INT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2278 PREAMBLE();
2279 uint4_t vregA = inst->VRegA_12x(inst_data);
2280 shadow_frame.SetVReg(vregA,
2281 shadow_frame.GetVReg(vregA) ^
2282 shadow_frame.GetVReg(inst->VRegB_12x(inst_data)));
2283 inst = inst->Next_1xx();
2284 }
2285
2286 ALWAYS_INLINE void ADD_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2287 PREAMBLE();
2288 uint4_t vregA = inst->VRegA_12x(inst_data);
2289 shadow_frame.SetVRegLong(vregA,
2290 SafeAdd(shadow_frame.GetVRegLong(vregA),
2291 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data))));
2292 inst = inst->Next_1xx();
2293 }
2294
2295 ALWAYS_INLINE void SUB_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2296 PREAMBLE();
2297 uint4_t vregA = inst->VRegA_12x(inst_data);
2298 shadow_frame.SetVRegLong(vregA,
2299 SafeSub(shadow_frame.GetVRegLong(vregA),
2300 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data))));
2301 inst = inst->Next_1xx();
2302 }
2303
2304 ALWAYS_INLINE void MUL_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2305 PREAMBLE();
2306 uint4_t vregA = inst->VRegA_12x(inst_data);
2307 shadow_frame.SetVRegLong(vregA,
2308 SafeMul(shadow_frame.GetVRegLong(vregA),
2309 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data))));
2310 inst = inst->Next_1xx();
2311 }
2312
2313 ALWAYS_INLINE void DIV_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2314 PREAMBLE();
2315 uint4_t vregA = inst->VRegA_12x(inst_data);
2316 DoLongDivide(shadow_frame, vregA, shadow_frame.GetVRegLong(vregA),
2317 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
2318 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
2319 }
2320
2321 ALWAYS_INLINE void REM_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2322 PREAMBLE();
2323 uint4_t vregA = inst->VRegA_12x(inst_data);
2324 DoLongRemainder(shadow_frame, vregA, shadow_frame.GetVRegLong(vregA),
2325 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
2326 POSSIBLY_HANDLE_PENDING_EXCEPTION(self->IsExceptionPending(), Next_1xx);
2327 }
2328
2329 ALWAYS_INLINE void AND_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2330 PREAMBLE();
2331 uint4_t vregA = inst->VRegA_12x(inst_data);
2332 shadow_frame.SetVRegLong(vregA,
2333 shadow_frame.GetVRegLong(vregA) &
2334 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
2335 inst = inst->Next_1xx();
2336 }
2337
2338 ALWAYS_INLINE void OR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2339 PREAMBLE();
2340 uint4_t vregA = inst->VRegA_12x(inst_data);
2341 shadow_frame.SetVRegLong(vregA,
2342 shadow_frame.GetVRegLong(vregA) |
2343 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
2344 inst = inst->Next_1xx();
2345 }
2346
2347 ALWAYS_INLINE void XOR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2348 PREAMBLE();
2349 uint4_t vregA = inst->VRegA_12x(inst_data);
2350 shadow_frame.SetVRegLong(vregA,
2351 shadow_frame.GetVRegLong(vregA) ^
2352 shadow_frame.GetVRegLong(inst->VRegB_12x(inst_data)));
2353 inst = inst->Next_1xx();
2354 }
2355
2356 ALWAYS_INLINE void SHL_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2357 PREAMBLE();
2358 uint4_t vregA = inst->VRegA_12x(inst_data);
2359 shadow_frame.SetVRegLong(vregA,
2360 shadow_frame.GetVRegLong(vregA) <<
2361 (shadow_frame.GetVReg(inst->VRegB_12x(inst_data)) & 0x3f));
2362 inst = inst->Next_1xx();
2363 }
2364
2365 ALWAYS_INLINE void SHR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2366 PREAMBLE();
2367 uint4_t vregA = inst->VRegA_12x(inst_data);
2368 shadow_frame.SetVRegLong(vregA,
2369 shadow_frame.GetVRegLong(vregA) >>
2370 (shadow_frame.GetVReg(inst->VRegB_12x(inst_data)) & 0x3f));
2371 inst = inst->Next_1xx();
2372 }
2373
2374 ALWAYS_INLINE void USHR_LONG_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2375 PREAMBLE();
2376 uint4_t vregA = inst->VRegA_12x(inst_data);
2377 shadow_frame.SetVRegLong(vregA,
2378 static_cast<uint64_t>(shadow_frame.GetVRegLong(vregA)) >>
2379 (shadow_frame.GetVReg(inst->VRegB_12x(inst_data)) & 0x3f));
2380 inst = inst->Next_1xx();
2381 }
2382
2383 ALWAYS_INLINE void ADD_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2384 PREAMBLE();
2385 uint4_t vregA = inst->VRegA_12x(inst_data);
2386 shadow_frame.SetVRegFloat(vregA,
2387 shadow_frame.GetVRegFloat(vregA) +
2388 shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
2389 inst = inst->Next_1xx();
2390 }
2391
2392 ALWAYS_INLINE void SUB_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2393 PREAMBLE();
2394 uint4_t vregA = inst->VRegA_12x(inst_data);
2395 shadow_frame.SetVRegFloat(vregA,
2396 shadow_frame.GetVRegFloat(vregA) -
2397 shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
2398 inst = inst->Next_1xx();
2399 }
2400
2401 ALWAYS_INLINE void MUL_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2402 PREAMBLE();
2403 uint4_t vregA = inst->VRegA_12x(inst_data);
2404 shadow_frame.SetVRegFloat(vregA,
2405 shadow_frame.GetVRegFloat(vregA) *
2406 shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
2407 inst = inst->Next_1xx();
2408 }
2409
2410 ALWAYS_INLINE void DIV_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2411 PREAMBLE();
2412 uint4_t vregA = inst->VRegA_12x(inst_data);
2413 shadow_frame.SetVRegFloat(vregA,
2414 shadow_frame.GetVRegFloat(vregA) /
2415 shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data)));
2416 inst = inst->Next_1xx();
2417 }
2418
2419 ALWAYS_INLINE void REM_FLOAT_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2420 PREAMBLE();
2421 uint4_t vregA = inst->VRegA_12x(inst_data);
2422 shadow_frame.SetVRegFloat(vregA,
2423 fmodf(shadow_frame.GetVRegFloat(vregA),
2424 shadow_frame.GetVRegFloat(inst->VRegB_12x(inst_data))));
2425 inst = inst->Next_1xx();
2426 }
2427
2428 ALWAYS_INLINE void ADD_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2429 PREAMBLE();
2430 uint4_t vregA = inst->VRegA_12x(inst_data);
2431 shadow_frame.SetVRegDouble(vregA,
2432 shadow_frame.GetVRegDouble(vregA) +
2433 shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
2434 inst = inst->Next_1xx();
2435 }
2436
2437 ALWAYS_INLINE void SUB_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2438 PREAMBLE();
2439 uint4_t vregA = inst->VRegA_12x(inst_data);
2440 shadow_frame.SetVRegDouble(vregA,
2441 shadow_frame.GetVRegDouble(vregA) -
2442 shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
2443 inst = inst->Next_1xx();
2444 }
2445
2446 ALWAYS_INLINE void MUL_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2447 PREAMBLE();
2448 uint4_t vregA = inst->VRegA_12x(inst_data);
2449 shadow_frame.SetVRegDouble(vregA,
2450 shadow_frame.GetVRegDouble(vregA) *
2451 shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
2452 inst = inst->Next_1xx();
2453 }
2454
2455 ALWAYS_INLINE void DIV_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2456 PREAMBLE();
2457 uint4_t vregA = inst->VRegA_12x(inst_data);
2458 shadow_frame.SetVRegDouble(vregA,
2459 shadow_frame.GetVRegDouble(vregA) /
2460 shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data)));
2461 inst = inst->Next_1xx();
2462 }
2463
2464 ALWAYS_INLINE void REM_DOUBLE_2ADDR() REQUIRES_SHARED(Locks::mutator_lock_) {
2465 PREAMBLE();
2466 uint4_t vregA = inst->VRegA_12x(inst_data);
2467 shadow_frame.SetVRegDouble(vregA,
2468 fmod(shadow_frame.GetVRegDouble(vregA),
2469 shadow_frame.GetVRegDouble(inst->VRegB_12x(inst_data))));
2470 inst = inst->Next_1xx();
2471 }
2472
2473 ALWAYS_INLINE void ADD_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
2474 PREAMBLE();
2475 shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
2476 SafeAdd(shadow_frame.GetVReg(inst->VRegB_22s(inst_data)),
2477 inst->VRegC_22s()));
2478 inst = inst->Next_2xx();
2479 }
2480
2481 ALWAYS_INLINE void RSUB_INT() REQUIRES_SHARED(Locks::mutator_lock_) {
2482 PREAMBLE();
2483 shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
2484 SafeSub(inst->VRegC_22s(),
2485 shadow_frame.GetVReg(inst->VRegB_22s(inst_data))));
2486 inst = inst->Next_2xx();
2487 }
2488
2489 ALWAYS_INLINE void MUL_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
2490 PREAMBLE();
2491 shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
2492 SafeMul(shadow_frame.GetVReg(inst->VRegB_22s(inst_data)),
2493 inst->VRegC_22s()));
2494 inst = inst->Next_2xx();
2495 }
2496
2497 ALWAYS_INLINE void DIV_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
2498 PREAMBLE();
2499 bool success = DoIntDivide(shadow_frame, inst->VRegA_22s(inst_data),
2500 shadow_frame.GetVReg(inst->VRegB_22s(inst_data)),
2501 inst->VRegC_22s());
2502 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
2503 }
2504
2505 ALWAYS_INLINE void REM_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
2506 PREAMBLE();
2507 bool success = DoIntRemainder(shadow_frame, inst->VRegA_22s(inst_data),
2508 shadow_frame.GetVReg(inst->VRegB_22s(inst_data)),
2509 inst->VRegC_22s());
2510 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
2511 }
2512
2513 ALWAYS_INLINE void AND_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
2514 PREAMBLE();
2515 shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
2516 shadow_frame.GetVReg(inst->VRegB_22s(inst_data)) &
2517 inst->VRegC_22s());
2518 inst = inst->Next_2xx();
2519 }
2520
2521 ALWAYS_INLINE void OR_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
2522 PREAMBLE();
2523 shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
2524 shadow_frame.GetVReg(inst->VRegB_22s(inst_data)) |
2525 inst->VRegC_22s());
2526 inst = inst->Next_2xx();
2527 }
2528
2529 ALWAYS_INLINE void XOR_INT_LIT16() REQUIRES_SHARED(Locks::mutator_lock_) {
2530 PREAMBLE();
2531 shadow_frame.SetVReg(inst->VRegA_22s(inst_data),
2532 shadow_frame.GetVReg(inst->VRegB_22s(inst_data)) ^
2533 inst->VRegC_22s());
2534 inst = inst->Next_2xx();
2535 }
2536
2537 ALWAYS_INLINE void ADD_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
2538 PREAMBLE();
2539 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2540 SafeAdd(shadow_frame.GetVReg(inst->VRegB_22b()), inst->VRegC_22b()));
2541 inst = inst->Next_2xx();
2542 }
2543
2544 ALWAYS_INLINE void RSUB_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
2545 PREAMBLE();
2546 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2547 SafeSub(inst->VRegC_22b(), shadow_frame.GetVReg(inst->VRegB_22b())));
2548 inst = inst->Next_2xx();
2549 }
2550
2551 ALWAYS_INLINE void MUL_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
2552 PREAMBLE();
2553 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2554 SafeMul(shadow_frame.GetVReg(inst->VRegB_22b()), inst->VRegC_22b()));
2555 inst = inst->Next_2xx();
2556 }
2557
2558 ALWAYS_INLINE void DIV_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
2559 PREAMBLE();
2560 bool success = DoIntDivide(shadow_frame, inst->VRegA_22b(inst_data),
2561 shadow_frame.GetVReg(inst->VRegB_22b()), inst->VRegC_22b());
2562 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
2563 }
2564
2565 ALWAYS_INLINE void REM_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
2566 PREAMBLE();
2567 bool success = DoIntRemainder(shadow_frame, inst->VRegA_22b(inst_data),
2568 shadow_frame.GetVReg(inst->VRegB_22b()), inst->VRegC_22b());
2569 POSSIBLY_HANDLE_PENDING_EXCEPTION(!success, Next_2xx);
2570 }
2571
2572 ALWAYS_INLINE void AND_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
2573 PREAMBLE();
2574 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2575 shadow_frame.GetVReg(inst->VRegB_22b()) &
2576 inst->VRegC_22b());
2577 inst = inst->Next_2xx();
2578 }
2579
2580 ALWAYS_INLINE void OR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
2581 PREAMBLE();
2582 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2583 shadow_frame.GetVReg(inst->VRegB_22b()) |
2584 inst->VRegC_22b());
2585 inst = inst->Next_2xx();
2586 }
2587
2588 ALWAYS_INLINE void XOR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
2589 PREAMBLE();
2590 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2591 shadow_frame.GetVReg(inst->VRegB_22b()) ^
2592 inst->VRegC_22b());
2593 inst = inst->Next_2xx();
2594 }
2595
2596 ALWAYS_INLINE void SHL_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
2597 PREAMBLE();
2598 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2599 shadow_frame.GetVReg(inst->VRegB_22b()) <<
2600 (inst->VRegC_22b() & 0x1f));
2601 inst = inst->Next_2xx();
2602 }
2603
2604 ALWAYS_INLINE void SHR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
2605 PREAMBLE();
2606 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2607 shadow_frame.GetVReg(inst->VRegB_22b()) >>
2608 (inst->VRegC_22b() & 0x1f));
2609 inst = inst->Next_2xx();
2610 }
2611
2612 ALWAYS_INLINE void USHR_INT_LIT8() REQUIRES_SHARED(Locks::mutator_lock_) {
2613 PREAMBLE();
2614 shadow_frame.SetVReg(inst->VRegA_22b(inst_data),
2615 static_cast<uint32_t>(shadow_frame.GetVReg(inst->VRegB_22b())) >>
2616 (inst->VRegC_22b() & 0x1f));
2617 inst = inst->Next_2xx();
2618 }
2619
2620 ALWAYS_INLINE void UNUSED_3E() REQUIRES_SHARED(Locks::mutator_lock_) {
2621 UnexpectedOpcode(inst, shadow_frame);
2622 }
2623
2624 ALWAYS_INLINE void UNUSED_3F() REQUIRES_SHARED(Locks::mutator_lock_) {
2625 UnexpectedOpcode(inst, shadow_frame);
2626 }
2627
2628 ALWAYS_INLINE void UNUSED_40() REQUIRES_SHARED(Locks::mutator_lock_) {
2629 UnexpectedOpcode(inst, shadow_frame);
2630 }
2631
2632 ALWAYS_INLINE void UNUSED_41() REQUIRES_SHARED(Locks::mutator_lock_) {
2633 UnexpectedOpcode(inst, shadow_frame);
2634 }
2635
2636 ALWAYS_INLINE void UNUSED_42() REQUIRES_SHARED(Locks::mutator_lock_) {
2637 UnexpectedOpcode(inst, shadow_frame);
2638 }
2639
2640 ALWAYS_INLINE void UNUSED_43() REQUIRES_SHARED(Locks::mutator_lock_) {
2641 UnexpectedOpcode(inst, shadow_frame);
2642 }
2643
2644 ALWAYS_INLINE void UNUSED_79() REQUIRES_SHARED(Locks::mutator_lock_) {
2645 UnexpectedOpcode(inst, shadow_frame);
2646 }
2647
2648 ALWAYS_INLINE void UNUSED_7A() REQUIRES_SHARED(Locks::mutator_lock_) {
2649 UnexpectedOpcode(inst, shadow_frame);
2650 }
2651
2652 ALWAYS_INLINE void UNUSED_F3() REQUIRES_SHARED(Locks::mutator_lock_) {
2653 UnexpectedOpcode(inst, shadow_frame);
2654 }
2655
2656 ALWAYS_INLINE void UNUSED_F4() REQUIRES_SHARED(Locks::mutator_lock_) {
2657 UnexpectedOpcode(inst, shadow_frame);
2658 }
2659
2660 ALWAYS_INLINE void UNUSED_F5() REQUIRES_SHARED(Locks::mutator_lock_) {
2661 UnexpectedOpcode(inst, shadow_frame);
2662 }
2663
2664 ALWAYS_INLINE void UNUSED_F6() REQUIRES_SHARED(Locks::mutator_lock_) {
2665 UnexpectedOpcode(inst, shadow_frame);
2666 }
2667
2668 ALWAYS_INLINE void UNUSED_F7() REQUIRES_SHARED(Locks::mutator_lock_) {
2669 UnexpectedOpcode(inst, shadow_frame);
2670 }
2671
2672 ALWAYS_INLINE void UNUSED_F8() REQUIRES_SHARED(Locks::mutator_lock_) {
2673 UnexpectedOpcode(inst, shadow_frame);
2674 }
2675
2676 ALWAYS_INLINE void UNUSED_F9() REQUIRES_SHARED(Locks::mutator_lock_) {
2677 UnexpectedOpcode(inst, shadow_frame);
2678 }
2679
2680 ALWAYS_INLINE InstructionHandler(SwitchImplContext* ctx,
2681 const instrumentation::Instrumentation* instrumentation,
2682 Thread* self,
2683 ShadowFrame& shadow_frame,
2684 uint16_t dex_pc,
2685 const Instruction*& inst,
2686 uint16_t inst_data,
2687 bool& exit_interpreter_loop)
2688 : ctx(ctx),
2689 instrumentation(instrumentation),
2690 self(self),
2691 shadow_frame(shadow_frame),
2692 dex_pc(dex_pc),
2693 inst(inst),
2694 inst_data(inst_data),
2695 exit_interpreter_loop(exit_interpreter_loop) {
2696 }
2697
2698 private:
2699 static constexpr bool do_assignability_check = do_access_check;
2700
2701 const CodeItemDataAccessor& Accessor() { return ctx->accessor; }
2702 const uint16_t* Insns() { return ctx->accessor.Insns(); }
2703 JValue* ResultRegister() { return &ctx->result_register; }
2704
2705 SwitchImplContext* const ctx;
2706 const instrumentation::Instrumentation* const instrumentation;
2707 Thread* const self;
2708 ShadowFrame& shadow_frame;
2709 uint32_t const dex_pc;
2710 const Instruction*& inst;
2711 uint16_t const inst_data;
2712 bool& exit_interpreter_loop;
2713};
2714
2715#undef HANDLE_BACKWARD_BRANCH
2716#undef HANDLE_ASYNC_EXCEPTION
2717#undef HOTNESS_UPDATE
2718#undef BRANCH_INSTRUMENTATION
2719#undef PREAMBLE
2720#undef PREAMBLE_SAVE
2721#undef HANDLE_MONITOR_CHECKS
2722#undef POSSIBLY_HANDLE_PENDING_EXCEPTION
2723#undef POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE
2724#undef POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_POLYMORPHIC
2725#undef POSSIBLY_HANDLE_PENDING_EXCEPTION_ON_INVOKE_IMPL
2726#undef HANDLE_PENDING_EXCEPTION
2727#undef HANDLE_PENDING_EXCEPTION_WITH_INSTRUMENTATION
2728#undef CHECK_FORCE_RETURN
2729
Alex Light6f22e062018-10-05 15:05:12 -07002730// TODO On ASAN builds this function gets a huge stack frame. Since normally we run in the mterp
2731// this shouldn't cause any problems for stack overflow detection. Remove this once b/117341496 is
2732// fixed.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +01002733template<bool do_access_check, bool transaction_active>
Alex Light6f22e062018-10-05 15:05:12 -07002734ATTRIBUTE_NO_SANITIZE_ADDRESS void ExecuteSwitchImplCpp(SwitchImplContext* ctx) {
David Srbecky946bb092018-03-09 17:23:01 +00002735 Thread* self = ctx->self;
2736 const CodeItemDataAccessor& accessor = ctx->accessor;
2737 ShadowFrame& shadow_frame = ctx->shadow_frame;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002738 if (UNLIKELY(!shadow_frame.HasReferenceArray())) {
2739 LOG(FATAL) << "Invalid shadow frame for interpreter use";
David Srbecky946bb092018-03-09 17:23:01 +00002740 ctx->result = JValue();
2741 return;
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002742 }
2743 self->VerifyStack();
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002744
2745 uint32_t dex_pc = shadow_frame.GetDexPC();
Mathieu Chartier2cebb242015-04-21 16:50:40 -07002746 const auto* const instrumentation = Runtime::Current()->GetInstrumentation();
Mathieu Chartier808c7a52017-12-15 11:19:33 -08002747 const uint16_t* const insns = accessor.Insns();
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002748 const Instruction* inst = Instruction::At(insns + dex_pc);
Sebastien Hertz3b588e02013-09-11 14:33:18 +02002749 uint16_t inst_data;
Igor Murashkin6918bf12015-09-27 19:19:06 -07002750
Alex Light0aa7a5a2018-10-10 15:58:14 +00002751 DCHECK(!shadow_frame.GetForceRetryInstruction())
2752 << "Entered interpreter from invoke without retry instruction being handled!";
2753
David Srbecky6da82472018-10-23 14:03:08 +01002754 bool const interpret_one_instruction = ctx->interpret_one_instruction;
2755 while (true) {
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002756 dex_pc = inst->GetDexPc(insns);
2757 shadow_frame.SetDexPC(dex_pc);
Ian Rogerse94652f2014-12-02 11:13:19 -08002758 TraceExecution(shadow_frame, inst, dex_pc);
Sebastien Hertz3b588e02013-09-11 14:33:18 +02002759 inst_data = inst->Fetch16(0);
2760 switch (inst->Opcode(inst_data)) {
David Srbecky6da82472018-10-23 14:03:08 +01002761#define OPCODE_CASE(OPCODE, OPCODE_NAME, pname, f, i, a, e, v) \
2762 case OPCODE: { \
2763 bool exit_loop = false; \
2764 InstructionHandler<do_access_check, transaction_active> handler( \
2765 ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, exit_loop); \
2766 /* TODO: Call PREAMBLE here, instead of explicitly in each handler */ \
2767 handler.OPCODE_NAME(); \
2768 /* TODO: Advance 'inst' here, instead of explicitly in each handler */ \
2769 if (UNLIKELY(exit_loop)) { \
2770 return; \
2771 } \
2772 break; \
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002773 }
David Srbecky6da82472018-10-23 14:03:08 +01002774DEX_INSTRUCTION_LIST(OPCODE_CASE)
2775#undef OPCODE_CASE
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002776 }
David Srbecky6da82472018-10-23 14:03:08 +01002777 if (UNLIKELY(interpret_one_instruction)) {
2778 // Record where we stopped.
2779 shadow_frame.SetDexPC(inst->GetDexPc(insns));
2780 ctx->result = ctx->result_register;
2781 return;
2782 }
2783 }
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002784} // NOLINT(readability/fn_size)
2785
Sebastien Hertz8ece0502013-08-07 11:26:41 +02002786} // namespace interpreter
2787} // namespace art
David Srbecky2ee09ff2018-10-24 13:24:22 +01002788
2789#endif // ART_RUNTIME_INTERPRETER_INTERPRETER_SWITCH_IMPL_INL_H_