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