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