• 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 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