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