1 /*
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
17 #ifndef ART_RUNTIME_INTERPRETER_INTERPRETER_SWITCH_IMPL_INL_H_
18 #define ART_RUNTIME_INTERPRETER_INTERPRETER_SWITCH_IMPL_INL_H_
19
20 #include "interpreter_switch_impl.h"
21
22 #include "base/enums.h"
23 #include "base/globals.h"
24 #include "base/memory_tool.h"
25 #include "base/quasi_atomic.h"
26 #include "dex/dex_file_types.h"
27 #include "dex/dex_instruction_list.h"
28 #include "experimental_flags.h"
29 #include "handle_scope.h"
30 #include "interpreter_common.h"
31 #include "interpreter/shadow_frame.h"
32 #include "jit/jit-inl.h"
33 #include "jvalue-inl.h"
34 #include "mirror/string-alloc-inl.h"
35 #include "mirror/throwable.h"
36 #include "monitor.h"
37 #include "nth_caller_visitor.h"
38 #include "safe_math.h"
39 #include "shadow_frame-inl.h"
40 #include "thread.h"
41 #include "verifier/method_verifier.h"
42
43 namespace art {
44 namespace interpreter {
45
46 // Short-lived helper class which executes single DEX bytecode. It is inlined by compiler.
47 // Any relevant execution information is stored in the fields - it should be kept to minimum.
48 // All instance functions must be inlined so that the fields can be stored in registers.
49 //
50 // The function names must match the names from dex_instruction_list.h and have no arguments.
51 // Return value: The handlers must return false if the instruction throws or returns (exits).
52 //
53 template<bool do_access_check, bool transaction_active, Instruction::Format kFormat>
54 class InstructionHandler {
55 public:
56 #define HANDLER_ATTRIBUTES ALWAYS_INLINE FLATTEN WARN_UNUSED REQUIRES_SHARED(Locks::mutator_lock_)
57
CheckForceReturn()58 HANDLER_ATTRIBUTES bool CheckForceReturn() {
59 if (PerformNonStandardReturn<kMonitorState>(self,
60 shadow_frame,
61 ctx->result,
62 instrumentation,
63 Accessor().InsSize(),
64 inst->GetDexPc(Insns()))) {
65 exit_interpreter_loop = true;
66 return false;
67 }
68 return true;
69 }
70
HandlePendingException()71 HANDLER_ATTRIBUTES bool HandlePendingException() {
72 DCHECK(self->IsExceptionPending());
73 self->AllowThreadSuspension();
74 if (!CheckForceReturn()) {
75 return false;
76 }
77 bool skip_event = shadow_frame.GetSkipNextExceptionEvent();
78 shadow_frame.SetSkipNextExceptionEvent(false);
79 if (!MoveToExceptionHandler(self, shadow_frame, skip_event ? nullptr : instrumentation)) {
80 /* Structured locking is to be enforced for abnormal termination, too. */
81 DoMonitorCheckOnExit<do_assignability_check>(self, &shadow_frame);
82 ctx->result = JValue(); /* Handled in caller. */
83 exit_interpreter_loop = true;
84 return false; // Return to caller.
85 }
86 if (!CheckForceReturn()) {
87 return false;
88 }
89 int32_t displacement =
90 static_cast<int32_t>(shadow_frame.GetDexPC()) - static_cast<int32_t>(dex_pc);
91 SetNextInstruction(inst->RelativeAt(displacement));
92 return true;
93 }
94
PossiblyHandlePendingExceptionOnInvoke(bool is_exception_pending)95 HANDLER_ATTRIBUTES bool PossiblyHandlePendingExceptionOnInvoke(bool is_exception_pending) {
96 if (UNLIKELY(shadow_frame.GetForceRetryInstruction())) {
97 /* Don't need to do anything except clear the flag and exception. We leave the */
98 /* instruction the same so it will be re-executed on the next go-around. */
99 DCHECK(inst->IsInvoke());
100 shadow_frame.SetForceRetryInstruction(false);
101 if (UNLIKELY(is_exception_pending)) {
102 DCHECK(self->IsExceptionPending());
103 if (kIsDebugBuild) {
104 LOG(WARNING) << "Suppressing exception for instruction-retry: "
105 << self->GetException()->Dump();
106 }
107 self->ClearException();
108 }
109 SetNextInstruction(inst);
110 } else if (UNLIKELY(is_exception_pending)) {
111 /* Should have succeeded. */
112 DCHECK(!shadow_frame.GetForceRetryInstruction());
113 return false; // Pending exception.
114 }
115 return true;
116 }
117
HandleMonitorChecks()118 HANDLER_ATTRIBUTES bool HandleMonitorChecks() {
119 if (!DoMonitorCheckOnExit<do_assignability_check>(self, &shadow_frame)) {
120 return false; // Pending exception.
121 }
122 return true;
123 }
124
125 // Code to run before each dex instruction.
Preamble()126 HANDLER_ATTRIBUTES bool Preamble() {
127 /* We need to put this before & after the instrumentation to avoid having to put in a */
128 /* post-script macro. */
129 if (!CheckForceReturn()) {
130 return false;
131 }
132 if (UNLIKELY(instrumentation->HasDexPcListeners())) {
133 uint8_t opcode = inst->Opcode(inst_data);
134 bool is_move_result_object = (opcode == Instruction::MOVE_RESULT_OBJECT);
135 JValue* save_ref = is_move_result_object ? &ctx->result_register : nullptr;
136 if (UNLIKELY(!DoDexPcMoveEvent(self,
137 Accessor(),
138 shadow_frame,
139 dex_pc,
140 instrumentation,
141 save_ref))) {
142 DCHECK(self->IsExceptionPending());
143 // Do not raise exception event if it is caused by other instrumentation event.
144 shadow_frame.SetSkipNextExceptionEvent(true);
145 return false; // Pending exception.
146 }
147 if (!CheckForceReturn()) {
148 return false;
149 }
150 }
151 return true;
152 }
153
BranchInstrumentation(int32_t offset)154 HANDLER_ATTRIBUTES bool BranchInstrumentation(int32_t offset) {
155 if (UNLIKELY(instrumentation->HasBranchListeners())) {
156 instrumentation->Branch(self, shadow_frame.GetMethod(), dex_pc, offset);
157 }
158 JValue result;
159 if (jit::Jit::MaybeDoOnStackReplacement(self,
160 shadow_frame.GetMethod(),
161 dex_pc,
162 offset,
163 &result)) {
164 ctx->result = result;
165 exit_interpreter_loop = true;
166 return false;
167 }
168 return true;
169 }
170
HotnessUpdate()171 ALWAYS_INLINE void HotnessUpdate()
172 REQUIRES_SHARED(Locks::mutator_lock_) {
173 jit::Jit* jit = Runtime::Current()->GetJit();
174 if (jit != nullptr) {
175 jit->AddSamples(self, shadow_frame.GetMethod(), 1, /*with_backedges=*/ true);
176 }
177 }
178
HandleAsyncException()179 HANDLER_ATTRIBUTES bool HandleAsyncException() {
180 if (UNLIKELY(self->ObserveAsyncException())) {
181 return false; // Pending exception.
182 }
183 return true;
184 }
185
HandleBackwardBranch(int32_t offset)186 ALWAYS_INLINE void HandleBackwardBranch(int32_t offset)
187 REQUIRES_SHARED(Locks::mutator_lock_) {
188 if (IsBackwardBranch(offset)) {
189 HotnessUpdate();
190 /* Record new dex pc early to have consistent suspend point at loop header. */
191 shadow_frame.SetDexPC(next->GetDexPc(Insns()));
192 self->AllowThreadSuspension();
193 }
194 }
195
196 // Unlike most other events the DexPcMovedEvent can be sent when there is a pending exception (if
197 // the next instruction is MOVE_EXCEPTION). This means it needs to be handled carefully to be able
198 // to detect exceptions thrown by the DexPcMovedEvent itself. These exceptions could be thrown by
199 // jvmti-agents while handling breakpoint or single step events. We had to move this into its own
200 // function because it was making ExecuteSwitchImpl have too large a stack.
DoDexPcMoveEvent(Thread * self,const CodeItemDataAccessor & accessor,const ShadowFrame & shadow_frame,uint32_t dex_pc,const instrumentation::Instrumentation * instrumentation,JValue * save_ref)201 NO_INLINE static bool DoDexPcMoveEvent(Thread* self,
202 const CodeItemDataAccessor& accessor,
203 const ShadowFrame& shadow_frame,
204 uint32_t dex_pc,
205 const instrumentation::Instrumentation* instrumentation,
206 JValue* save_ref)
207 REQUIRES_SHARED(Locks::mutator_lock_) {
208 DCHECK(instrumentation->HasDexPcListeners());
209 StackHandleScope<2> hs(self);
210 Handle<mirror::Throwable> thr(hs.NewHandle(self->GetException()));
211 mirror::Object* null_obj = nullptr;
212 HandleWrapper<mirror::Object> h(
213 hs.NewHandleWrapper(LIKELY(save_ref == nullptr) ? &null_obj : save_ref->GetGCRoot()));
214 self->ClearException();
215 instrumentation->DexPcMovedEvent(self,
216 shadow_frame.GetThisObject(accessor.InsSize()),
217 shadow_frame.GetMethod(),
218 dex_pc);
219 if (UNLIKELY(self->IsExceptionPending())) {
220 // We got a new exception in the dex-pc-moved event.
221 // We just let this exception replace the old one.
222 // TODO It would be good to add the old exception to the
223 // suppressed exceptions of the new one if possible.
224 return false; // Pending exception.
225 } else {
226 if (UNLIKELY(!thr.IsNull())) {
227 self->SetException(thr.Get());
228 }
229 return true;
230 }
231 }
232
HandleReturn(JValue result)233 HANDLER_ATTRIBUTES bool HandleReturn(JValue result) {
234 self->AllowThreadSuspension();
235 if (!HandleMonitorChecks()) {
236 return false;
237 }
238 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
239 !SendMethodExitEvents(self,
240 instrumentation,
241 shadow_frame,
242 shadow_frame.GetThisObject(Accessor().InsSize()),
243 shadow_frame.GetMethod(),
244 inst->GetDexPc(Insns()),
245 result))) {
246 DCHECK(self->IsExceptionPending());
247 // Do not raise exception event if it is caused by other instrumentation event.
248 shadow_frame.SetSkipNextExceptionEvent(true);
249 return false; // Pending exception.
250 }
251 ctx->result = result;
252 exit_interpreter_loop = true;
253 return false;
254 }
255
HandleGoto(int32_t offset)256 HANDLER_ATTRIBUTES bool HandleGoto(int32_t offset) {
257 if (!HandleAsyncException()) {
258 return false;
259 }
260 if (!BranchInstrumentation(offset)) {
261 return false;
262 }
263 SetNextInstruction(inst->RelativeAt(offset));
264 HandleBackwardBranch(offset);
265 return true;
266 }
267
268 #pragma clang diagnostic push
269 #pragma clang diagnostic ignored "-Wfloat-equal"
270
271 template<typename T>
HandleCmpl(T val1,T val2)272 HANDLER_ATTRIBUTES bool HandleCmpl(T val1, T val2) {
273 int32_t result;
274 if (val1 > val2) {
275 result = 1;
276 } else if (val1 == val2) {
277 result = 0;
278 } else {
279 result = -1;
280 }
281 SetVReg(A(), result);
282 return true;
283 }
284
285 // Returns the same result as the function above. It only differs for NaN values.
286 template<typename T>
HandleCmpg(T val1,T val2)287 HANDLER_ATTRIBUTES bool HandleCmpg(T val1, T val2) {
288 int32_t result;
289 if (val1 < val2) {
290 result = -1;
291 } else if (val1 == val2) {
292 result = 0;
293 } else {
294 result = 1;
295 }
296 SetVReg(A(), result);
297 return true;
298 }
299
300 #pragma clang diagnostic pop
301
HandleIf(bool cond,int32_t offset)302 HANDLER_ATTRIBUTES bool HandleIf(bool cond, int32_t offset) {
303 if (cond) {
304 if (!BranchInstrumentation(offset)) {
305 return false;
306 }
307 SetNextInstruction(inst->RelativeAt(offset));
308 HandleBackwardBranch(offset);
309 } else {
310 if (!BranchInstrumentation(2)) {
311 return false;
312 }
313 }
314 return true;
315 }
316
317 template<typename ArrayType, typename SetVRegFn>
HandleAGet(SetVRegFn setVReg)318 HANDLER_ATTRIBUTES bool HandleAGet(SetVRegFn setVReg) {
319 ObjPtr<mirror::Object> a = GetVRegReference(B());
320 if (UNLIKELY(a == nullptr)) {
321 ThrowNullPointerExceptionFromInterpreter();
322 return false; // Pending exception.
323 }
324 int32_t index = GetVReg(C());
325 ObjPtr<ArrayType> array = ObjPtr<ArrayType>::DownCast(a);
326 if (UNLIKELY(!array->CheckIsValidIndex(index))) {
327 return false; // Pending exception.
328 } else {
329 (this->*setVReg)(A(), array->GetWithoutChecks(index));
330 }
331 return true;
332 }
333
334 template<typename ArrayType, typename T>
HandleAPut(T value)335 HANDLER_ATTRIBUTES bool HandleAPut(T value) {
336 ObjPtr<mirror::Object> a = GetVRegReference(B());
337 if (UNLIKELY(a == nullptr)) {
338 ThrowNullPointerExceptionFromInterpreter();
339 return false; // Pending exception.
340 }
341 int32_t index = GetVReg(C());
342 ObjPtr<ArrayType> array = ObjPtr<ArrayType>::DownCast(a);
343 if (UNLIKELY(!array->CheckIsValidIndex(index))) {
344 return false; // Pending exception.
345 } else {
346 if (transaction_active && !CheckWriteConstraint(self, array)) {
347 return false;
348 }
349 array->template SetWithoutChecks<transaction_active>(index, value);
350 }
351 return true;
352 }
353
354 template<FindFieldType find_type, Primitive::Type field_type>
HandleGet()355 HANDLER_ATTRIBUTES bool HandleGet() {
356 return DoFieldGet<find_type, field_type, do_access_check, transaction_active>(
357 self, shadow_frame, inst, inst_data);
358 }
359
360 template<Primitive::Type field_type>
HandleGetQuick()361 HANDLER_ATTRIBUTES bool HandleGetQuick() {
362 return DoIGetQuick<field_type>(shadow_frame, inst, inst_data);
363 }
364
365 template<FindFieldType find_type, Primitive::Type field_type>
HandlePut()366 HANDLER_ATTRIBUTES bool HandlePut() {
367 return DoFieldPut<find_type, field_type, do_access_check, transaction_active>(
368 self, shadow_frame, inst, inst_data);
369 }
370
371 template<Primitive::Type field_type>
HandlePutQuick()372 HANDLER_ATTRIBUTES bool HandlePutQuick() {
373 return DoIPutQuick<field_type, transaction_active>(
374 shadow_frame, inst, inst_data);
375 }
376
377 template<InvokeType type, bool is_range, bool is_quick = false>
HandleInvoke()378 HANDLER_ATTRIBUTES bool HandleInvoke() {
379 bool success = DoInvoke<type, is_range, do_access_check, /*is_mterp=*/ false, is_quick>(
380 self, shadow_frame, inst, inst_data, ResultRegister());
381 return PossiblyHandlePendingExceptionOnInvoke(!success);
382 }
383
HandleUnused()384 HANDLER_ATTRIBUTES bool HandleUnused() {
385 UnexpectedOpcode(inst, shadow_frame);
386 return true;
387 }
388
NOP()389 HANDLER_ATTRIBUTES bool NOP() {
390 return true;
391 }
392
MOVE()393 HANDLER_ATTRIBUTES bool MOVE() {
394 SetVReg(A(), GetVReg(B()));
395 return true;
396 }
397
MOVE_FROM16()398 HANDLER_ATTRIBUTES bool MOVE_FROM16() {
399 SetVReg(A(), GetVReg(B()));
400 return true;
401 }
402
MOVE_16()403 HANDLER_ATTRIBUTES bool MOVE_16() {
404 SetVReg(A(), GetVReg(B()));
405 return true;
406 }
407
MOVE_WIDE()408 HANDLER_ATTRIBUTES bool MOVE_WIDE() {
409 SetVRegLong(A(), GetVRegLong(B()));
410 return true;
411 }
412
MOVE_WIDE_FROM16()413 HANDLER_ATTRIBUTES bool MOVE_WIDE_FROM16() {
414 SetVRegLong(A(), GetVRegLong(B()));
415 return true;
416 }
417
MOVE_WIDE_16()418 HANDLER_ATTRIBUTES bool MOVE_WIDE_16() {
419 SetVRegLong(A(), GetVRegLong(B()));
420 return true;
421 }
422
MOVE_OBJECT()423 HANDLER_ATTRIBUTES bool MOVE_OBJECT() {
424 SetVRegReference(A(), GetVRegReference(B()));
425 return true;
426 }
427
MOVE_OBJECT_FROM16()428 HANDLER_ATTRIBUTES bool MOVE_OBJECT_FROM16() {
429 SetVRegReference(A(), GetVRegReference(B()));
430 return true;
431 }
432
MOVE_OBJECT_16()433 HANDLER_ATTRIBUTES bool MOVE_OBJECT_16() {
434 SetVRegReference(A(), GetVRegReference(B()));
435 return true;
436 }
437
MOVE_RESULT()438 HANDLER_ATTRIBUTES bool MOVE_RESULT() {
439 SetVReg(A(), ResultRegister()->GetI());
440 return true;
441 }
442
MOVE_RESULT_WIDE()443 HANDLER_ATTRIBUTES bool MOVE_RESULT_WIDE() {
444 SetVRegLong(A(), ResultRegister()->GetJ());
445 return true;
446 }
447
MOVE_RESULT_OBJECT()448 HANDLER_ATTRIBUTES bool MOVE_RESULT_OBJECT() {
449 SetVRegReference(A(), ResultRegister()->GetL());
450 return true;
451 }
452
MOVE_EXCEPTION()453 HANDLER_ATTRIBUTES bool MOVE_EXCEPTION() {
454 ObjPtr<mirror::Throwable> exception = self->GetException();
455 DCHECK(exception != nullptr) << "No pending exception on MOVE_EXCEPTION instruction";
456 SetVRegReference(A(), exception);
457 self->ClearException();
458 return true;
459 }
460
RETURN_VOID_NO_BARRIER()461 HANDLER_ATTRIBUTES bool RETURN_VOID_NO_BARRIER() {
462 JValue result;
463 return HandleReturn(result);
464 }
465
RETURN_VOID()466 HANDLER_ATTRIBUTES bool RETURN_VOID() {
467 QuasiAtomic::ThreadFenceForConstructor();
468 JValue result;
469 return HandleReturn(result);
470 }
471
RETURN()472 HANDLER_ATTRIBUTES bool RETURN() {
473 JValue result;
474 result.SetJ(0);
475 result.SetI(GetVReg(A()));
476 return HandleReturn(result);
477 }
478
RETURN_WIDE()479 HANDLER_ATTRIBUTES bool RETURN_WIDE() {
480 JValue result;
481 result.SetJ(GetVRegLong(A()));
482 return HandleReturn(result);
483 }
484
RETURN_OBJECT()485 HANDLER_ATTRIBUTES bool RETURN_OBJECT() {
486 JValue result;
487 self->AllowThreadSuspension();
488 if (!HandleMonitorChecks()) {
489 return false;
490 }
491 const size_t ref_idx = A();
492 ObjPtr<mirror::Object> obj_result = GetVRegReference(ref_idx);
493 if (do_assignability_check && obj_result != nullptr) {
494 ObjPtr<mirror::Class> return_type = shadow_frame.GetMethod()->ResolveReturnType();
495 // Re-load since it might have moved.
496 obj_result = GetVRegReference(ref_idx);
497 if (return_type == nullptr) {
498 // Return the pending exception.
499 return false; // Pending exception.
500 }
501 if (!obj_result->VerifierInstanceOf(return_type)) {
502 CHECK_LE(Runtime::Current()->GetTargetSdkVersion(), 29u);
503 // This should never happen.
504 std::string temp1, temp2;
505 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
506 "Returning '%s' that is not instance of return type '%s'",
507 obj_result->GetClass()->GetDescriptor(&temp1),
508 return_type->GetDescriptor(&temp2));
509 return false; // Pending exception.
510 }
511 }
512 StackHandleScope<1> hs(self);
513 MutableHandle<mirror::Object> h_result(hs.NewHandle(obj_result));
514 result.SetL(obj_result);
515 if (UNLIKELY(NeedsMethodExitEvent(instrumentation) &&
516 !SendMethodExitEvents(self,
517 instrumentation,
518 shadow_frame,
519 shadow_frame.GetThisObject(Accessor().InsSize()),
520 shadow_frame.GetMethod(),
521 inst->GetDexPc(Insns()),
522 h_result))) {
523 DCHECK(self->IsExceptionPending());
524 // Do not raise exception event if it is caused by other instrumentation event.
525 shadow_frame.SetSkipNextExceptionEvent(true);
526 return false; // Pending exception.
527 }
528 // Re-load since it might have moved or been replaced during the MethodExitEvent.
529 result.SetL(h_result.Get());
530 ctx->result = result;
531 exit_interpreter_loop = true;
532 return false;
533 }
534
CONST_4()535 HANDLER_ATTRIBUTES bool CONST_4() {
536 uint4_t dst = inst->VRegA_11n(inst_data);
537 int4_t val = inst->VRegB_11n(inst_data);
538 SetVReg(dst, val);
539 if (val == 0) {
540 SetVRegReference(dst, nullptr);
541 }
542 return true;
543 }
544
CONST_16()545 HANDLER_ATTRIBUTES bool CONST_16() {
546 uint8_t dst = A();
547 int16_t val = B();
548 SetVReg(dst, val);
549 if (val == 0) {
550 SetVRegReference(dst, nullptr);
551 }
552 return true;
553 }
554
CONST()555 HANDLER_ATTRIBUTES bool CONST() {
556 uint8_t dst = A();
557 int32_t val = B();
558 SetVReg(dst, val);
559 if (val == 0) {
560 SetVRegReference(dst, nullptr);
561 }
562 return true;
563 }
564
CONST_HIGH16()565 HANDLER_ATTRIBUTES bool CONST_HIGH16() {
566 uint8_t dst = A();
567 int32_t val = static_cast<int32_t>(B() << 16);
568 SetVReg(dst, val);
569 if (val == 0) {
570 SetVRegReference(dst, nullptr);
571 }
572 return true;
573 }
574
CONST_WIDE_16()575 HANDLER_ATTRIBUTES bool CONST_WIDE_16() {
576 SetVRegLong(A(), B());
577 return true;
578 }
579
CONST_WIDE_32()580 HANDLER_ATTRIBUTES bool CONST_WIDE_32() {
581 SetVRegLong(A(), B());
582 return true;
583 }
584
CONST_WIDE()585 HANDLER_ATTRIBUTES bool CONST_WIDE() {
586 SetVRegLong(A(), inst->WideVRegB());
587 return true;
588 }
589
CONST_WIDE_HIGH16()590 HANDLER_ATTRIBUTES bool CONST_WIDE_HIGH16() {
591 SetVRegLong(A(), static_cast<uint64_t>(B()) << 48);
592 return true;
593 }
594
CONST_STRING()595 HANDLER_ATTRIBUTES bool CONST_STRING() {
596 ObjPtr<mirror::String> s = ResolveString(self, shadow_frame, dex::StringIndex(B()));
597 if (UNLIKELY(s == nullptr)) {
598 return false; // Pending exception.
599 } else {
600 SetVRegReference(A(), s);
601 }
602 return true;
603 }
604
CONST_STRING_JUMBO()605 HANDLER_ATTRIBUTES bool CONST_STRING_JUMBO() {
606 ObjPtr<mirror::String> s = ResolveString(self, shadow_frame, dex::StringIndex(B()));
607 if (UNLIKELY(s == nullptr)) {
608 return false; // Pending exception.
609 } else {
610 SetVRegReference(A(), s);
611 }
612 return true;
613 }
614
CONST_CLASS()615 HANDLER_ATTRIBUTES bool CONST_CLASS() {
616 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(B()),
617 shadow_frame.GetMethod(),
618 self,
619 false,
620 do_access_check);
621 if (UNLIKELY(c == nullptr)) {
622 return false; // Pending exception.
623 } else {
624 SetVRegReference(A(), c);
625 }
626 return true;
627 }
628
CONST_METHOD_HANDLE()629 HANDLER_ATTRIBUTES bool CONST_METHOD_HANDLE() {
630 ClassLinker* cl = Runtime::Current()->GetClassLinker();
631 ObjPtr<mirror::MethodHandle> mh = cl->ResolveMethodHandle(self,
632 B(),
633 shadow_frame.GetMethod());
634 if (UNLIKELY(mh == nullptr)) {
635 return false; // Pending exception.
636 } else {
637 SetVRegReference(A(), mh);
638 }
639 return true;
640 }
641
CONST_METHOD_TYPE()642 HANDLER_ATTRIBUTES bool CONST_METHOD_TYPE() {
643 ClassLinker* cl = Runtime::Current()->GetClassLinker();
644 ObjPtr<mirror::MethodType> mt = cl->ResolveMethodType(self,
645 dex::ProtoIndex(B()),
646 shadow_frame.GetMethod());
647 if (UNLIKELY(mt == nullptr)) {
648 return false; // Pending exception.
649 } else {
650 SetVRegReference(A(), mt);
651 }
652 return true;
653 }
654
MONITOR_ENTER()655 HANDLER_ATTRIBUTES bool MONITOR_ENTER() {
656 if (!HandleAsyncException()) {
657 return false;
658 }
659 ObjPtr<mirror::Object> obj = GetVRegReference(A());
660 if (UNLIKELY(obj == nullptr)) {
661 ThrowNullPointerExceptionFromInterpreter();
662 return false; // Pending exception.
663 } else {
664 DoMonitorEnter<do_assignability_check>(self, &shadow_frame, obj);
665 return !self->IsExceptionPending();
666 }
667 }
668
MONITOR_EXIT()669 HANDLER_ATTRIBUTES bool MONITOR_EXIT() {
670 if (!HandleAsyncException()) {
671 return false;
672 }
673 ObjPtr<mirror::Object> obj = GetVRegReference(A());
674 if (UNLIKELY(obj == nullptr)) {
675 ThrowNullPointerExceptionFromInterpreter();
676 return false; // Pending exception.
677 } else {
678 DoMonitorExit<do_assignability_check>(self, &shadow_frame, obj);
679 return !self->IsExceptionPending();
680 }
681 }
682
CHECK_CAST()683 HANDLER_ATTRIBUTES bool CHECK_CAST() {
684 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(B()),
685 shadow_frame.GetMethod(),
686 self,
687 false,
688 do_access_check);
689 if (UNLIKELY(c == nullptr)) {
690 return false; // Pending exception.
691 } else {
692 ObjPtr<mirror::Object> obj = GetVRegReference(A());
693 if (UNLIKELY(obj != nullptr && !obj->InstanceOf(c))) {
694 ThrowClassCastException(c, obj->GetClass());
695 return false; // Pending exception.
696 }
697 }
698 return true;
699 }
700
INSTANCE_OF()701 HANDLER_ATTRIBUTES bool INSTANCE_OF() {
702 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(C()),
703 shadow_frame.GetMethod(),
704 self,
705 false,
706 do_access_check);
707 if (UNLIKELY(c == nullptr)) {
708 return false; // Pending exception.
709 } else {
710 ObjPtr<mirror::Object> obj = GetVRegReference(B());
711 SetVReg(A(), (obj != nullptr && obj->InstanceOf(c)) ? 1 : 0);
712 }
713 return true;
714 }
715
ARRAY_LENGTH()716 HANDLER_ATTRIBUTES bool ARRAY_LENGTH() {
717 ObjPtr<mirror::Object> array = GetVRegReference(B());
718 if (UNLIKELY(array == nullptr)) {
719 ThrowNullPointerExceptionFromInterpreter();
720 return false; // Pending exception.
721 } else {
722 SetVReg(A(), array->AsArray()->GetLength());
723 }
724 return true;
725 }
726
NEW_INSTANCE()727 HANDLER_ATTRIBUTES bool NEW_INSTANCE() {
728 ObjPtr<mirror::Object> obj = nullptr;
729 ObjPtr<mirror::Class> c = ResolveVerifyAndClinit(dex::TypeIndex(B()),
730 shadow_frame.GetMethod(),
731 self,
732 false,
733 do_access_check);
734 if (LIKELY(c != nullptr)) {
735 // Don't allow finalizable objects to be allocated during a transaction since these can't
736 // be finalized without a started runtime.
737 if (transaction_active && c->IsFinalizable()) {
738 AbortTransactionF(self,
739 "Allocating finalizable object in transaction: %s",
740 c->PrettyDescriptor().c_str());
741 return false; // Pending exception.
742 }
743 gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator();
744 if (UNLIKELY(c->IsStringClass())) {
745 obj = mirror::String::AllocEmptyString(self, allocator_type);
746 } else {
747 obj = AllocObjectFromCode(c, self, allocator_type);
748 }
749 }
750 if (UNLIKELY(obj == nullptr)) {
751 return false; // Pending exception.
752 } else {
753 obj->GetClass()->AssertInitializedOrInitializingInThread(self);
754 SetVRegReference(A(), obj);
755 }
756 return true;
757 }
758
NEW_ARRAY()759 HANDLER_ATTRIBUTES bool NEW_ARRAY() {
760 int32_t length = GetVReg(B());
761 ObjPtr<mirror::Object> obj = AllocArrayFromCode<do_access_check>(
762 dex::TypeIndex(C()),
763 length,
764 shadow_frame.GetMethod(),
765 self,
766 Runtime::Current()->GetHeap()->GetCurrentAllocator());
767 if (UNLIKELY(obj == nullptr)) {
768 return false; // Pending exception.
769 } else {
770 SetVRegReference(A(), obj);
771 }
772 return true;
773 }
774
FILLED_NEW_ARRAY()775 HANDLER_ATTRIBUTES bool FILLED_NEW_ARRAY() {
776 return DoFilledNewArray<false, do_access_check, transaction_active>(
777 inst, shadow_frame, self, ResultRegister());
778 }
779
FILLED_NEW_ARRAY_RANGE()780 HANDLER_ATTRIBUTES bool FILLED_NEW_ARRAY_RANGE() {
781 return DoFilledNewArray<true, do_access_check, transaction_active>(
782 inst, shadow_frame, self, ResultRegister());
783 }
784
FILL_ARRAY_DATA()785 HANDLER_ATTRIBUTES bool FILL_ARRAY_DATA() {
786 const uint16_t* payload_addr = reinterpret_cast<const uint16_t*>(inst) + B();
787 const Instruction::ArrayDataPayload* payload =
788 reinterpret_cast<const Instruction::ArrayDataPayload*>(payload_addr);
789 ObjPtr<mirror::Object> obj = GetVRegReference(A());
790 if (!FillArrayData(obj, payload)) {
791 return false; // Pending exception.
792 }
793 if (transaction_active) {
794 RecordArrayElementsInTransaction(obj->AsArray(), payload->element_count);
795 }
796 return true;
797 }
798
THROW()799 HANDLER_ATTRIBUTES bool THROW() {
800 if (!HandleAsyncException()) {
801 return false;
802 }
803 ObjPtr<mirror::Object> exception = GetVRegReference(A());
804 if (UNLIKELY(exception == nullptr)) {
805 ThrowNullPointerException();
806 } else if (do_assignability_check && !exception->GetClass()->IsThrowableClass()) {
807 // This should never happen.
808 std::string temp;
809 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
810 "Throwing '%s' that is not instance of Throwable",
811 exception->GetClass()->GetDescriptor(&temp));
812 } else {
813 self->SetException(exception->AsThrowable());
814 }
815 return false; // Pending exception.
816 }
817
GOTO()818 HANDLER_ATTRIBUTES bool GOTO() {
819 return HandleGoto(A());
820 }
821
GOTO_16()822 HANDLER_ATTRIBUTES bool GOTO_16() {
823 return HandleGoto(A());
824 }
825
GOTO_32()826 HANDLER_ATTRIBUTES bool GOTO_32() {
827 return HandleGoto(A());
828 }
829
PACKED_SWITCH()830 HANDLER_ATTRIBUTES bool PACKED_SWITCH() {
831 int32_t offset = DoPackedSwitch(inst, shadow_frame, inst_data);
832 if (!BranchInstrumentation(offset)) {
833 return false;
834 }
835 SetNextInstruction(inst->RelativeAt(offset));
836 HandleBackwardBranch(offset);
837 return true;
838 }
839
SPARSE_SWITCH()840 HANDLER_ATTRIBUTES bool SPARSE_SWITCH() {
841 int32_t offset = DoSparseSwitch(inst, shadow_frame, inst_data);
842 if (!BranchInstrumentation(offset)) {
843 return false;
844 }
845 SetNextInstruction(inst->RelativeAt(offset));
846 HandleBackwardBranch(offset);
847 return true;
848 }
849
CMPL_FLOAT()850 HANDLER_ATTRIBUTES bool CMPL_FLOAT() {
851 return HandleCmpl<float>(GetVRegFloat(B()), GetVRegFloat(C()));
852 }
853
CMPG_FLOAT()854 HANDLER_ATTRIBUTES bool CMPG_FLOAT() {
855 return HandleCmpg<float>(GetVRegFloat(B()), GetVRegFloat(C()));
856 }
857
CMPL_DOUBLE()858 HANDLER_ATTRIBUTES bool CMPL_DOUBLE() {
859 return HandleCmpl<double>(GetVRegDouble(B()), GetVRegDouble(C()));
860 }
861
CMPG_DOUBLE()862 HANDLER_ATTRIBUTES bool CMPG_DOUBLE() {
863 return HandleCmpg<double>(GetVRegDouble(B()), GetVRegDouble(C()));
864 }
865
CMP_LONG()866 HANDLER_ATTRIBUTES bool CMP_LONG() {
867 return HandleCmpl<int64_t>(GetVRegLong(B()), GetVRegLong(C()));
868 }
869
IF_EQ()870 HANDLER_ATTRIBUTES bool IF_EQ() {
871 return HandleIf(GetVReg(A()) == GetVReg(B()), C());
872 }
873
IF_NE()874 HANDLER_ATTRIBUTES bool IF_NE() {
875 return HandleIf(GetVReg(A()) != GetVReg(B()), C());
876 }
877
IF_LT()878 HANDLER_ATTRIBUTES bool IF_LT() {
879 return HandleIf(GetVReg(A()) < GetVReg(B()), C());
880 }
881
IF_GE()882 HANDLER_ATTRIBUTES bool IF_GE() {
883 return HandleIf(GetVReg(A()) >= GetVReg(B()), C());
884 }
885
IF_GT()886 HANDLER_ATTRIBUTES bool IF_GT() {
887 return HandleIf(GetVReg(A()) > GetVReg(B()), C());
888 }
889
IF_LE()890 HANDLER_ATTRIBUTES bool IF_LE() {
891 return HandleIf(GetVReg(A()) <= GetVReg(B()), C());
892 }
893
IF_EQZ()894 HANDLER_ATTRIBUTES bool IF_EQZ() {
895 return HandleIf(GetVReg(A()) == 0, B());
896 }
897
IF_NEZ()898 HANDLER_ATTRIBUTES bool IF_NEZ() {
899 return HandleIf(GetVReg(A()) != 0, B());
900 }
901
IF_LTZ()902 HANDLER_ATTRIBUTES bool IF_LTZ() {
903 return HandleIf(GetVReg(A()) < 0, B());
904 }
905
IF_GEZ()906 HANDLER_ATTRIBUTES bool IF_GEZ() {
907 return HandleIf(GetVReg(A()) >= 0, B());
908 }
909
IF_GTZ()910 HANDLER_ATTRIBUTES bool IF_GTZ() {
911 return HandleIf(GetVReg(A()) > 0, B());
912 }
913
IF_LEZ()914 HANDLER_ATTRIBUTES bool IF_LEZ() {
915 return HandleIf(GetVReg(A()) <= 0, B());
916 }
917
AGET_BOOLEAN()918 HANDLER_ATTRIBUTES bool AGET_BOOLEAN() {
919 return HandleAGet<mirror::BooleanArray>(&InstructionHandler::SetVReg);
920 }
921
AGET_BYTE()922 HANDLER_ATTRIBUTES bool AGET_BYTE() {
923 return HandleAGet<mirror::ByteArray>(&InstructionHandler::SetVReg);
924 }
925
AGET_CHAR()926 HANDLER_ATTRIBUTES bool AGET_CHAR() {
927 return HandleAGet<mirror::CharArray>(&InstructionHandler::SetVReg);
928 }
929
AGET_SHORT()930 HANDLER_ATTRIBUTES bool AGET_SHORT() {
931 return HandleAGet<mirror::ShortArray>(&InstructionHandler::SetVReg);
932 }
933
AGET()934 HANDLER_ATTRIBUTES bool AGET() {
935 return HandleAGet<mirror::IntArray>(&InstructionHandler::SetVReg);
936 }
937
AGET_WIDE()938 HANDLER_ATTRIBUTES bool AGET_WIDE() {
939 return HandleAGet<mirror::LongArray>(&InstructionHandler::SetVRegLong);
940 }
941
AGET_OBJECT()942 HANDLER_ATTRIBUTES bool AGET_OBJECT() {
943 return HandleAGet<mirror::ObjectArray<mirror::Object>>(&InstructionHandler::SetVRegReference);
944 }
945
APUT_BOOLEAN()946 HANDLER_ATTRIBUTES bool APUT_BOOLEAN() {
947 return HandleAPut<mirror::BooleanArray>(GetVReg(A()));
948 }
949
APUT_BYTE()950 HANDLER_ATTRIBUTES bool APUT_BYTE() {
951 return HandleAPut<mirror::ByteArray>(GetVReg(A()));
952 }
953
APUT_CHAR()954 HANDLER_ATTRIBUTES bool APUT_CHAR() {
955 return HandleAPut<mirror::CharArray>(GetVReg(A()));
956 }
957
APUT_SHORT()958 HANDLER_ATTRIBUTES bool APUT_SHORT() {
959 return HandleAPut<mirror::ShortArray>(GetVReg(A()));
960 }
961
APUT()962 HANDLER_ATTRIBUTES bool APUT() {
963 return HandleAPut<mirror::IntArray>(GetVReg(A()));
964 }
965
APUT_WIDE()966 HANDLER_ATTRIBUTES bool APUT_WIDE() {
967 return HandleAPut<mirror::LongArray>(GetVRegLong(A()));
968 }
969
APUT_OBJECT()970 HANDLER_ATTRIBUTES bool APUT_OBJECT() {
971 ObjPtr<mirror::Object> a = GetVRegReference(B());
972 if (UNLIKELY(a == nullptr)) {
973 ThrowNullPointerExceptionFromInterpreter();
974 return false; // Pending exception.
975 }
976 int32_t index = GetVReg(C());
977 ObjPtr<mirror::Object> val = GetVRegReference(A());
978 ObjPtr<mirror::ObjectArray<mirror::Object>> array = a->AsObjectArray<mirror::Object>();
979 if (array->CheckIsValidIndex(index) && array->CheckAssignable(val)) {
980 if (transaction_active &&
981 (!CheckWriteConstraint(self, array) || !CheckWriteValueConstraint(self, val))) {
982 return false;
983 }
984 array->SetWithoutChecks<transaction_active>(index, val);
985 } else {
986 return false; // Pending exception.
987 }
988 return true;
989 }
990
IGET_BOOLEAN()991 HANDLER_ATTRIBUTES bool IGET_BOOLEAN() {
992 return HandleGet<InstancePrimitiveRead, Primitive::kPrimBoolean>();
993 }
994
IGET_BYTE()995 HANDLER_ATTRIBUTES bool IGET_BYTE() {
996 return HandleGet<InstancePrimitiveRead, Primitive::kPrimByte>();
997 }
998
IGET_CHAR()999 HANDLER_ATTRIBUTES bool IGET_CHAR() {
1000 return HandleGet<InstancePrimitiveRead, Primitive::kPrimChar>();
1001 }
1002
IGET_SHORT()1003 HANDLER_ATTRIBUTES bool IGET_SHORT() {
1004 return HandleGet<InstancePrimitiveRead, Primitive::kPrimShort>();
1005 }
1006
IGET()1007 HANDLER_ATTRIBUTES bool IGET() {
1008 return HandleGet<InstancePrimitiveRead, Primitive::kPrimInt>();
1009 }
1010
IGET_WIDE()1011 HANDLER_ATTRIBUTES bool IGET_WIDE() {
1012 return HandleGet<InstancePrimitiveRead, Primitive::kPrimLong>();
1013 }
1014
IGET_OBJECT()1015 HANDLER_ATTRIBUTES bool IGET_OBJECT() {
1016 return HandleGet<InstanceObjectRead, Primitive::kPrimNot>();
1017 }
1018
IGET_QUICK()1019 HANDLER_ATTRIBUTES bool IGET_QUICK() {
1020 return HandleGetQuick<Primitive::kPrimInt>();
1021 }
1022
IGET_WIDE_QUICK()1023 HANDLER_ATTRIBUTES bool IGET_WIDE_QUICK() {
1024 return HandleGetQuick<Primitive::kPrimLong>();
1025 }
1026
IGET_OBJECT_QUICK()1027 HANDLER_ATTRIBUTES bool IGET_OBJECT_QUICK() {
1028 return HandleGetQuick<Primitive::kPrimNot>();
1029 }
1030
IGET_BOOLEAN_QUICK()1031 HANDLER_ATTRIBUTES bool IGET_BOOLEAN_QUICK() {
1032 return HandleGetQuick<Primitive::kPrimBoolean>();
1033 }
1034
IGET_BYTE_QUICK()1035 HANDLER_ATTRIBUTES bool IGET_BYTE_QUICK() {
1036 return HandleGetQuick<Primitive::kPrimByte>();
1037 }
1038
IGET_CHAR_QUICK()1039 HANDLER_ATTRIBUTES bool IGET_CHAR_QUICK() {
1040 return HandleGetQuick<Primitive::kPrimChar>();
1041 }
1042
IGET_SHORT_QUICK()1043 HANDLER_ATTRIBUTES bool IGET_SHORT_QUICK() {
1044 return HandleGetQuick<Primitive::kPrimShort>();
1045 }
1046
SGET_BOOLEAN()1047 HANDLER_ATTRIBUTES bool SGET_BOOLEAN() {
1048 return HandleGet<StaticPrimitiveRead, Primitive::kPrimBoolean>();
1049 }
1050
SGET_BYTE()1051 HANDLER_ATTRIBUTES bool SGET_BYTE() {
1052 return HandleGet<StaticPrimitiveRead, Primitive::kPrimByte>();
1053 }
1054
SGET_CHAR()1055 HANDLER_ATTRIBUTES bool SGET_CHAR() {
1056 return HandleGet<StaticPrimitiveRead, Primitive::kPrimChar>();
1057 }
1058
SGET_SHORT()1059 HANDLER_ATTRIBUTES bool SGET_SHORT() {
1060 return HandleGet<StaticPrimitiveRead, Primitive::kPrimShort>();
1061 }
1062
SGET()1063 HANDLER_ATTRIBUTES bool SGET() {
1064 return HandleGet<StaticPrimitiveRead, Primitive::kPrimInt>();
1065 }
1066
SGET_WIDE()1067 HANDLER_ATTRIBUTES bool SGET_WIDE() {
1068 return HandleGet<StaticPrimitiveRead, Primitive::kPrimLong>();
1069 }
1070
SGET_OBJECT()1071 HANDLER_ATTRIBUTES bool SGET_OBJECT() {
1072 return HandleGet<StaticObjectRead, Primitive::kPrimNot>();
1073 }
1074
IPUT_BOOLEAN()1075 HANDLER_ATTRIBUTES bool IPUT_BOOLEAN() {
1076 return HandlePut<InstancePrimitiveWrite, Primitive::kPrimBoolean>();
1077 }
1078
IPUT_BYTE()1079 HANDLER_ATTRIBUTES bool IPUT_BYTE() {
1080 return HandlePut<InstancePrimitiveWrite, Primitive::kPrimByte>();
1081 }
1082
IPUT_CHAR()1083 HANDLER_ATTRIBUTES bool IPUT_CHAR() {
1084 return HandlePut<InstancePrimitiveWrite, Primitive::kPrimChar>();
1085 }
1086
IPUT_SHORT()1087 HANDLER_ATTRIBUTES bool IPUT_SHORT() {
1088 return HandlePut<InstancePrimitiveWrite, Primitive::kPrimShort>();
1089 }
1090
IPUT()1091 HANDLER_ATTRIBUTES bool IPUT() {
1092 return HandlePut<InstancePrimitiveWrite, Primitive::kPrimInt>();
1093 }
1094
IPUT_WIDE()1095 HANDLER_ATTRIBUTES bool IPUT_WIDE() {
1096 return HandlePut<InstancePrimitiveWrite, Primitive::kPrimLong>();
1097 }
1098
IPUT_OBJECT()1099 HANDLER_ATTRIBUTES bool IPUT_OBJECT() {
1100 return HandlePut<InstanceObjectWrite, Primitive::kPrimNot>();
1101 }
1102
IPUT_QUICK()1103 HANDLER_ATTRIBUTES bool IPUT_QUICK() {
1104 return HandlePutQuick<Primitive::kPrimInt>();
1105 }
1106
IPUT_BOOLEAN_QUICK()1107 HANDLER_ATTRIBUTES bool IPUT_BOOLEAN_QUICK() {
1108 return HandlePutQuick<Primitive::kPrimBoolean>();
1109 }
1110
IPUT_BYTE_QUICK()1111 HANDLER_ATTRIBUTES bool IPUT_BYTE_QUICK() {
1112 return HandlePutQuick<Primitive::kPrimByte>();
1113 }
1114
IPUT_CHAR_QUICK()1115 HANDLER_ATTRIBUTES bool IPUT_CHAR_QUICK() {
1116 return HandlePutQuick<Primitive::kPrimChar>();
1117 }
1118
IPUT_SHORT_QUICK()1119 HANDLER_ATTRIBUTES bool IPUT_SHORT_QUICK() {
1120 return HandlePutQuick<Primitive::kPrimShort>();
1121 }
1122
IPUT_WIDE_QUICK()1123 HANDLER_ATTRIBUTES bool IPUT_WIDE_QUICK() {
1124 return HandlePutQuick<Primitive::kPrimLong>();
1125 }
1126
IPUT_OBJECT_QUICK()1127 HANDLER_ATTRIBUTES bool IPUT_OBJECT_QUICK() {
1128 return HandlePutQuick<Primitive::kPrimNot>();
1129 }
1130
SPUT_BOOLEAN()1131 HANDLER_ATTRIBUTES bool SPUT_BOOLEAN() {
1132 return HandlePut<StaticPrimitiveWrite, Primitive::kPrimBoolean>();
1133 }
1134
SPUT_BYTE()1135 HANDLER_ATTRIBUTES bool SPUT_BYTE() {
1136 return HandlePut<StaticPrimitiveWrite, Primitive::kPrimByte>();
1137 }
1138
SPUT_CHAR()1139 HANDLER_ATTRIBUTES bool SPUT_CHAR() {
1140 return HandlePut<StaticPrimitiveWrite, Primitive::kPrimChar>();
1141 }
1142
SPUT_SHORT()1143 HANDLER_ATTRIBUTES bool SPUT_SHORT() {
1144 return HandlePut<StaticPrimitiveWrite, Primitive::kPrimShort>();
1145 }
1146
SPUT()1147 HANDLER_ATTRIBUTES bool SPUT() {
1148 return HandlePut<StaticPrimitiveWrite, Primitive::kPrimInt>();
1149 }
1150
SPUT_WIDE()1151 HANDLER_ATTRIBUTES bool SPUT_WIDE() {
1152 return HandlePut<StaticPrimitiveWrite, Primitive::kPrimLong>();
1153 }
1154
SPUT_OBJECT()1155 HANDLER_ATTRIBUTES bool SPUT_OBJECT() {
1156 return HandlePut<StaticObjectWrite, Primitive::kPrimNot>();
1157 }
1158
INVOKE_VIRTUAL()1159 HANDLER_ATTRIBUTES bool INVOKE_VIRTUAL() {
1160 return HandleInvoke<kVirtual, /*is_range=*/ false>();
1161 }
1162
INVOKE_VIRTUAL_RANGE()1163 HANDLER_ATTRIBUTES bool INVOKE_VIRTUAL_RANGE() {
1164 return HandleInvoke<kVirtual, /*is_range=*/ true>();
1165 }
1166
INVOKE_SUPER()1167 HANDLER_ATTRIBUTES bool INVOKE_SUPER() {
1168 return HandleInvoke<kSuper, /*is_range=*/ false>();
1169 }
1170
INVOKE_SUPER_RANGE()1171 HANDLER_ATTRIBUTES bool INVOKE_SUPER_RANGE() {
1172 return HandleInvoke<kSuper, /*is_range=*/ true>();
1173 }
1174
INVOKE_DIRECT()1175 HANDLER_ATTRIBUTES bool INVOKE_DIRECT() {
1176 return HandleInvoke<kDirect, /*is_range=*/ false>();
1177 }
1178
INVOKE_DIRECT_RANGE()1179 HANDLER_ATTRIBUTES bool INVOKE_DIRECT_RANGE() {
1180 return HandleInvoke<kDirect, /*is_range=*/ true>();
1181 }
1182
INVOKE_INTERFACE()1183 HANDLER_ATTRIBUTES bool INVOKE_INTERFACE() {
1184 return HandleInvoke<kInterface, /*is_range=*/ false>();
1185 }
1186
INVOKE_INTERFACE_RANGE()1187 HANDLER_ATTRIBUTES bool INVOKE_INTERFACE_RANGE() {
1188 return HandleInvoke<kInterface, /*is_range=*/ true>();
1189 }
1190
INVOKE_STATIC()1191 HANDLER_ATTRIBUTES bool INVOKE_STATIC() {
1192 return HandleInvoke<kStatic, /*is_range=*/ false>();
1193 }
1194
INVOKE_STATIC_RANGE()1195 HANDLER_ATTRIBUTES bool INVOKE_STATIC_RANGE() {
1196 return HandleInvoke<kStatic, /*is_range=*/ true>();
1197 }
1198
INVOKE_VIRTUAL_QUICK()1199 HANDLER_ATTRIBUTES bool INVOKE_VIRTUAL_QUICK() {
1200 return HandleInvoke<kVirtual, /*is_range=*/ false, /*is_quick=*/ true>();
1201 }
1202
INVOKE_VIRTUAL_RANGE_QUICK()1203 HANDLER_ATTRIBUTES bool INVOKE_VIRTUAL_RANGE_QUICK() {
1204 return HandleInvoke<kVirtual, /*is_range=*/ true, /*is_quick=*/ true>();
1205 }
1206
INVOKE_POLYMORPHIC()1207 HANDLER_ATTRIBUTES bool INVOKE_POLYMORPHIC() {
1208 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1209 bool success = DoInvokePolymorphic</* is_range= */ false>(
1210 self, shadow_frame, inst, inst_data, ResultRegister());
1211 return PossiblyHandlePendingExceptionOnInvoke(!success);
1212 }
1213
INVOKE_POLYMORPHIC_RANGE()1214 HANDLER_ATTRIBUTES bool INVOKE_POLYMORPHIC_RANGE() {
1215 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1216 bool success = DoInvokePolymorphic</* is_range= */ true>(
1217 self, shadow_frame, inst, inst_data, ResultRegister());
1218 return PossiblyHandlePendingExceptionOnInvoke(!success);
1219 }
1220
INVOKE_CUSTOM()1221 HANDLER_ATTRIBUTES bool INVOKE_CUSTOM() {
1222 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1223 bool success = DoInvokeCustom</* is_range= */ false>(
1224 self, shadow_frame, inst, inst_data, ResultRegister());
1225 return PossiblyHandlePendingExceptionOnInvoke(!success);
1226 }
1227
INVOKE_CUSTOM_RANGE()1228 HANDLER_ATTRIBUTES bool INVOKE_CUSTOM_RANGE() {
1229 DCHECK(Runtime::Current()->IsMethodHandlesEnabled());
1230 bool success = DoInvokeCustom</* is_range= */ true>(
1231 self, shadow_frame, inst, inst_data, ResultRegister());
1232 return PossiblyHandlePendingExceptionOnInvoke(!success);
1233 }
1234
NEG_INT()1235 HANDLER_ATTRIBUTES bool NEG_INT() {
1236 SetVReg(A(), -GetVReg(B()));
1237 return true;
1238 }
1239
NOT_INT()1240 HANDLER_ATTRIBUTES bool NOT_INT() {
1241 SetVReg(A(), ~GetVReg(B()));
1242 return true;
1243 }
1244
NEG_LONG()1245 HANDLER_ATTRIBUTES bool NEG_LONG() {
1246 SetVRegLong(A(), -GetVRegLong(B()));
1247 return true;
1248 }
1249
NOT_LONG()1250 HANDLER_ATTRIBUTES bool NOT_LONG() {
1251 SetVRegLong(A(), ~GetVRegLong(B()));
1252 return true;
1253 }
1254
NEG_FLOAT()1255 HANDLER_ATTRIBUTES bool NEG_FLOAT() {
1256 SetVRegFloat(A(), -GetVRegFloat(B()));
1257 return true;
1258 }
1259
NEG_DOUBLE()1260 HANDLER_ATTRIBUTES bool NEG_DOUBLE() {
1261 SetVRegDouble(A(), -GetVRegDouble(B()));
1262 return true;
1263 }
1264
INT_TO_LONG()1265 HANDLER_ATTRIBUTES bool INT_TO_LONG() {
1266 SetVRegLong(A(), GetVReg(B()));
1267 return true;
1268 }
1269
INT_TO_FLOAT()1270 HANDLER_ATTRIBUTES bool INT_TO_FLOAT() {
1271 SetVRegFloat(A(), GetVReg(B()));
1272 return true;
1273 }
1274
INT_TO_DOUBLE()1275 HANDLER_ATTRIBUTES bool INT_TO_DOUBLE() {
1276 SetVRegDouble(A(), GetVReg(B()));
1277 return true;
1278 }
1279
LONG_TO_INT()1280 HANDLER_ATTRIBUTES bool LONG_TO_INT() {
1281 SetVReg(A(), GetVRegLong(B()));
1282 return true;
1283 }
1284
LONG_TO_FLOAT()1285 HANDLER_ATTRIBUTES bool LONG_TO_FLOAT() {
1286 SetVRegFloat(A(), GetVRegLong(B()));
1287 return true;
1288 }
1289
LONG_TO_DOUBLE()1290 HANDLER_ATTRIBUTES bool LONG_TO_DOUBLE() {
1291 SetVRegDouble(A(), GetVRegLong(B()));
1292 return true;
1293 }
1294
FLOAT_TO_INT()1295 HANDLER_ATTRIBUTES bool FLOAT_TO_INT() {
1296 float val = GetVRegFloat(B());
1297 int32_t result = art_float_to_integral<int32_t, float>(val);
1298 SetVReg(A(), result);
1299 return true;
1300 }
1301
FLOAT_TO_LONG()1302 HANDLER_ATTRIBUTES bool FLOAT_TO_LONG() {
1303 float val = GetVRegFloat(B());
1304 int64_t result = art_float_to_integral<int64_t, float>(val);
1305 SetVRegLong(A(), result);
1306 return true;
1307 }
1308
FLOAT_TO_DOUBLE()1309 HANDLER_ATTRIBUTES bool FLOAT_TO_DOUBLE() {
1310 SetVRegDouble(A(), GetVRegFloat(B()));
1311 return true;
1312 }
1313
DOUBLE_TO_INT()1314 HANDLER_ATTRIBUTES bool DOUBLE_TO_INT() {
1315 double val = GetVRegDouble(B());
1316 int32_t result = art_float_to_integral<int32_t, double>(val);
1317 SetVReg(A(), result);
1318 return true;
1319 }
1320
DOUBLE_TO_LONG()1321 HANDLER_ATTRIBUTES bool DOUBLE_TO_LONG() {
1322 double val = GetVRegDouble(B());
1323 int64_t result = art_float_to_integral<int64_t, double>(val);
1324 SetVRegLong(A(), result);
1325 return true;
1326 }
1327
DOUBLE_TO_FLOAT()1328 HANDLER_ATTRIBUTES bool DOUBLE_TO_FLOAT() {
1329 SetVRegFloat(A(), GetVRegDouble(B()));
1330 return true;
1331 }
1332
INT_TO_BYTE()1333 HANDLER_ATTRIBUTES bool INT_TO_BYTE() {
1334 SetVReg(A(), static_cast<int8_t>(GetVReg(B())));
1335 return true;
1336 }
1337
INT_TO_CHAR()1338 HANDLER_ATTRIBUTES bool INT_TO_CHAR() {
1339 SetVReg(A(), static_cast<uint16_t>(GetVReg(B())));
1340 return true;
1341 }
1342
INT_TO_SHORT()1343 HANDLER_ATTRIBUTES bool INT_TO_SHORT() {
1344 SetVReg(A(), static_cast<int16_t>(GetVReg(B())));
1345 return true;
1346 }
1347
ADD_INT()1348 HANDLER_ATTRIBUTES bool ADD_INT() {
1349 SetVReg(A(), SafeAdd(GetVReg(B()), GetVReg(C())));
1350 return true;
1351 }
1352
SUB_INT()1353 HANDLER_ATTRIBUTES bool SUB_INT() {
1354 SetVReg(A(), SafeSub(GetVReg(B()), GetVReg(C())));
1355 return true;
1356 }
1357
MUL_INT()1358 HANDLER_ATTRIBUTES bool MUL_INT() {
1359 SetVReg(A(), SafeMul(GetVReg(B()), GetVReg(C())));
1360 return true;
1361 }
1362
DIV_INT()1363 HANDLER_ATTRIBUTES bool DIV_INT() {
1364 return DoIntDivide(shadow_frame, A(), GetVReg(B()), GetVReg(C()));
1365 }
1366
REM_INT()1367 HANDLER_ATTRIBUTES bool REM_INT() {
1368 return DoIntRemainder(shadow_frame, A(), GetVReg(B()), GetVReg(C()));
1369 }
1370
SHL_INT()1371 HANDLER_ATTRIBUTES bool SHL_INT() {
1372 SetVReg(A(), GetVReg(B()) << (GetVReg(C()) & 0x1f));
1373 return true;
1374 }
1375
SHR_INT()1376 HANDLER_ATTRIBUTES bool SHR_INT() {
1377 SetVReg(A(), GetVReg(B()) >> (GetVReg(C()) & 0x1f));
1378 return true;
1379 }
1380
USHR_INT()1381 HANDLER_ATTRIBUTES bool USHR_INT() {
1382 SetVReg(A(), static_cast<uint32_t>(GetVReg(B())) >> (GetVReg(C()) & 0x1f));
1383 return true;
1384 }
1385
AND_INT()1386 HANDLER_ATTRIBUTES bool AND_INT() {
1387 SetVReg(A(), GetVReg(B()) & GetVReg(C()));
1388 return true;
1389 }
1390
OR_INT()1391 HANDLER_ATTRIBUTES bool OR_INT() {
1392 SetVReg(A(), GetVReg(B()) | GetVReg(C()));
1393 return true;
1394 }
1395
XOR_INT()1396 HANDLER_ATTRIBUTES bool XOR_INT() {
1397 SetVReg(A(), GetVReg(B()) ^ GetVReg(C()));
1398 return true;
1399 }
1400
ADD_LONG()1401 HANDLER_ATTRIBUTES bool ADD_LONG() {
1402 SetVRegLong(A(), SafeAdd(GetVRegLong(B()), GetVRegLong(C())));
1403 return true;
1404 }
1405
SUB_LONG()1406 HANDLER_ATTRIBUTES bool SUB_LONG() {
1407 SetVRegLong(A(), SafeSub(GetVRegLong(B()), GetVRegLong(C())));
1408 return true;
1409 }
1410
MUL_LONG()1411 HANDLER_ATTRIBUTES bool MUL_LONG() {
1412 SetVRegLong(A(), SafeMul(GetVRegLong(B()), GetVRegLong(C())));
1413 return true;
1414 }
1415
DIV_LONG()1416 HANDLER_ATTRIBUTES bool DIV_LONG() {
1417 return DoLongDivide(shadow_frame, A(), GetVRegLong(B()), GetVRegLong(C()));
1418 }
1419
REM_LONG()1420 HANDLER_ATTRIBUTES bool REM_LONG() {
1421 return DoLongRemainder(shadow_frame, A(), GetVRegLong(B()), GetVRegLong(C()));
1422 }
1423
AND_LONG()1424 HANDLER_ATTRIBUTES bool AND_LONG() {
1425 SetVRegLong(A(), GetVRegLong(B()) & GetVRegLong(C()));
1426 return true;
1427 }
1428
OR_LONG()1429 HANDLER_ATTRIBUTES bool OR_LONG() {
1430 SetVRegLong(A(), GetVRegLong(B()) | GetVRegLong(C()));
1431 return true;
1432 }
1433
XOR_LONG()1434 HANDLER_ATTRIBUTES bool XOR_LONG() {
1435 SetVRegLong(A(), GetVRegLong(B()) ^ GetVRegLong(C()));
1436 return true;
1437 }
1438
SHL_LONG()1439 HANDLER_ATTRIBUTES bool SHL_LONG() {
1440 SetVRegLong(A(), GetVRegLong(B()) << (GetVReg(C()) & 0x3f));
1441 return true;
1442 }
1443
SHR_LONG()1444 HANDLER_ATTRIBUTES bool SHR_LONG() {
1445 SetVRegLong(A(), GetVRegLong(B()) >> (GetVReg(C()) & 0x3f));
1446 return true;
1447 }
1448
USHR_LONG()1449 HANDLER_ATTRIBUTES bool USHR_LONG() {
1450 SetVRegLong(A(), static_cast<uint64_t>(GetVRegLong(B())) >> (GetVReg(C()) & 0x3f));
1451 return true;
1452 }
1453
ADD_FLOAT()1454 HANDLER_ATTRIBUTES bool ADD_FLOAT() {
1455 SetVRegFloat(A(), GetVRegFloat(B()) + GetVRegFloat(C()));
1456 return true;
1457 }
1458
SUB_FLOAT()1459 HANDLER_ATTRIBUTES bool SUB_FLOAT() {
1460 SetVRegFloat(A(), GetVRegFloat(B()) - GetVRegFloat(C()));
1461 return true;
1462 }
1463
MUL_FLOAT()1464 HANDLER_ATTRIBUTES bool MUL_FLOAT() {
1465 SetVRegFloat(A(), GetVRegFloat(B()) * GetVRegFloat(C()));
1466 return true;
1467 }
1468
DIV_FLOAT()1469 HANDLER_ATTRIBUTES bool DIV_FLOAT() {
1470 SetVRegFloat(A(), GetVRegFloat(B()) / GetVRegFloat(C()));
1471 return true;
1472 }
1473
REM_FLOAT()1474 HANDLER_ATTRIBUTES bool REM_FLOAT() {
1475 SetVRegFloat(A(), fmodf(GetVRegFloat(B()), GetVRegFloat(C())));
1476 return true;
1477 }
1478
ADD_DOUBLE()1479 HANDLER_ATTRIBUTES bool ADD_DOUBLE() {
1480 SetVRegDouble(A(), GetVRegDouble(B()) + GetVRegDouble(C()));
1481 return true;
1482 }
1483
SUB_DOUBLE()1484 HANDLER_ATTRIBUTES bool SUB_DOUBLE() {
1485 SetVRegDouble(A(), GetVRegDouble(B()) - GetVRegDouble(C()));
1486 return true;
1487 }
1488
MUL_DOUBLE()1489 HANDLER_ATTRIBUTES bool MUL_DOUBLE() {
1490 SetVRegDouble(A(), GetVRegDouble(B()) * GetVRegDouble(C()));
1491 return true;
1492 }
1493
DIV_DOUBLE()1494 HANDLER_ATTRIBUTES bool DIV_DOUBLE() {
1495 SetVRegDouble(A(), GetVRegDouble(B()) / GetVRegDouble(C()));
1496 return true;
1497 }
1498
REM_DOUBLE()1499 HANDLER_ATTRIBUTES bool REM_DOUBLE() {
1500 SetVRegDouble(A(), fmod(GetVRegDouble(B()), GetVRegDouble(C())));
1501 return true;
1502 }
1503
ADD_INT_2ADDR()1504 HANDLER_ATTRIBUTES bool ADD_INT_2ADDR() {
1505 uint4_t vregA = A();
1506 SetVReg(vregA, SafeAdd(GetVReg(vregA), GetVReg(B())));
1507 return true;
1508 }
1509
SUB_INT_2ADDR()1510 HANDLER_ATTRIBUTES bool SUB_INT_2ADDR() {
1511 uint4_t vregA = A();
1512 SetVReg(vregA, SafeSub(GetVReg(vregA), GetVReg(B())));
1513 return true;
1514 }
1515
MUL_INT_2ADDR()1516 HANDLER_ATTRIBUTES bool MUL_INT_2ADDR() {
1517 uint4_t vregA = A();
1518 SetVReg(vregA, SafeMul(GetVReg(vregA), GetVReg(B())));
1519 return true;
1520 }
1521
DIV_INT_2ADDR()1522 HANDLER_ATTRIBUTES bool DIV_INT_2ADDR() {
1523 uint4_t vregA = A();
1524 return DoIntDivide(shadow_frame, vregA, GetVReg(vregA), GetVReg(B()));
1525 }
1526
REM_INT_2ADDR()1527 HANDLER_ATTRIBUTES bool REM_INT_2ADDR() {
1528 uint4_t vregA = A();
1529 return DoIntRemainder(shadow_frame, vregA, GetVReg(vregA), GetVReg(B()));
1530 }
1531
SHL_INT_2ADDR()1532 HANDLER_ATTRIBUTES bool SHL_INT_2ADDR() {
1533 uint4_t vregA = A();
1534 SetVReg(vregA, GetVReg(vregA) << (GetVReg(B()) & 0x1f));
1535 return true;
1536 }
1537
SHR_INT_2ADDR()1538 HANDLER_ATTRIBUTES bool SHR_INT_2ADDR() {
1539 uint4_t vregA = A();
1540 SetVReg(vregA, GetVReg(vregA) >> (GetVReg(B()) & 0x1f));
1541 return true;
1542 }
1543
USHR_INT_2ADDR()1544 HANDLER_ATTRIBUTES bool USHR_INT_2ADDR() {
1545 uint4_t vregA = A();
1546 SetVReg(vregA, static_cast<uint32_t>(GetVReg(vregA)) >> (GetVReg(B()) & 0x1f));
1547 return true;
1548 }
1549
AND_INT_2ADDR()1550 HANDLER_ATTRIBUTES bool AND_INT_2ADDR() {
1551 uint4_t vregA = A();
1552 SetVReg(vregA, GetVReg(vregA) & GetVReg(B()));
1553 return true;
1554 }
1555
OR_INT_2ADDR()1556 HANDLER_ATTRIBUTES bool OR_INT_2ADDR() {
1557 uint4_t vregA = A();
1558 SetVReg(vregA, GetVReg(vregA) | GetVReg(B()));
1559 return true;
1560 }
1561
XOR_INT_2ADDR()1562 HANDLER_ATTRIBUTES bool XOR_INT_2ADDR() {
1563 uint4_t vregA = A();
1564 SetVReg(vregA, GetVReg(vregA) ^ GetVReg(B()));
1565 return true;
1566 }
1567
ADD_LONG_2ADDR()1568 HANDLER_ATTRIBUTES bool ADD_LONG_2ADDR() {
1569 uint4_t vregA = A();
1570 SetVRegLong(vregA, SafeAdd(GetVRegLong(vregA), GetVRegLong(B())));
1571 return true;
1572 }
1573
SUB_LONG_2ADDR()1574 HANDLER_ATTRIBUTES bool SUB_LONG_2ADDR() {
1575 uint4_t vregA = A();
1576 SetVRegLong(vregA, SafeSub(GetVRegLong(vregA), GetVRegLong(B())));
1577 return true;
1578 }
1579
MUL_LONG_2ADDR()1580 HANDLER_ATTRIBUTES bool MUL_LONG_2ADDR() {
1581 uint4_t vregA = A();
1582 SetVRegLong(vregA, SafeMul(GetVRegLong(vregA), GetVRegLong(B())));
1583 return true;
1584 }
1585
DIV_LONG_2ADDR()1586 HANDLER_ATTRIBUTES bool DIV_LONG_2ADDR() {
1587 uint4_t vregA = A();
1588 return DoLongDivide(shadow_frame, vregA, GetVRegLong(vregA), GetVRegLong(B()));
1589 }
1590
REM_LONG_2ADDR()1591 HANDLER_ATTRIBUTES bool REM_LONG_2ADDR() {
1592 uint4_t vregA = A();
1593 return DoLongRemainder(shadow_frame, vregA, GetVRegLong(vregA), GetVRegLong(B()));
1594 }
1595
AND_LONG_2ADDR()1596 HANDLER_ATTRIBUTES bool AND_LONG_2ADDR() {
1597 uint4_t vregA = A();
1598 SetVRegLong(vregA, GetVRegLong(vregA) & GetVRegLong(B()));
1599 return true;
1600 }
1601
OR_LONG_2ADDR()1602 HANDLER_ATTRIBUTES bool OR_LONG_2ADDR() {
1603 uint4_t vregA = A();
1604 SetVRegLong(vregA, GetVRegLong(vregA) | GetVRegLong(B()));
1605 return true;
1606 }
1607
XOR_LONG_2ADDR()1608 HANDLER_ATTRIBUTES bool XOR_LONG_2ADDR() {
1609 uint4_t vregA = A();
1610 SetVRegLong(vregA, GetVRegLong(vregA) ^ GetVRegLong(B()));
1611 return true;
1612 }
1613
SHL_LONG_2ADDR()1614 HANDLER_ATTRIBUTES bool SHL_LONG_2ADDR() {
1615 uint4_t vregA = A();
1616 SetVRegLong(vregA, GetVRegLong(vregA) << (GetVReg(B()) & 0x3f));
1617 return true;
1618 }
1619
SHR_LONG_2ADDR()1620 HANDLER_ATTRIBUTES bool SHR_LONG_2ADDR() {
1621 uint4_t vregA = A();
1622 SetVRegLong(vregA, GetVRegLong(vregA) >> (GetVReg(B()) & 0x3f));
1623 return true;
1624 }
1625
USHR_LONG_2ADDR()1626 HANDLER_ATTRIBUTES bool USHR_LONG_2ADDR() {
1627 uint4_t vregA = A();
1628 SetVRegLong(vregA, static_cast<uint64_t>(GetVRegLong(vregA)) >> (GetVReg(B()) & 0x3f));
1629 return true;
1630 }
1631
ADD_FLOAT_2ADDR()1632 HANDLER_ATTRIBUTES bool ADD_FLOAT_2ADDR() {
1633 uint4_t vregA = A();
1634 SetVRegFloat(vregA, GetVRegFloat(vregA) + GetVRegFloat(B()));
1635 return true;
1636 }
1637
SUB_FLOAT_2ADDR()1638 HANDLER_ATTRIBUTES bool SUB_FLOAT_2ADDR() {
1639 uint4_t vregA = A();
1640 SetVRegFloat(vregA, GetVRegFloat(vregA) - GetVRegFloat(B()));
1641 return true;
1642 }
1643
MUL_FLOAT_2ADDR()1644 HANDLER_ATTRIBUTES bool MUL_FLOAT_2ADDR() {
1645 uint4_t vregA = A();
1646 SetVRegFloat(vregA, GetVRegFloat(vregA) * GetVRegFloat(B()));
1647 return true;
1648 }
1649
DIV_FLOAT_2ADDR()1650 HANDLER_ATTRIBUTES bool DIV_FLOAT_2ADDR() {
1651 uint4_t vregA = A();
1652 SetVRegFloat(vregA, GetVRegFloat(vregA) / GetVRegFloat(B()));
1653 return true;
1654 }
1655
REM_FLOAT_2ADDR()1656 HANDLER_ATTRIBUTES bool REM_FLOAT_2ADDR() {
1657 uint4_t vregA = A();
1658 SetVRegFloat(vregA, fmodf(GetVRegFloat(vregA), GetVRegFloat(B())));
1659 return true;
1660 }
1661
ADD_DOUBLE_2ADDR()1662 HANDLER_ATTRIBUTES bool ADD_DOUBLE_2ADDR() {
1663 uint4_t vregA = A();
1664 SetVRegDouble(vregA, GetVRegDouble(vregA) + GetVRegDouble(B()));
1665 return true;
1666 }
1667
SUB_DOUBLE_2ADDR()1668 HANDLER_ATTRIBUTES bool SUB_DOUBLE_2ADDR() {
1669 uint4_t vregA = A();
1670 SetVRegDouble(vregA, GetVRegDouble(vregA) - GetVRegDouble(B()));
1671 return true;
1672 }
1673
MUL_DOUBLE_2ADDR()1674 HANDLER_ATTRIBUTES bool MUL_DOUBLE_2ADDR() {
1675 uint4_t vregA = A();
1676 SetVRegDouble(vregA, GetVRegDouble(vregA) * GetVRegDouble(B()));
1677 return true;
1678 }
1679
DIV_DOUBLE_2ADDR()1680 HANDLER_ATTRIBUTES bool DIV_DOUBLE_2ADDR() {
1681 uint4_t vregA = A();
1682 SetVRegDouble(vregA, GetVRegDouble(vregA) / GetVRegDouble(B()));
1683 return true;
1684 }
1685
REM_DOUBLE_2ADDR()1686 HANDLER_ATTRIBUTES bool REM_DOUBLE_2ADDR() {
1687 uint4_t vregA = A();
1688 SetVRegDouble(vregA, fmod(GetVRegDouble(vregA), GetVRegDouble(B())));
1689 return true;
1690 }
1691
ADD_INT_LIT16()1692 HANDLER_ATTRIBUTES bool ADD_INT_LIT16() {
1693 SetVReg(A(), SafeAdd(GetVReg(B()), C()));
1694 return true;
1695 }
1696
RSUB_INT()1697 HANDLER_ATTRIBUTES bool RSUB_INT() {
1698 SetVReg(A(), SafeSub(C(), GetVReg(B())));
1699 return true;
1700 }
1701
MUL_INT_LIT16()1702 HANDLER_ATTRIBUTES bool MUL_INT_LIT16() {
1703 SetVReg(A(), SafeMul(GetVReg(B()), C()));
1704 return true;
1705 }
1706
DIV_INT_LIT16()1707 HANDLER_ATTRIBUTES bool DIV_INT_LIT16() {
1708 return DoIntDivide(shadow_frame, A(), GetVReg(B()), C());
1709 }
1710
REM_INT_LIT16()1711 HANDLER_ATTRIBUTES bool REM_INT_LIT16() {
1712 return DoIntRemainder(shadow_frame, A(), GetVReg(B()), C());
1713 }
1714
AND_INT_LIT16()1715 HANDLER_ATTRIBUTES bool AND_INT_LIT16() {
1716 SetVReg(A(), GetVReg(B()) & C());
1717 return true;
1718 }
1719
OR_INT_LIT16()1720 HANDLER_ATTRIBUTES bool OR_INT_LIT16() {
1721 SetVReg(A(), GetVReg(B()) | C());
1722 return true;
1723 }
1724
XOR_INT_LIT16()1725 HANDLER_ATTRIBUTES bool XOR_INT_LIT16() {
1726 SetVReg(A(), GetVReg(B()) ^ C());
1727 return true;
1728 }
1729
ADD_INT_LIT8()1730 HANDLER_ATTRIBUTES bool ADD_INT_LIT8() {
1731 SetVReg(A(), SafeAdd(GetVReg(B()), C()));
1732 return true;
1733 }
1734
RSUB_INT_LIT8()1735 HANDLER_ATTRIBUTES bool RSUB_INT_LIT8() {
1736 SetVReg(A(), SafeSub(C(), GetVReg(B())));
1737 return true;
1738 }
1739
MUL_INT_LIT8()1740 HANDLER_ATTRIBUTES bool MUL_INT_LIT8() {
1741 SetVReg(A(), SafeMul(GetVReg(B()), C()));
1742 return true;
1743 }
1744
DIV_INT_LIT8()1745 HANDLER_ATTRIBUTES bool DIV_INT_LIT8() {
1746 return DoIntDivide(shadow_frame, A(), GetVReg(B()), C());
1747 }
1748
REM_INT_LIT8()1749 HANDLER_ATTRIBUTES bool REM_INT_LIT8() {
1750 return DoIntRemainder(shadow_frame, A(), GetVReg(B()), C());
1751 }
1752
AND_INT_LIT8()1753 HANDLER_ATTRIBUTES bool AND_INT_LIT8() {
1754 SetVReg(A(), GetVReg(B()) & C());
1755 return true;
1756 }
1757
OR_INT_LIT8()1758 HANDLER_ATTRIBUTES bool OR_INT_LIT8() {
1759 SetVReg(A(), GetVReg(B()) | C());
1760 return true;
1761 }
1762
XOR_INT_LIT8()1763 HANDLER_ATTRIBUTES bool XOR_INT_LIT8() {
1764 SetVReg(A(), GetVReg(B()) ^ C());
1765 return true;
1766 }
1767
SHL_INT_LIT8()1768 HANDLER_ATTRIBUTES bool SHL_INT_LIT8() {
1769 SetVReg(A(), GetVReg(B()) << (C() & 0x1f));
1770 return true;
1771 }
1772
SHR_INT_LIT8()1773 HANDLER_ATTRIBUTES bool SHR_INT_LIT8() {
1774 SetVReg(A(), GetVReg(B()) >> (C() & 0x1f));
1775 return true;
1776 }
1777
USHR_INT_LIT8()1778 HANDLER_ATTRIBUTES bool USHR_INT_LIT8() {
1779 SetVReg(A(), static_cast<uint32_t>(GetVReg(B())) >> (C() & 0x1f));
1780 return true;
1781 }
1782
UNUSED_3E()1783 HANDLER_ATTRIBUTES bool UNUSED_3E() {
1784 return HandleUnused();
1785 }
1786
UNUSED_3F()1787 HANDLER_ATTRIBUTES bool UNUSED_3F() {
1788 return HandleUnused();
1789 }
1790
UNUSED_40()1791 HANDLER_ATTRIBUTES bool UNUSED_40() {
1792 return HandleUnused();
1793 }
1794
UNUSED_41()1795 HANDLER_ATTRIBUTES bool UNUSED_41() {
1796 return HandleUnused();
1797 }
1798
UNUSED_42()1799 HANDLER_ATTRIBUTES bool UNUSED_42() {
1800 return HandleUnused();
1801 }
1802
UNUSED_43()1803 HANDLER_ATTRIBUTES bool UNUSED_43() {
1804 return HandleUnused();
1805 }
1806
UNUSED_79()1807 HANDLER_ATTRIBUTES bool UNUSED_79() {
1808 return HandleUnused();
1809 }
1810
UNUSED_7A()1811 HANDLER_ATTRIBUTES bool UNUSED_7A() {
1812 return HandleUnused();
1813 }
1814
UNUSED_F3()1815 HANDLER_ATTRIBUTES bool UNUSED_F3() {
1816 return HandleUnused();
1817 }
1818
UNUSED_F4()1819 HANDLER_ATTRIBUTES bool UNUSED_F4() {
1820 return HandleUnused();
1821 }
1822
UNUSED_F5()1823 HANDLER_ATTRIBUTES bool UNUSED_F5() {
1824 return HandleUnused();
1825 }
1826
UNUSED_F6()1827 HANDLER_ATTRIBUTES bool UNUSED_F6() {
1828 return HandleUnused();
1829 }
1830
UNUSED_F7()1831 HANDLER_ATTRIBUTES bool UNUSED_F7() {
1832 return HandleUnused();
1833 }
1834
UNUSED_F8()1835 HANDLER_ATTRIBUTES bool UNUSED_F8() {
1836 return HandleUnused();
1837 }
1838
UNUSED_F9()1839 HANDLER_ATTRIBUTES bool UNUSED_F9() {
1840 return HandleUnused();
1841 }
1842
InstructionHandler(SwitchImplContext * ctx,const instrumentation::Instrumentation * instrumentation,Thread * self,ShadowFrame & shadow_frame,uint16_t dex_pc,const Instruction * inst,uint16_t inst_data,const Instruction * & next,bool & exit_interpreter_loop)1843 ALWAYS_INLINE InstructionHandler(SwitchImplContext* ctx,
1844 const instrumentation::Instrumentation* instrumentation,
1845 Thread* self,
1846 ShadowFrame& shadow_frame,
1847 uint16_t dex_pc,
1848 const Instruction* inst,
1849 uint16_t inst_data,
1850 const Instruction*& next,
1851 bool& exit_interpreter_loop)
1852 : ctx(ctx),
1853 instrumentation(instrumentation),
1854 self(self),
1855 shadow_frame(shadow_frame),
1856 dex_pc(dex_pc),
1857 inst(inst),
1858 inst_data(inst_data),
1859 next(next),
1860 exit_interpreter_loop(exit_interpreter_loop) {
1861 }
1862
1863 private:
1864 static constexpr bool do_assignability_check = do_access_check;
1865 static constexpr MonitorState kMonitorState =
1866 do_assignability_check ? MonitorState::kCountingMonitors : MonitorState::kNormalMonitors;
1867
Accessor()1868 const CodeItemDataAccessor& Accessor() { return ctx->accessor; }
Insns()1869 const uint16_t* Insns() { return ctx->accessor.Insns(); }
ResultRegister()1870 JValue* ResultRegister() { return &ctx->result_register; }
1871
A()1872 ALWAYS_INLINE int32_t A() { return inst->VRegA(kFormat, inst_data); }
B()1873 ALWAYS_INLINE int32_t B() { return inst->VRegB(kFormat, inst_data); }
C()1874 ALWAYS_INLINE int32_t C() { return inst->VRegC(kFormat); }
1875
GetVReg(size_t i)1876 int32_t GetVReg(size_t i) const { return shadow_frame.GetVReg(i); }
GetVRegLong(size_t i)1877 int64_t GetVRegLong(size_t i) const { return shadow_frame.GetVRegLong(i); }
GetVRegFloat(size_t i)1878 float GetVRegFloat(size_t i) const { return shadow_frame.GetVRegFloat(i); }
GetVRegDouble(size_t i)1879 double GetVRegDouble(size_t i) const { return shadow_frame.GetVRegDouble(i); }
GetVRegReference(size_t i)1880 ObjPtr<mirror::Object> GetVRegReference(size_t i) const REQUIRES_SHARED(Locks::mutator_lock_) {
1881 return shadow_frame.GetVRegReference(i);
1882 }
1883
SetVReg(size_t i,int32_t val)1884 void SetVReg(size_t i, int32_t val) { shadow_frame.SetVReg(i, val); }
SetVRegLong(size_t i,int64_t val)1885 void SetVRegLong(size_t i, int64_t val) { shadow_frame.SetVRegLong(i, val); }
SetVRegFloat(size_t i,float val)1886 void SetVRegFloat(size_t i, float val) { shadow_frame.SetVRegFloat(i, val); }
SetVRegDouble(size_t i,double val)1887 void SetVRegDouble(size_t i, double val) { shadow_frame.SetVRegDouble(i, val); }
SetVRegReference(size_t i,ObjPtr<mirror::Object> val)1888 void SetVRegReference(size_t i, ObjPtr<mirror::Object> val)
1889 REQUIRES_SHARED(Locks::mutator_lock_) {
1890 shadow_frame.SetVRegReference(i, val);
1891 }
1892
1893 // Set the next instruction to be executed. It is the 'fall-through' instruction by default.
SetNextInstruction(const Instruction * next_inst)1894 ALWAYS_INLINE void SetNextInstruction(const Instruction* next_inst) {
1895 DCHECK_LT(next_inst->GetDexPc(Insns()), Accessor().InsnsSizeInCodeUnits());
1896 next = next_inst;
1897 }
1898
1899 SwitchImplContext* const ctx;
1900 const instrumentation::Instrumentation* const instrumentation;
1901 Thread* const self;
1902 ShadowFrame& shadow_frame;
1903 uint32_t const dex_pc;
1904 const Instruction* const inst;
1905 uint16_t const inst_data;
1906 const Instruction*& next;
1907
1908 bool& exit_interpreter_loop;
1909 };
1910
1911 // Don't inline in ASAN. It would create massive stack frame.
1912 #if defined(ADDRESS_SANITIZER) || defined(HWADDRESS_SANITIZER)
1913 #define ASAN_NO_INLINE NO_INLINE
1914 #else
1915 #define ASAN_NO_INLINE ALWAYS_INLINE
1916 #endif
1917
1918 #define OPCODE_CASE(OPCODE, OPCODE_NAME, NAME, FORMAT, i, a, e, v) \
1919 template<bool do_access_check, bool transaction_active> \
1920 ASAN_NO_INLINE static bool OP_##OPCODE_NAME( \
1921 SwitchImplContext* ctx, \
1922 const instrumentation::Instrumentation* instrumentation, \
1923 Thread* self, \
1924 ShadowFrame& shadow_frame, \
1925 uint16_t dex_pc, \
1926 const Instruction* inst, \
1927 uint16_t inst_data, \
1928 const Instruction*& next, \
1929 bool& exit) REQUIRES_SHARED(Locks::mutator_lock_) { \
1930 InstructionHandler<do_access_check, transaction_active, Instruction::FORMAT> handler( \
1931 ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, next, exit); \
1932 return LIKELY(handler.OPCODE_NAME()); \
1933 }
DEX_INSTRUCTION_LIST(OPCODE_CASE)1934 DEX_INSTRUCTION_LIST(OPCODE_CASE)
1935 #undef OPCODE_CASE
1936
1937 template<bool do_access_check, bool transaction_active>
1938 void ExecuteSwitchImplCpp(SwitchImplContext* ctx) {
1939 Thread* self = ctx->self;
1940 const CodeItemDataAccessor& accessor = ctx->accessor;
1941 ShadowFrame& shadow_frame = ctx->shadow_frame;
1942 self->VerifyStack();
1943
1944 uint32_t dex_pc = shadow_frame.GetDexPC();
1945 const auto* const instrumentation = Runtime::Current()->GetInstrumentation();
1946 const uint16_t* const insns = accessor.Insns();
1947 const Instruction* next = Instruction::At(insns + dex_pc);
1948
1949 DCHECK(!shadow_frame.GetForceRetryInstruction())
1950 << "Entered interpreter from invoke without retry instruction being handled!";
1951
1952 bool const interpret_one_instruction = ctx->interpret_one_instruction;
1953 while (true) {
1954 const Instruction* const inst = next;
1955 dex_pc = inst->GetDexPc(insns);
1956 shadow_frame.SetDexPC(dex_pc);
1957 TraceExecution(shadow_frame, inst, dex_pc);
1958 uint16_t inst_data = inst->Fetch16(0);
1959 bool exit = false;
1960 if (InstructionHandler<do_access_check, transaction_active, Instruction::kInvalidFormat>(
1961 ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, next, exit).
1962 Preamble()) {
1963 switch (inst->Opcode(inst_data)) {
1964 #define OPCODE_CASE(OPCODE, OPCODE_NAME, NAME, FORMAT, i, a, e, v) \
1965 case OPCODE: { \
1966 DCHECK_EQ(self->IsExceptionPending(), (OPCODE == Instruction::MOVE_EXCEPTION)); \
1967 next = inst->RelativeAt(Instruction::SizeInCodeUnits(Instruction::FORMAT)); \
1968 bool success = OP_##OPCODE_NAME<do_access_check, transaction_active>( \
1969 ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, next, exit); \
1970 if (success && LIKELY(!interpret_one_instruction)) { \
1971 DCHECK(!exit) << NAME; \
1972 continue; \
1973 } \
1974 if (exit) { \
1975 shadow_frame.SetDexPC(dex::kDexNoIndex); \
1976 return; \
1977 } \
1978 break; \
1979 }
1980 DEX_INSTRUCTION_LIST(OPCODE_CASE)
1981 #undef OPCODE_CASE
1982 }
1983 } else {
1984 // Preamble returned false due to debugger event.
1985 if (exit) {
1986 shadow_frame.SetDexPC(dex::kDexNoIndex);
1987 return; // Return statement or debugger forced exit.
1988 }
1989 }
1990 if (self->IsExceptionPending()) {
1991 if (!InstructionHandler<do_access_check, transaction_active, Instruction::kInvalidFormat>(
1992 ctx, instrumentation, self, shadow_frame, dex_pc, inst, inst_data, next, exit).
1993 HandlePendingException()) {
1994 shadow_frame.SetDexPC(dex::kDexNoIndex);
1995 return; // Locally unhandled exception - return to caller.
1996 }
1997 // Continue execution in the catch block.
1998 }
1999 if (interpret_one_instruction) {
2000 shadow_frame.SetDexPC(next->GetDexPc(insns)); // Record where we stopped.
2001 ctx->result = ctx->result_register;
2002 return;
2003 }
2004 }
2005 } // NOLINT(readability/fn_size)
2006
2007 } // namespace interpreter
2008 } // namespace art
2009
2010 #endif // ART_RUNTIME_INTERPRETER_INTERPRETER_SWITCH_IMPL_INL_H_
2011