diff options
Diffstat (limited to 'src/3rdparty/webkit/JavaScriptCore/assembler/AbstractMacroAssembler.h')
-rw-r--r-- | src/3rdparty/webkit/JavaScriptCore/assembler/AbstractMacroAssembler.h | 322 |
1 files changed, 71 insertions, 251 deletions
diff --git a/src/3rdparty/webkit/JavaScriptCore/assembler/AbstractMacroAssembler.h b/src/3rdparty/webkit/JavaScriptCore/assembler/AbstractMacroAssembler.h index cf94677..95b5afc 100644 --- a/src/3rdparty/webkit/JavaScriptCore/assembler/AbstractMacroAssembler.h +++ b/src/3rdparty/webkit/JavaScriptCore/assembler/AbstractMacroAssembler.h @@ -35,22 +35,20 @@ #if ENABLE(ASSEMBLER) -// FIXME: keep transitioning this out into MacroAssemblerX86_64. -#if PLATFORM(X86_64) -#define REPTACH_OFFSET_CALL_R11 3 -#endif - namespace JSC { +class LinkBuffer; +class RepatchBuffer; + template <class AssemblerType> class AbstractMacroAssembler { public: + typedef AssemblerType AssemblerType_T; + typedef MacroAssemblerCodePtr CodePtr; typedef MacroAssemblerCodeRef CodeRef; class Jump; - class LinkBuffer; - class RepatchBuffer; typedef typename AssemblerType::RegisterID RegisterID; typedef typename AssemblerType::FPRegisterID FPRegisterID; @@ -292,7 +290,7 @@ public: class Call { template<class TemplateAssemblerType> friend class AbstractMacroAssembler; - friend class LinkBuffer; + public: enum Flags { None = 0x0, @@ -322,8 +320,13 @@ public: return Call(jump.m_jmp, Linkable); } - private: + void enableLatePatch() + { + m_jmp.enableLatePatch(); + } + JmpSrc m_jmp; + private: Flags m_flags; }; @@ -358,6 +361,11 @@ public: masm->m_assembler.linkJump(m_jmp, label.m_label); } + void enableLatePatch() + { + m_jmp.enableLatePatch(); + } + private: JmpSrc m_jmp; }; @@ -406,254 +414,13 @@ public: }; - // Section 3: LinkBuffer - utility to finalize code generation. + // Section 3: Misc admin methods static CodePtr trampolineAt(CodeRef ref, Label label) { return CodePtr(AssemblerType::getRelocatedAddress(ref.m_code.dataLocation(), label.m_label)); } - // LinkBuffer: - // - // This class assists in linking code generated by the macro assembler, once code generation - // has been completed, and the code has been copied to is final location in memory. At this - // time pointers to labels within the code may be resolved, and relative offsets to external - // addresses may be fixed. - // - // Specifically: - // * Jump objects may be linked to external targets, - // * The address of Jump objects may taken, such that it can later be relinked. - // * The return address of a Jump object representing a call may be acquired. - // * The address of a Label pointing into the code may be resolved. - // * The value referenced by a DataLabel may be fixed. - // - // FIXME: distinguish between Calls & Jumps (make a specific call to obtain the return - // address of calls, as opposed to a point that can be used to later relink a Jump - - // possibly wrap the later up in an object that can do just that). - class LinkBuffer : public Noncopyable { - public: - // Note: Initialization sequence is significant, since executablePool is a PassRefPtr. - // First, executablePool is copied into m_executablePool, then the initialization of - // m_code uses m_executablePool, *not* executablePool, since this is no longer valid. - LinkBuffer(AbstractMacroAssembler<AssemblerType>* masm, PassRefPtr<ExecutablePool> executablePool) - : m_executablePool(executablePool) - , m_code(masm->m_assembler.executableCopy(m_executablePool.get())) - , m_size(masm->m_assembler.size()) -#ifndef NDEBUG - , m_completed(false) -#endif - { - } - - ~LinkBuffer() - { - ASSERT(m_completed); - } - - // These methods are used to link or set values at code generation time. - - void link(Call call, FunctionPtr function) - { - ASSERT(call.isFlagSet(Call::Linkable)); -#if PLATFORM(X86_64) - if (!call.isFlagSet(Call::Near)) { - char* callLocation = reinterpret_cast<char*>(AssemblerType::getRelocatedAddress(code(), call.m_jmp)) - REPTACH_OFFSET_CALL_R11; - AssemblerType::patchPointerForCall(callLocation, function.value()); - } else -#endif - AssemblerType::linkCall(code(), call.m_jmp, function.value()); - } - - void link(Jump jump, CodeLocationLabel label) - { - AssemblerType::linkJump(code(), jump.m_jmp, label.dataLocation()); - } - - void link(JumpList list, CodeLocationLabel label) - { - for (unsigned i = 0; i < list.m_jumps.size(); ++i) - AssemblerType::linkJump(code(), list.m_jumps[i].m_jmp, label.dataLocation()); - } - - void patch(DataLabelPtr label, void* value) - { - AssemblerType::patchPointer(code(), label.m_label, value); - } - - void patch(DataLabelPtr label, CodeLocationLabel value) - { - AssemblerType::patchPointer(code(), label.m_label, value.executableAddress()); - } - - // These methods are used to obtain handles to allow the code to be relinked / repatched later. - - CodeLocationCall locationOf(Call call) - { - ASSERT(call.isFlagSet(Call::Linkable)); - ASSERT(!call.isFlagSet(Call::Near)); - return CodeLocationCall(AssemblerType::getRelocatedAddress(code(), call.m_jmp)); - } - - CodeLocationNearCall locationOfNearCall(Call call) - { - ASSERT(call.isFlagSet(Call::Linkable)); - ASSERT(call.isFlagSet(Call::Near)); - return CodeLocationNearCall(AssemblerType::getRelocatedAddress(code(), call.m_jmp)); - } - - CodeLocationLabel locationOf(Label label) - { - return CodeLocationLabel(AssemblerType::getRelocatedAddress(code(), label.m_label)); - } - - CodeLocationDataLabelPtr locationOf(DataLabelPtr label) - { - return CodeLocationDataLabelPtr(AssemblerType::getRelocatedAddress(code(), label.m_label)); - } - - CodeLocationDataLabel32 locationOf(DataLabel32 label) - { - return CodeLocationDataLabel32(AssemblerType::getRelocatedAddress(code(), label.m_label)); - } - - // This method obtains the return address of the call, given as an offset from - // the start of the code. - unsigned returnAddressOffset(Call call) - { - return AssemblerType::getCallReturnOffset(call.m_jmp); - } - - // Upon completion of all patching either 'finalizeCode()' or 'finalizeCodeAddendum()' should be called - // once to complete generation of the code. 'finalizeCode()' is suited to situations - // where the executable pool must also be retained, the lighter-weight 'finalizeCodeAddendum()' is - // suited to adding to an existing allocation. - CodeRef finalizeCode() - { - performFinalization(); - - return CodeRef(m_code, m_executablePool, m_size); - } - CodeLocationLabel finalizeCodeAddendum() - { - performFinalization(); - - return CodeLocationLabel(code()); - } - - private: - // Keep this private! - the underlying code should only be obtained externally via - // finalizeCode() or finalizeCodeAddendum(). - void* code() - { - return m_code; - } - - void performFinalization() - { -#ifndef NDEBUG - ASSERT(!m_completed); - m_completed = true; -#endif - - ExecutableAllocator::makeExecutable(code(), m_size); - } - - RefPtr<ExecutablePool> m_executablePool; - void* m_code; - size_t m_size; -#ifndef NDEBUG - bool m_completed; -#endif - }; - - class RepatchBuffer { - public: - RepatchBuffer() - { - } - - void relink(CodeLocationJump jump, CodeLocationLabel destination) - { - AssemblerType::relinkJump(jump.dataLocation(), destination.dataLocation()); - } - - void relink(CodeLocationCall call, CodeLocationLabel destination) - { -#if PLATFORM(X86_64) - repatch(call.dataLabelPtrAtOffset(-REPTACH_OFFSET_CALL_R11), destination.executableAddress()); -#else - AssemblerType::relinkCall(call.dataLocation(), destination.executableAddress()); -#endif - } - - void relink(CodeLocationCall call, FunctionPtr destination) - { -#if PLATFORM(X86_64) - repatch(call.dataLabelPtrAtOffset(-REPTACH_OFFSET_CALL_R11), destination.executableAddress()); -#else - AssemblerType::relinkCall(call.dataLocation(), destination.executableAddress()); -#endif - } - - void relink(CodeLocationNearCall nearCall, CodePtr destination) - { - AssemblerType::relinkCall(nearCall.dataLocation(), destination.executableAddress()); - } - - void relink(CodeLocationNearCall nearCall, CodeLocationLabel destination) - { - AssemblerType::relinkCall(nearCall.dataLocation(), destination.executableAddress()); - } - - void relink(CodeLocationNearCall nearCall, FunctionPtr destination) - { - AssemblerType::relinkCall(nearCall.dataLocation(), destination.executableAddress()); - } - - void repatch(CodeLocationDataLabel32 dataLabel32, int32_t value) - { - AssemblerType::repatchInt32(dataLabel32.dataLocation(), value); - } - - void repatch(CodeLocationDataLabelPtr dataLabelPtr, void* value) - { - AssemblerType::repatchPointer(dataLabelPtr.dataLocation(), value); - } - - void relinkCallerToTrampoline(ReturnAddressPtr returnAddress, CodeLocationLabel label) - { - relink(CodeLocationCall(CodePtr(returnAddress)), label); - } - - void relinkCallerToTrampoline(ReturnAddressPtr returnAddress, CodePtr newCalleeFunction) - { - relinkCallerToTrampoline(returnAddress, CodeLocationLabel(newCalleeFunction)); - } - - void relinkCallerToFunction(ReturnAddressPtr returnAddress, FunctionPtr function) - { - relink(CodeLocationCall(CodePtr(returnAddress)), function); - } - - void relinkNearCallerToTrampoline(ReturnAddressPtr returnAddress, CodeLocationLabel label) - { - relink(CodeLocationNearCall(CodePtr(returnAddress)), label); - } - - void relinkNearCallerToTrampoline(ReturnAddressPtr returnAddress, CodePtr newCalleeFunction) - { - relinkNearCallerToTrampoline(returnAddress, CodeLocationLabel(newCalleeFunction)); - } - - void repatchLoadPtrToLEA(CodeLocationInstruction instruction) - { - AssemblerType::repatchLoadPtrToLEA(instruction.dataLocation()); - } - }; - - - // Section 4: Misc admin methods - size_t size() { return m_assembler.size(); @@ -712,6 +479,59 @@ public: protected: AssemblerType m_assembler; + + friend class LinkBuffer; + friend class RepatchBuffer; + + static void linkJump(void* code, Jump jump, CodeLocationLabel target) + { + AssemblerType::linkJump(code, jump.m_jmp, target.dataLocation()); + } + + static void linkPointer(void* code, typename AssemblerType::JmpDst label, void* value) + { + AssemblerType::linkPointer(code, label, value); + } + + static void* getLinkerAddress(void* code, typename AssemblerType::JmpSrc label) + { + return AssemblerType::getRelocatedAddress(code, label); + } + + static void* getLinkerAddress(void* code, typename AssemblerType::JmpDst label) + { + return AssemblerType::getRelocatedAddress(code, label); + } + + static unsigned getLinkerCallReturnOffset(Call call) + { + return AssemblerType::getCallReturnOffset(call.m_jmp); + } + + static void repatchJump(CodeLocationJump jump, CodeLocationLabel destination) + { + AssemblerType::relinkJump(jump.dataLocation(), destination.dataLocation()); + } + + static void repatchNearCall(CodeLocationNearCall nearCall, CodeLocationLabel destination) + { + AssemblerType::relinkCall(nearCall.dataLocation(), destination.executableAddress()); + } + + static void repatchInt32(CodeLocationDataLabel32 dataLabel32, int32_t value) + { + AssemblerType::repatchInt32(dataLabel32.dataLocation(), value); + } + + static void repatchPointer(CodeLocationDataLabelPtr dataLabelPtr, void* value) + { + AssemblerType::repatchPointer(dataLabelPtr.dataLocation(), value); + } + + static void repatchLoadPtrToLEA(CodeLocationInstruction instruction) + { + AssemblerType::repatchLoadPtrToLEA(instruction.dataLocation()); + } }; } // namespace JSC |