Ignore:
Timestamp:
May 21, 2009, 7:34:41 PM (16 years ago)
Author:
[email protected]
Message:

2009-05-21 Gavin Barraclough <[email protected]>

Reviewed by Darin Adler.
Addition of MacroAssemblerCodeRef.h rubber stamped by Geoff Garen.

Refactor JIT code-handle objects. The representation of generated code is currently
a bit of a mess. We have a class JITCode which wraps the pointer to a block of
generated code, but this object does not reference the executable pool meaning that
external events (the pool being derefed) could make the pointer become invalid.
To overcome this both the JIT and Yarr implement further (and similar) objects to
wrap the code pointer with a RefPtr to the pool. To add to the mire, as well as the
CodeBlock containing a handle onto the code the FunctionBodyNode also contains a
copy of the code pointer which is used almost (but not entirely) uniquely to access
the JIT code for a function.

Rationalization of all this:

  • Add a new type 'MacroAssembler::CodeRef' as a handle for a block of JIT generated code.
  • Change the JIT & Yarr to internally handle code using CodeRefs.
  • Move the CodeRef (formerly anow defunct JITCodeRef) from CodeBlock to its owner node.
  • Remove the (now) redundant code pointer from FunctionBodyNode.

While tidying this up I've made the PatchBuffer return code in new allocations using a CodeRef,
and have enforced an interface that the PatchBuffer will always be used, and 'finalizeCode()' or
'finalizeCodeAddendum()' will always be called exactly once on the PatchBuffer to complete code generation.

This gives us a potentially useful hook ('PatchBuffer::performFinalization()') at the end of generation,
which may have a number of uses. It may be helpful should we wish to switch our generation
model to allow RW/RX exclusive memory, and it may be useful on non-cache-coherent platforms to
give us an oportunity to cache flush as necessary.

No performance impact.

  • assembler/AbstractMacroAssembler.h: (JSC::AbstractMacroAssembler::ProcessorReturnAddress::relinkCallerToTrampoline): (JSC::AbstractMacroAssembler::CodeRef::CodeRef): (JSC::AbstractMacroAssembler::CodeRef::trampolineAt): (JSC::AbstractMacroAssembler::PatchBuffer::PatchBuffer): (JSC::AbstractMacroAssembler::PatchBuffer::~PatchBuffer): (JSC::AbstractMacroAssembler::PatchBuffer::link): (JSC::AbstractMacroAssembler::PatchBuffer::linkTailRecursive): (JSC::AbstractMacroAssembler::PatchBuffer::patch): (JSC::AbstractMacroAssembler::PatchBuffer::complete): (JSC::AbstractMacroAssembler::PatchBuffer::finalize): (JSC::AbstractMacroAssembler::PatchBuffer::entry):
  • bytecode/CodeBlock.cpp: (JSC::CodeBlock::CodeBlock): (JSC::CodeBlock::reparseForExceptionInfoIfNecessary): (JSC::CodeBlock::setJITCode):
  • bytecode/CodeBlock.h: (JSC::CodeBlock::getBytecodeIndex): (JSC::CodeBlock::executablePool):
  • interpreter/CallFrameClosure.h:
  • interpreter/Interpreter.cpp: (JSC::Interpreter::execute): (JSC::Interpreter::prepareForRepeatCall):
  • jit/JIT.cpp: (JSC::JIT::privateCompile): (JSC::JIT::privateCompileCTIMachineTrampolines): (JSC::JIT::linkCall):
  • jit/JIT.h:
  • jit/JITCode.h: (JSC::JITCode::JITCode): (JSC::JITCode::operator bool): (JSC::JITCode::addressForCall): (JSC::JITCode::offsetOf): (JSC::JITCode::execute): (JSC::JITCode::size): (JSC::JITCode::executablePool): (JSC::JITCode::HostFunction):
  • jit/JITPropertyAccess.cpp: (JSC::JIT::privateCompilePutByIdTransition): (JSC::JIT::privateCompilePatchGetArrayLength): (JSC::JIT::privateCompileGetByIdProto): (JSC::JIT::privateCompileGetByIdSelfList): (JSC::JIT::privateCompileGetByIdProtoList): (JSC::JIT::privateCompileGetByIdChainList): (JSC::JIT::privateCompileGetByIdChain):
  • jit/JITStubs.cpp: (JSC::JITStubs::cti_vm_dontLazyLinkCall): (JSC::JITStubs::cti_vm_lazyLinkCall):
  • parser/Nodes.cpp: (JSC::ProgramNode::generateJITCode): (JSC::EvalNode::generateJITCode): (JSC::FunctionBodyNode::FunctionBodyNode): (JSC::FunctionBodyNode::createNativeThunk): (JSC::FunctionBodyNode::generateJITCode):
  • parser/Nodes.h: (JSC::ScopeNode::generatedJITCode): (JSC::ScopeNode::getExecutablePool): (JSC::ScopeNode::setJITCode): (JSC::ProgramNode::jitCode): (JSC::EvalNode::jitCode): (JSC::FunctionBodyNode::jitCode):
  • runtime/RegExp.cpp: (JSC::RegExp::match):
  • yarr/RegexJIT.cpp: (JSC::Yarr::RegexGenerator::compile): (JSC::Yarr::jitCompileRegex): (JSC::Yarr::executeRegex):
  • yarr/RegexJIT.h: (JSC::Yarr::RegexCodeBlock::RegexCodeBlock): (JSC::Yarr::RegexCodeBlock::pcreFallback): (JSC::Yarr::RegexCodeBlock::setFallback): (JSC::Yarr::RegexCodeBlock::operator bool): (JSC::Yarr::RegexCodeBlock::set): (JSC::Yarr::RegexCodeBlock::execute):
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/assembler/AbstractMacroAssembler.h

    r43839 r44030  
    2929#include <wtf/Platform.h>
    3030
     31#include <MacroAssemblerCodeRef.h>
     32#include <wtf/Noncopyable.h>
     33#include <wtf/UnusedParam.h>
     34
    3135#if ENABLE(ASSEMBLER)
    3236
     
    3640class AbstractMacroAssembler {
    3741public:
     42    typedef MacroAssemblerCodeRef CodeRef;
     43
    3844    class Jump;
    3945    class PatchBuffer;
     
    4450    class CodeLocationDataLabel32;
    4551    class CodeLocationDataLabelPtr;
     52    class ProcessorReturnAddress;
    4653
    4754    typedef typename AssemblerType::RegisterID RegisterID;
     
    195202    // it may be used as a destination for a jump.
    196203    class Label {
     204        template<class TemplateAssemblerType>
     205        friend class AbstractMacroAssembler;
    197206        friend class Jump;
    198         template<class AssemblerType_T>
    199         friend class AbstractMacroAssembler;
    200         friend class PatchBuffer;
     207        friend class MacroAssemblerCodeRef;
     208        friend class PatchBuffer;
     209
    201210    public:
    202211        Label()
     
    220229    // patched after the code has been generated.
    221230    class DataLabelPtr {
    222         template<class AssemblerType_T>
     231        template<class TemplateAssemblerType>
    223232        friend class AbstractMacroAssembler;
    224233        friend class PatchBuffer;
     
    242251    // patched after the code has been generated.
    243252    class DataLabel32 {
    244         template<class AssemblerType_T>
     253        template<class TemplateAssemblerType>
    245254        friend class AbstractMacroAssembler;
    246255        friend class PatchBuffer;
     
    266275    // destination.
    267276    class Call {
    268         friend class PatchBuffer;
    269         template<class AssemblerType_T>
     277        template<class TemplateAssemblerType>
    270278        friend class AbstractMacroAssembler;
     279        friend class PatchBuffer;
    271280    public:
    272281        enum Flags {
     
    310319    // destination.
    311320    class Jump {
    312         friend class PatchBuffer;
    313         template<class AssemblerType_T>
     321        template<class TemplateAssemblerType>
    314322        friend class AbstractMacroAssembler;
    315323        friend class Call;
     324        friend class PatchBuffer;
    316325    public:
    317326        Jump()
     
    456465        friend class CodeLocationJump;
    457466        friend class PatchBuffer;
     467        friend class ProcessorReturnAddress;
     468
    458469    public:
    459470        CodeLocationLabel()
     
    615626        }
    616627
     628        void relinkCallerToTrampoline(CodeLocationLabel label)
     629        {
     630            AssemblerType::patchMacroAssemblerCall(reinterpret_cast<intptr_t>(this->m_location), label.getJumpDestination());
     631        }
     632       
    617633        template<typename FunctionSig>
    618634        void relinkCallerToFunction(FunctionSig* newCalleeFunction)
     
    637653
    638654
    639     // Section 4: The patch buffer - utility to finalize code generation.
    640 
     655    // Section 4: PatchBuffer - utility to finalize code generation.
     656
     657    static void* trampolineAt(CodeRef ref, Label label)
     658    {
     659        return AssemblerType::getRelocatedAddress(ref.m_code, label.m_label);
     660    }
    641661
    642662    // PatchBuffer:
     
    657677    // address of calls, as opposed to a point that can be used to later relink a Jump -
    658678    // possibly wrap the later up in an object that can do just that).
    659     class PatchBuffer {
    660     public:
    661         PatchBuffer(void* code)
    662             : m_code(code)
    663         {
    664         }
    665 
    666         CodeLocationLabel entry()
    667         {
    668             return CodeLocationLabel(m_code);
    669         }
    670 
    671         void* trampolineAt(Label label)
    672         {
    673             return AssemblerType::getRelocatedAddress(m_code, label.m_label);
    674         }
    675        
     679    class PatchBuffer : public Noncopyable {
     680    public:
     681        PatchBuffer(AbstractMacroAssembler<AssemblerType>* masm, PassRefPtr<ExecutablePool> executablePool)
     682            : m_ref(0, executablePool, masm->m_assembler.size())
     683#ifndef NDEBUG
     684            , m_completed(false)
     685#endif
     686        {
     687            m_ref.m_code = masm->m_assembler.executableCopy(m_ref.m_executablePool.get());
     688        }
     689
     690#ifndef NDEBUG
     691        ~PatchBuffer()
     692        {
     693            ASSERT(m_completed);
     694        }
     695#endif
     696
    676697        // These methods are used to link or set values at code generation time.
    677698
     
    681702            ASSERT(call.isFlagSet(Call::Linkable));
    682703#if PLATFORM(X86_64)
    683             if (call.isFlagSet(Call::Near)) {
    684                 AssemblerType::linkCall(m_code, call.m_jmp, reinterpret_cast<void*>(function));
    685             } else {
    686                 intptr_t callLocation = reinterpret_cast<intptr_t>(AssemblerType::getRelocatedAddress(m_code, call.m_jmp));
     704            if (call.isFlagSet(Call::Near))
     705                AssemblerType::linkCall(code(), call.m_jmp, reinterpret_cast<void*>(function));
     706            else {
     707                intptr_t callLocation = reinterpret_cast<intptr_t>(AssemblerType::getRelocatedAddress(code(), call.m_jmp));
    687708                AssemblerType::patchMacroAssemblerCall(callLocation, reinterpret_cast<void*>(function));
    688709            }
    689710#else
    690             AssemblerType::linkCall(m_code, call.m_jmp, reinterpret_cast<void*>(function));
     711            AssemblerType::linkCall(code(), call.m_jmp, reinterpret_cast<void*>(function));
    691712#endif
    692713        }
     
    695716        void linkTailRecursive(Jump jump, FunctionSig* function)
    696717        {
    697             AssemblerType::linkJump(m_code, jump.m_jmp, reinterpret_cast<void*>(function));
     718            AssemblerType::linkJump(code(), jump.m_jmp, reinterpret_cast<void*>(function));
    698719        }
    699720
     
    701722        void linkTailRecursive(JumpList list, FunctionSig* function)
    702723        {
    703             for (unsigned i = 0; i < list.m_jumps.size(); ++i) {
    704                 AssemblerType::linkJump(m_code, list.m_jumps[i].m_jmp, reinterpret_cast<void*>(function));
    705             }
     724            for (unsigned i = 0; i < list.m_jumps.size(); ++i)
     725                AssemblerType::linkJump(code(), list.m_jumps[i].m_jmp, reinterpret_cast<void*>(function));
    706726        }
    707727
    708728        void link(Jump jump, CodeLocationLabel label)
    709729        {
    710             AssemblerType::linkJump(m_code, jump.m_jmp, label.m_location);
     730            AssemblerType::linkJump(code(), jump.m_jmp, label.m_location);
    711731        }
    712732
     
    714734        {
    715735            for (unsigned i = 0; i < list.m_jumps.size(); ++i)
    716                 AssemblerType::linkJump(m_code, list.m_jumps[i].m_jmp, label.m_location);
     736                AssemblerType::linkJump(code(), list.m_jumps[i].m_jmp, label.m_location);
    717737        }
    718738
    719739        void patch(DataLabelPtr label, void* value)
    720740        {
    721             AssemblerType::patchAddress(m_code, label.m_label, value);
     741            AssemblerType::patchAddress(code(), label.m_label, value);
     742        }
     743
     744        void patch(DataLabelPtr label, CodeLocationLabel value)
     745        {
     746            AssemblerType::patchAddress(code(), label.m_label, value.getJumpDestination());
    722747        }
    723748
     
    728753            ASSERT(call.isFlagSet(Call::Linkable));
    729754            ASSERT(!call.isFlagSet(Call::Near));
    730             return CodeLocationCall(AssemblerType::getRelocatedAddress(m_code, call.m_jmp));
     755            return CodeLocationCall(AssemblerType::getRelocatedAddress(code(), call.m_jmp));
    731756        }
    732757
     
    735760            ASSERT(call.isFlagSet(Call::Linkable));
    736761            ASSERT(call.isFlagSet(Call::Near));
    737             return CodeLocationNearCall(AssemblerType::getRelocatedAddress(m_code, call.m_jmp));
     762            return CodeLocationNearCall(AssemblerType::getRelocatedAddress(code(), call.m_jmp));
    738763        }
    739764
    740765        CodeLocationLabel locationOf(Label label)
    741766        {
    742             return CodeLocationLabel(AssemblerType::getRelocatedAddress(m_code, label.m_label));
     767            return CodeLocationLabel(AssemblerType::getRelocatedAddress(code(), label.m_label));
    743768        }
    744769
    745770        CodeLocationDataLabelPtr locationOf(DataLabelPtr label)
    746771        {
    747             return CodeLocationDataLabelPtr(AssemblerType::getRelocatedAddress(m_code, label.m_label));
     772            return CodeLocationDataLabelPtr(AssemblerType::getRelocatedAddress(code(), label.m_label));
    748773        }
    749774
    750775        CodeLocationDataLabel32 locationOf(DataLabel32 label)
    751776        {
    752             return CodeLocationDataLabel32(AssemblerType::getRelocatedAddress(m_code, label.m_label));
     777            return CodeLocationDataLabel32(AssemblerType::getRelocatedAddress(code(), label.m_label));
    753778        }
    754779
     
    760785        }
    761786
    762     private:
    763         void* m_code;
     787        // Upon completion of all patching either 'finalizeCode()' or 'finalizeCodeAddendum()' should be called
     788        // once to complete generation of the code.  'finalizeCode()' is suited to situations
     789        // where the executable pool must also be retained, the lighter-weight 'finalizeCodeAddendum()' is
     790        // suited to adding to an existing allocation.
     791        CodeRef finalizeCode()
     792        {
     793            performFinalization();
     794
     795            return m_ref;
     796        }
     797        CodeLocationLabel finalizeCodeAddendum()
     798        {
     799            performFinalization();
     800
     801            return CodeLocationLabel(code());
     802        }
     803
     804    private:
     805        // Keep this private! - the underlying code should only be obtained externally via
     806        // finalizeCode() or finalizeCodeAddendum().
     807        void* code()
     808        {
     809            return m_ref.m_code;
     810        }
     811
     812        void performFinalization()
     813        {
     814#ifndef NDEBUG
     815            ASSERT(!m_completed);
     816            m_completed = true;
     817#endif
     818        }
     819
     820        CodeRef m_ref;
     821#ifndef NDEBUG
     822        bool m_completed;
     823#endif
    764824    };
    765825
     
    770830    {
    771831        return m_assembler.size();
    772     }
    773 
    774     void* copyCode(ExecutablePool* allocator)
    775     {
    776         return m_assembler.executableCopy(allocator);
    777832    }
    778833
Note: See TracChangeset for help on using the changeset viewer.