JNI compiler: Rewrite exception polling.
Make the slow path explicit in the JNI compiler. Fix the
CFI data for the exceptional path of synchronized methods.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Test: run-gtests.sh
Test: testrunner.py --target --optimizing
Bug: 172332525
Change-Id: If64965eef15c063e36b78dd8bb6cba5af34ab4fa
diff --git a/compiler/jni/quick/jni_compiler.cc b/compiler/jni/quick/jni_compiler.cc
index 25eb919..5752c75 100644
--- a/compiler/jni/quick/jni_compiler.cc
+++ b/compiler/jni/quick/jni_compiler.cc
@@ -288,6 +288,8 @@
// 5. Call into appropriate JniMethodStart passing Thread* so that transition out of Runnable
// can occur. We abuse the JNI calling convention here, that is guaranteed to support passing
// two pointer arguments.
+ std::unique_ptr<JNIMacroLabel> monitor_enter_exception_slow_path =
+ UNLIKELY(is_synchronized) ? __ CreateLabel() : nullptr;
if (LIKELY(!is_critical_native)) {
// Skip this for @CriticalNative methods. They do not call JniMethodStart.
ThreadOffset<kPointerSize> jni_start =
@@ -328,7 +330,7 @@
}
method_register = ManagedRegister::NoRegister(); // Method register is clobbered.
if (is_synchronized) { // Check for exceptions from monitor enter.
- __ ExceptionPoll(main_out_arg_size);
+ __ ExceptionPoll(monitor_enter_exception_slow_path.get());
}
}
@@ -602,8 +604,10 @@
// 17. Process pending exceptions from JNI call or monitor exit.
// @CriticalNative methods do not need exception poll in the stub.
+ std::unique_ptr<JNIMacroLabel> exception_slow_path =
+ LIKELY(!is_critical_native) ? __ CreateLabel() : nullptr;
if (LIKELY(!is_critical_native)) {
- __ ExceptionPoll(/* stack_adjust= */ 0);
+ __ ExceptionPoll(exception_slow_path.get());
}
// 18. Remove activation - need to restore callee save registers since the GC may have changed
@@ -673,7 +677,21 @@
}
}
- // 20. Finalize code generation
+ // 20. Emit exception poll slow paths.
+ if (LIKELY(!is_critical_native)) {
+ if (UNLIKELY(is_synchronized)) {
+ __ Bind(monitor_enter_exception_slow_path.get());
+ if (main_out_arg_size != 0) {
+ jni_asm->cfi().AdjustCFAOffset(main_out_arg_size);
+ __ DecreaseFrameSize(main_out_arg_size);
+ }
+ }
+ DCHECK_EQ(jni_asm->cfi().GetCurrentCFAOffset(), static_cast<int>(current_frame_size));
+ __ Bind(exception_slow_path.get());
+ __ DeliverPendingException();
+ }
+
+ // 21. Finalize code generation
__ FinalizeCode();
size_t cs = __ CodeSize();
std::vector<uint8_t> managed_code(cs);
diff --git a/compiler/utils/arm/jni_macro_assembler_arm_vixl.cc b/compiler/utils/arm/jni_macro_assembler_arm_vixl.cc
index c23d682..c59262d 100644
--- a/compiler/utils/arm/jni_macro_assembler_arm_vixl.cc
+++ b/compiler/utils/arm/jni_macro_assembler_arm_vixl.cc
@@ -68,10 +68,6 @@
}
void ArmVIXLJNIMacroAssembler::FinalizeCode() {
- for (const std::unique_ptr<
- ArmVIXLJNIMacroAssembler::ArmException>& exception : exception_blocks_) {
- EmitExceptionPoll(exception.get());
- }
asm_.FinalizeCode();
}
@@ -986,23 +982,33 @@
asm_.StoreToOffset(kStoreWord, tr, sp, dest_offset.Int32Value());
}
-void ArmVIXLJNIMacroAssembler::ExceptionPoll(size_t stack_adjust) {
- CHECK_ALIGNED(stack_adjust, kAapcsStackAlignment);
+void ArmVIXLJNIMacroAssembler::ExceptionPoll(JNIMacroLabel* label) {
UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
vixl32::Register scratch = temps.Acquire();
- exception_blocks_.emplace_back(
- new ArmVIXLJNIMacroAssembler::ArmException(scratch, stack_adjust));
asm_.LoadFromOffset(kLoadWord,
scratch,
tr,
Thread::ExceptionOffset<kArmPointerSize>().Int32Value());
___ Cmp(scratch, 0);
- vixl32::Label* label = exception_blocks_.back()->Entry();
- ___ BPreferNear(ne, label);
+ ___ BPreferNear(ne, ArmVIXLJNIMacroLabel::Cast(label)->AsArm());
// TODO: think about using CBNZ here.
}
+void ArmVIXLJNIMacroAssembler::DeliverPendingException() {
+ // Pass exception object as argument.
+ // Don't care about preserving r0 as this won't return.
+ // Note: The scratch register from `ExceptionPoll()` may have been clobbered.
+ asm_.LoadFromOffset(kLoadWord,
+ r0,
+ tr,
+ Thread::ExceptionOffset<kArmPointerSize>().Int32Value());
+ ___ Ldr(lr,
+ MemOperand(tr,
+ QUICK_ENTRYPOINT_OFFSET(kArmPointerSize, pDeliverException).Int32Value()));
+ ___ Blx(lr);
+}
+
std::unique_ptr<JNIMacroLabel> ArmVIXLJNIMacroAssembler::CreateLabel() {
return std::unique_ptr<JNIMacroLabel>(new ArmVIXLJNIMacroLabel());
}
@@ -1048,25 +1054,6 @@
___ Bind(ArmVIXLJNIMacroLabel::Cast(label)->AsArm());
}
-void ArmVIXLJNIMacroAssembler::EmitExceptionPoll(
- ArmVIXLJNIMacroAssembler::ArmException* exception) {
- ___ Bind(exception->Entry());
- if (exception->stack_adjust_ != 0) { // Fix up the frame.
- DecreaseFrameSize(exception->stack_adjust_);
- }
-
- vixl32::Register scratch = exception->scratch_;
- UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
- temps.Exclude(scratch);
- // Pass exception object as argument.
- // Don't care about preserving r0 as this won't return.
- ___ Mov(r0, scratch);
- ___ Ldr(lr,
- MemOperand(tr,
- QUICK_ENTRYPOINT_OFFSET(kArmPointerSize, pDeliverException).Int32Value()));
- ___ Blx(lr);
-}
-
void ArmVIXLJNIMacroAssembler::MemoryBarrier(ManagedRegister scratch ATTRIBUTE_UNUSED) {
UNIMPLEMENTED(FATAL);
}
diff --git a/compiler/utils/arm/jni_macro_assembler_arm_vixl.h b/compiler/utils/arm/jni_macro_assembler_arm_vixl.h
index d98f688..89805ce 100644
--- a/compiler/utils/arm/jni_macro_assembler_arm_vixl.h
+++ b/compiler/utils/arm/jni_macro_assembler_arm_vixl.h
@@ -34,12 +34,9 @@
class ArmVIXLJNIMacroAssembler final
: public JNIMacroAssemblerFwd<ArmVIXLAssembler, PointerSize::k32> {
- private:
- class ArmException;
public:
explicit ArmVIXLJNIMacroAssembler(ArenaAllocator* allocator)
- : JNIMacroAssemblerFwd(allocator),
- exception_blocks_(allocator->Adapter(kArenaAllocAssembler)) {}
+ : JNIMacroAssemblerFwd(allocator) {}
virtual ~ArmVIXLJNIMacroAssembler() {}
void FinalizeCode() override;
@@ -186,8 +183,10 @@
void CallFromThread(ThreadOffset32 offset) override;
// Generate code to check if Thread::Current()->exception_ is non-null
- // and branch to a ExceptionSlowPath if it is.
- void ExceptionPoll(size_t stack_adjust) override;
+ // and branch to the `label` if it is.
+ void ExceptionPoll(JNIMacroLabel* label) override;
+ // Deliver pending exception.
+ void DeliverPendingException() override;
// Create a new label that can be used with Jump/Bind calls.
std::unique_ptr<JNIMacroLabel> CreateLabel() override;
@@ -200,31 +199,9 @@
void MemoryBarrier(ManagedRegister scratch) override;
- void EmitExceptionPoll(ArmVIXLJNIMacroAssembler::ArmException *exception);
void Load(ArmManagedRegister dest, vixl32::Register base, int32_t offset, size_t size);
private:
- class ArmException {
- private:
- ArmException(vixl32::Register scratch, size_t stack_adjust)
- : scratch_(scratch), stack_adjust_(stack_adjust) {}
-
- vixl32::Label* Entry() { return &exception_entry_; }
-
- // Register used for passing Thread::Current()->exception_ .
- const vixl32::Register scratch_;
-
- // Stack adjust for ExceptionPool.
- const size_t stack_adjust_;
-
- vixl32::Label exception_entry_;
-
- friend class ArmVIXLJNIMacroAssembler;
- DISALLOW_COPY_AND_ASSIGN(ArmException);
- };
-
- // List of exception blocks to generate at the end of the code cache.
- ArenaVector<std::unique_ptr<ArmVIXLJNIMacroAssembler::ArmException>> exception_blocks_;
// Used for testing.
friend class ArmVIXLAssemblerTest_VixlLoadFromOffset_Test;
friend class ArmVIXLAssemblerTest_VixlStoreToOffset_Test;
diff --git a/compiler/utils/arm64/jni_macro_assembler_arm64.cc b/compiler/utils/arm64/jni_macro_assembler_arm64.cc
index 33fff55..bb16841 100644
--- a/compiler/utils/arm64/jni_macro_assembler_arm64.cc
+++ b/compiler/utils/arm64/jni_macro_assembler_arm64.cc
@@ -45,9 +45,6 @@
}
void Arm64JNIMacroAssembler::FinalizeCode() {
- for (const std::unique_ptr<Arm64Exception>& exception : exception_blocks_) {
- EmitExceptionPoll(exception.get());
- }
___ FinalizeCode();
}
@@ -737,13 +734,24 @@
___ Str(scratch, MEM_OP(reg_x(SP), out_off.Int32Value()));
}
-void Arm64JNIMacroAssembler::ExceptionPoll(size_t stack_adjust) {
- CHECK_ALIGNED(stack_adjust, kStackAlignment);
+void Arm64JNIMacroAssembler::ExceptionPoll(JNIMacroLabel* label) {
UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
Register scratch = temps.AcquireX();
- exception_blocks_.emplace_back(new Arm64Exception(scratch, stack_adjust));
___ Ldr(scratch, MEM_OP(reg_x(TR), Thread::ExceptionOffset<kArm64PointerSize>().Int32Value()));
- ___ Cbnz(scratch, exception_blocks_.back()->Entry());
+ ___ Cbnz(scratch, Arm64JNIMacroLabel::Cast(label)->AsArm64());
+}
+
+void Arm64JNIMacroAssembler::DeliverPendingException() {
+ // Pass exception object as argument.
+ // Don't care about preserving X0 as this won't return.
+ // Note: The scratch register from `ExceptionPoll()` may have been clobbered.
+ ___ Ldr(reg_x(X0), MEM_OP(reg_x(TR), Thread::ExceptionOffset<kArm64PointerSize>().Int32Value()));
+ ___ Ldr(lr,
+ MEM_OP(reg_x(TR),
+ QUICK_ENTRYPOINT_OFFSET(kArm64PointerSize, pDeliverException).Int32Value()));
+ ___ Blr(lr);
+ // Call should never return.
+ ___ Brk();
}
std::unique_ptr<JNIMacroLabel> Arm64JNIMacroAssembler::CreateLabel() {
@@ -792,27 +800,6 @@
___ Bind(Arm64JNIMacroLabel::Cast(label)->AsArm64());
}
-void Arm64JNIMacroAssembler::EmitExceptionPoll(Arm64Exception* exception) {
- UseScratchRegisterScope temps(asm_.GetVIXLAssembler());
- temps.Exclude(exception->scratch_);
-
- // Bind exception poll entry.
- ___ Bind(exception->Entry());
- if (exception->stack_adjust_ != 0) { // Fix up the frame.
- DecreaseFrameSize(exception->stack_adjust_);
- }
- // Pass exception object as argument.
- // Don't care about preserving X0 as this won't return.
- ___ Mov(reg_x(X0), exception->scratch_);
- ___ Ldr(lr,
- MEM_OP(reg_x(TR),
- QUICK_ENTRYPOINT_OFFSET(kArm64PointerSize, pDeliverException).Int32Value()));
-
- ___ Blr(lr);
- // Call should never return.
- ___ Brk();
-}
-
void Arm64JNIMacroAssembler::BuildFrame(size_t frame_size,
ManagedRegister method_reg,
ArrayRef<const ManagedRegister> callee_save_regs) {
diff --git a/compiler/utils/arm64/jni_macro_assembler_arm64.h b/compiler/utils/arm64/jni_macro_assembler_arm64.h
index 2c4b252..363bce9 100644
--- a/compiler/utils/arm64/jni_macro_assembler_arm64.h
+++ b/compiler/utils/arm64/jni_macro_assembler_arm64.h
@@ -43,8 +43,7 @@
class Arm64JNIMacroAssembler final : public JNIMacroAssemblerFwd<Arm64Assembler, PointerSize::k64> {
public:
explicit Arm64JNIMacroAssembler(ArenaAllocator* allocator)
- : JNIMacroAssemblerFwd(allocator),
- exception_blocks_(allocator->Adapter(kArenaAllocAssembler)) {}
+ : JNIMacroAssemblerFwd(allocator) {}
~Arm64JNIMacroAssembler();
@@ -168,8 +167,10 @@
void CallFromThread(ThreadOffset64 offset) override;
// Generate code to check if Thread::Current()->exception_ is non-null
- // and branch to a ExceptionSlowPath if it is.
- void ExceptionPoll(size_t stack_adjust) override;
+ // and branch to the `label` if it is.
+ void ExceptionPoll(JNIMacroLabel* label) override;
+ // Deliver pending exception.
+ void DeliverPendingException() override;
// Create a new label that can be used with Jump/Bind calls.
std::unique_ptr<JNIMacroLabel> CreateLabel() override;
@@ -181,28 +182,6 @@
void Bind(JNIMacroLabel* label) override;
private:
- class Arm64Exception {
- public:
- Arm64Exception(vixl::aarch64::Register scratch, size_t stack_adjust)
- : scratch_(scratch), stack_adjust_(stack_adjust) {}
-
- vixl::aarch64::Label* Entry() { return &exception_entry_; }
-
- // Register used for passing Thread::Current()->exception_ .
- const vixl::aarch64::Register scratch_;
-
- // Stack adjust for ExceptionPool.
- const size_t stack_adjust_;
-
- vixl::aarch64::Label exception_entry_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Arm64Exception);
- };
-
- // Emits Exception block.
- void EmitExceptionPoll(Arm64Exception *exception);
-
void StoreWToOffset(StoreOperandType type,
WRegister source,
XRegister base,
@@ -229,9 +208,6 @@
XRegister rn,
int32_t value,
vixl::aarch64::Condition cond = vixl::aarch64::al);
-
- // List of exception blocks to generate at the end of the code cache.
- ArenaVector<std::unique_ptr<Arm64Exception>> exception_blocks_;
};
class Arm64JNIMacroLabel final
diff --git a/compiler/utils/assembler_thumb_test.cc b/compiler/utils/assembler_thumb_test.cc
index 96f4a6c..83b7eeb 100644
--- a/compiler/utils/assembler_thumb_test.cc
+++ b/compiler/utils/assembler_thumb_test.cc
@@ -177,7 +177,8 @@
__ CreateJObject(method_register, FrameOffset(1025), scratch_register, true);
__ CreateJObject(scratch_register, FrameOffset(1025), scratch_register, true);
- __ ExceptionPoll(0);
+ std::unique_ptr<JNIMacroLabel> exception_slow_path = __ CreateLabel();
+ __ ExceptionPoll(exception_slow_path.get());
// Push the target out of range of branch emitted by ExceptionPoll.
for (int i = 0; i < 64; i++) {
@@ -188,6 +189,9 @@
__ DecreaseFrameSize(32);
__ RemoveFrame(frame_size, callee_save_regs, /* may_suspend= */ true);
+ __ Bind(exception_slow_path.get());
+ __ DeliverPendingException();
+
EmitAndCheck("VixlJniHelpers", VixlJniHelpersResults);
}
diff --git a/compiler/utils/assembler_thumb_test_expected.cc.inc b/compiler/utils/assembler_thumb_test_expected.cc.inc
index 78fd90c..fbbcbde 100644
--- a/compiler/utils/assembler_thumb_test_expected.cc.inc
+++ b/compiler/utils/assembler_thumb_test_expected.cc.inc
@@ -152,9 +152,9 @@
" 218: bd e8 e0 4d pop.w {r5, r6, r7, r8, r10, r11, lr}\n"
" 21c: d9 f8 24 80 ldr.w r8, [r9, #36]\n"
" 220: 70 47 bx lr\n"
- " 222: 60 46 mov r0, r12\n"
- " 224: d9 f8 d0 e2 ldr.w lr, [r9, #720]\n"
- " 228: f0 47 blx lr\n"
+ " 222: d9 f8 8c 00 ldr.w r0, [r9, #140]\n"
+ " 226: d9 f8 d0 e2 ldr.w lr, [r9, #720]\n"
+ " 22a: f0 47 blx lr\n"
};
const char* const VixlLoadFromOffsetResults = {
diff --git a/compiler/utils/jni_macro_assembler.h b/compiler/utils/jni_macro_assembler.h
index a9d9f54..5da70c1 100644
--- a/compiler/utils/jni_macro_assembler.h
+++ b/compiler/utils/jni_macro_assembler.h
@@ -243,8 +243,10 @@
virtual void CallFromThread(ThreadOffset<kPointerSize> offset) = 0;
// Generate code to check if Thread::Current()->exception_ is non-null
- // and branch to a ExceptionSlowPath if it is.
- virtual void ExceptionPoll(size_t stack_adjust) = 0;
+ // and branch to the `label` if it is.
+ virtual void ExceptionPoll(JNIMacroLabel* label) = 0;
+ // Deliver pending exception.
+ virtual void DeliverPendingException() = 0;
// Create a new label that can be used with Jump/Bind calls.
virtual std::unique_ptr<JNIMacroLabel> CreateLabel() = 0;
diff --git a/compiler/utils/x86/jni_macro_assembler_x86.cc b/compiler/utils/x86/jni_macro_assembler_x86.cc
index 3c88447..b08503e 100644
--- a/compiler/utils/x86/jni_macro_assembler_x86.cc
+++ b/compiler/utils/x86/jni_macro_assembler_x86.cc
@@ -30,15 +30,6 @@
return ECX;
}
-// Slowpath entered when Thread::Current()->_exception is non-null
-class X86ExceptionSlowPath final : public SlowPath {
- public:
- explicit X86ExceptionSlowPath(size_t stack_adjust) : stack_adjust_(stack_adjust) {}
- void Emit(Assembler *sp_asm) override;
- private:
- const size_t stack_adjust_;
-};
-
static dwarf::Reg DWARFReg(Register reg) {
return dwarf::Reg::X86Core(static_cast<int>(reg));
}
@@ -572,11 +563,17 @@
__ movl(Address(ESP, offset), scratch);
}
-void X86JNIMacroAssembler::ExceptionPoll(size_t stack_adjust) {
- X86ExceptionSlowPath* slow = new (__ GetAllocator()) X86ExceptionSlowPath(stack_adjust);
- __ GetBuffer()->EnqueueSlowPath(slow);
+void X86JNIMacroAssembler::ExceptionPoll(JNIMacroLabel* label) {
__ fs()->cmpl(Address::Absolute(Thread::ExceptionOffset<kX86PointerSize>()), Immediate(0));
- __ j(kNotEqual, slow->Entry());
+ __ j(kNotEqual, X86JNIMacroLabel::Cast(label)->AsX86());
+}
+
+void X86JNIMacroAssembler::DeliverPendingException() {
+ // Pass exception as argument in EAX
+ __ fs()->movl(EAX, Address::Absolute(Thread::ExceptionOffset<kX86PointerSize>()));
+ __ fs()->call(Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86PointerSize, pDeliverException)));
+ // this call should never return
+ __ int3();
}
std::unique_ptr<JNIMacroLabel> X86JNIMacroAssembler::CreateLabel() {
@@ -618,21 +615,5 @@
#undef __
-void X86ExceptionSlowPath::Emit(Assembler *sasm) {
- X86Assembler* sp_asm = down_cast<X86Assembler*>(sasm);
-#define __ sp_asm->
- __ Bind(&entry_);
- // Note: the return value is dead
- if (stack_adjust_ != 0) { // Fix up the frame.
- DecreaseFrameSizeImpl(sp_asm, stack_adjust_);
- }
- // Pass exception as argument in EAX
- __ fs()->movl(EAX, Address::Absolute(Thread::ExceptionOffset<kX86PointerSize>()));
- __ fs()->call(Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86PointerSize, pDeliverException)));
- // this call should never return
- __ int3();
-#undef __
-}
-
} // namespace x86
} // namespace art
diff --git a/compiler/utils/x86/jni_macro_assembler_x86.h b/compiler/utils/x86/jni_macro_assembler_x86.h
index 1f9355a..1de4eb1 100644
--- a/compiler/utils/x86/jni_macro_assembler_x86.h
+++ b/compiler/utils/x86/jni_macro_assembler_x86.h
@@ -159,8 +159,10 @@
void CallFromThread(ThreadOffset32 offset) override;
// Generate code to check if Thread::Current()->exception_ is non-null
- // and branch to a ExceptionSlowPath if it is.
- void ExceptionPoll(size_t stack_adjust) override;
+ // and branch to the `label` if it is.
+ void ExceptionPoll(JNIMacroLabel* label) override;
+ // Deliver pending exception.
+ void DeliverPendingException() override;
// Create a new label that can be used with Jump/Bind calls.
std::unique_ptr<JNIMacroLabel> CreateLabel() override;
diff --git a/compiler/utils/x86_64/jni_macro_assembler_x86_64.cc b/compiler/utils/x86_64/jni_macro_assembler_x86_64.cc
index d9f05df..b145e97 100644
--- a/compiler/utils/x86_64/jni_macro_assembler_x86_64.cc
+++ b/compiler/utils/x86_64/jni_macro_assembler_x86_64.cc
@@ -642,21 +642,20 @@
__ movq(Address(CpuRegister(RSP), offset), scratch);
}
-// Slowpath entered when Thread::Current()->_exception is non-null
-class X86_64ExceptionSlowPath final : public SlowPath {
- public:
- explicit X86_64ExceptionSlowPath(size_t stack_adjust) : stack_adjust_(stack_adjust) {}
- void Emit(Assembler *sp_asm) override;
- private:
- const size_t stack_adjust_;
-};
-
-void X86_64JNIMacroAssembler::ExceptionPoll(size_t stack_adjust) {
- X86_64ExceptionSlowPath* slow = new (__ GetAllocator()) X86_64ExceptionSlowPath(stack_adjust);
- __ GetBuffer()->EnqueueSlowPath(slow);
+void X86_64JNIMacroAssembler::ExceptionPoll(JNIMacroLabel* label) {
__ gs()->cmpl(Address::Absolute(Thread::ExceptionOffset<kX86_64PointerSize>(), true),
Immediate(0));
- __ j(kNotEqual, slow->Entry());
+ __ j(kNotEqual, X86_64JNIMacroLabel::Cast(label)->AsX86_64());
+}
+
+void X86_64JNIMacroAssembler::DeliverPendingException() {
+ // Pass exception as argument in RDI
+ __ gs()->movq(CpuRegister(RDI),
+ Address::Absolute(Thread::ExceptionOffset<kX86_64PointerSize>(), true));
+ __ gs()->call(
+ Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86_64PointerSize, pDeliverException), true));
+ // this call should never return
+ __ int3();
}
std::unique_ptr<JNIMacroLabel> X86_64JNIMacroAssembler::CreateLabel() {
@@ -699,23 +698,5 @@
#undef __
-void X86_64ExceptionSlowPath::Emit(Assembler *sasm) {
- X86_64Assembler* sp_asm = down_cast<X86_64Assembler*>(sasm);
-#define __ sp_asm->
- __ Bind(&entry_);
- // Note: the return value is dead
- if (stack_adjust_ != 0) { // Fix up the frame.
- DecreaseFrameSizeImpl(stack_adjust_, sp_asm);
- }
- // Pass exception as argument in RDI
- __ gs()->movq(CpuRegister(RDI),
- Address::Absolute(Thread::ExceptionOffset<kX86_64PointerSize>(), true));
- __ gs()->call(
- Address::Absolute(QUICK_ENTRYPOINT_OFFSET(kX86_64PointerSize, pDeliverException), true));
- // this call should never return
- __ int3();
-#undef __
-}
-
} // namespace x86_64
} // namespace art
diff --git a/compiler/utils/x86_64/jni_macro_assembler_x86_64.h b/compiler/utils/x86_64/jni_macro_assembler_x86_64.h
index f1ec74f..0468901 100644
--- a/compiler/utils/x86_64/jni_macro_assembler_x86_64.h
+++ b/compiler/utils/x86_64/jni_macro_assembler_x86_64.h
@@ -179,8 +179,10 @@
void CallFromThread(ThreadOffset64 offset) override;
// Generate code to check if Thread::Current()->exception_ is non-null
- // and branch to a ExceptionSlowPath if it is.
- void ExceptionPoll(size_t stack_adjust) override;
+ // and branch to the `label` if it is.
+ void ExceptionPoll(JNIMacroLabel* label) override;
+ // Deliver pending exception.
+ void DeliverPendingException() override;
// Create a new label that can be used with Jump/Bind calls.
std::unique_ptr<JNIMacroLabel> CreateLabel() override;