From c6ee54e9a9fd67d24c63bd802ef2fe540a4f86a5 Mon Sep 17 00:00:00 2001 From: Andreas Gampe Date: Mon, 24 Mar 2014 16:45:44 -0700 Subject: [PATCH] Trampoline and assembly fixes for ARM64 Trampolines need a jump, not a call. Expose br in the ARM64 assembler to allow this. The resolution trampoline is called with the Quick ABI, and will continue to a Quick ABI function. Then the method pointer must be in x0. Change-Id: I4e383b59d6c40a659d324a7faef3fadf0c890178 --- compiler/trampolines/trampoline_compiler.cc | 6 +++--- compiler/utils/arm64/assembler_arm64.cc | 9 +++++++++ compiler/utils/arm64/assembler_arm64.h | 3 +++ runtime/arch/arm64/quick_entrypoints_arm64.S | 6 ++++-- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/compiler/trampolines/trampoline_compiler.cc b/compiler/trampolines/trampoline_compiler.cc index 4dffef9f0..32980cba7 100644 --- a/compiler/trampolines/trampoline_compiler.cc +++ b/compiler/trampolines/trampoline_compiler.cc @@ -62,7 +62,7 @@ static const std::vector* CreateTrampoline(EntryPointCallingConvention switch (abi) { case kInterpreterAbi: // Thread* is first argument (X0) in interpreter ABI. // FIXME IPx used by VIXL - this is unsafe. - __ Call(Arm64ManagedRegister::FromCoreRegister(X0), Offset(offset.Int32Value()), + __ JumpTo(Arm64ManagedRegister::FromCoreRegister(X0), Offset(offset.Int32Value()), Arm64ManagedRegister::FromCoreRegister(IP1)); break; @@ -73,13 +73,13 @@ static const std::vector* CreateTrampoline(EntryPointCallingConvention Offset(JNIEnvExt::SelfOffset().Int32Value())); // FIXME IPx used by VIXL - this is unsafe. - __ Call(Arm64ManagedRegister::FromCoreRegister(IP1), Offset(offset.Int32Value()), + __ JumpTo(Arm64ManagedRegister::FromCoreRegister(IP1), Offset(offset.Int32Value()), Arm64ManagedRegister::FromCoreRegister(IP0)); break; case kPortableAbi: // X18 holds Thread*. case kQuickAbi: // Fall-through. - __ Call(Arm64ManagedRegister::FromCoreRegister(TR), Offset(offset.Int32Value()), + __ JumpTo(Arm64ManagedRegister::FromCoreRegister(TR), Offset(offset.Int32Value()), Arm64ManagedRegister::FromCoreRegister(IP0)); break; diff --git a/compiler/utils/arm64/assembler_arm64.cc b/compiler/utils/arm64/assembler_arm64.cc index b364ba0f6..00ce92351 100644 --- a/compiler/utils/arm64/assembler_arm64.cc +++ b/compiler/utils/arm64/assembler_arm64.cc @@ -468,6 +468,15 @@ void Arm64Assembler::Call(ManagedRegister m_base, Offset offs, ManagedRegister m ___ Blr(reg_x(scratch.AsCoreRegister())); } +void Arm64Assembler::JumpTo(ManagedRegister m_base, Offset offs, ManagedRegister m_scratch) { + Arm64ManagedRegister base = m_base.AsArm64(); + Arm64ManagedRegister scratch = m_scratch.AsArm64(); + CHECK(base.IsCoreRegister()) << base; + CHECK(scratch.IsCoreRegister()) << scratch; + LoadFromOffset(scratch.AsCoreRegister(), base.AsCoreRegister(), offs.Int32Value()); + ___ Br(reg_x(scratch.AsCoreRegister())); +} + void Arm64Assembler::Call(FrameOffset base, Offset offs, ManagedRegister m_scratch) { Arm64ManagedRegister scratch = m_scratch.AsArm64(); CHECK(scratch.IsCoreRegister()) << scratch; diff --git a/compiler/utils/arm64/assembler_arm64.h b/compiler/utils/arm64/assembler_arm64.h index 2bada3fc9..1c47e7757 100644 --- a/compiler/utils/arm64/assembler_arm64.h +++ b/compiler/utils/arm64/assembler_arm64.h @@ -204,6 +204,9 @@ class Arm64Assembler : public Assembler { void Call(FrameOffset base, Offset offset, ManagedRegister scratch); void Call(ThreadOffset offset, ManagedRegister scratch); + // Jump to address (not setting link register) + void JumpTo(ManagedRegister m_base, Offset offs, ManagedRegister m_scratch); + // Generate code to check if Thread::Current()->exception_ is non-null // and branch to a ExceptionSlowPath if it is. void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust); diff --git a/runtime/arch/arm64/quick_entrypoints_arm64.S b/runtime/arch/arm64/quick_entrypoints_arm64.S index 9db07f81d..447854f29 100644 --- a/runtime/arch/arm64/quick_entrypoints_arm64.S +++ b/runtime/arch/arm64/quick_entrypoints_arm64.S @@ -887,13 +887,15 @@ UNIMPLEMENTED art_quick_imt_conflict_trampoline ENTRY art_quick_resolution_trampoline SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME + mov x19, x0 // save the called method mov x2, xSELF mov x3, sp bl artQuickResolutionTrampoline // (called, receiver, Thread*, SP) - mov x9, x0 // Remember returned code pointer in x9. + mov x9, x0 // Remember returned code pointer in x9. + mov x0, x19 // Restore the method, before x19 is restored to on-call value RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME cbz x9, 1f - br x0 + br x9 1: RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME DELIVER_PENDING_EXCEPTION -- 2.11.0