Changeset 40846 in webkit for trunk/JavaScriptCore/assembler


Ignore:
Timestamp:
Feb 10, 2009, 8:57:08 PM (16 years ago)
Author:
[email protected]
Message:

2009-02-10 Gavin Barraclough <[email protected]>

Reviewed by Oliver Hunt.

Reduce use of void* / reinterpret_cast in JIT repatching code,
add strong types for Calls and for the various types of pointers
we retain into the JIT generated instruction stream.

No performance impact.

  • assembler/AbstractMacroAssembler.h: (JSC::AbstractMacroAssembler::ImmPtr::ImmPtr): (JSC::AbstractMacroAssembler::ImmPtr::asIntptr): (JSC::AbstractMacroAssembler::Imm32::Imm32): (JSC::AbstractMacroAssembler::Label::Label): (JSC::AbstractMacroAssembler::DataLabelPtr::DataLabelPtr): (JSC::AbstractMacroAssembler::Call::Call): (JSC::AbstractMacroAssembler::Call::link): (JSC::AbstractMacroAssembler::Call::linkTo): (JSC::AbstractMacroAssembler::Jump::Jump): (JSC::AbstractMacroAssembler::Jump::linkTo): (JSC::AbstractMacroAssembler::CodeLocationCommon::CodeLocationCommon): (JSC::AbstractMacroAssembler::CodeLocationCommon::operator bool): (JSC::AbstractMacroAssembler::CodeLocationCommon::reset): (JSC::AbstractMacroAssembler::CodeLocationLabel::CodeLocationLabel): (JSC::AbstractMacroAssembler::CodeLocationLabel::addressForSwitch): (JSC::AbstractMacroAssembler::CodeLocationLabel::addressForExceptionHandler): (JSC::AbstractMacroAssembler::CodeLocationLabel::addressForJSR): (JSC::AbstractMacroAssembler::CodeLocationLabel::getJumpDestination): (JSC::AbstractMacroAssembler::CodeLocationJump::CodeLocationJump): (JSC::AbstractMacroAssembler::CodeLocationJump::relink): (JSC::AbstractMacroAssembler::CodeLocationCall::CodeLocationCall): (JSC::AbstractMacroAssembler::CodeLocationCall::relink): (JSC::AbstractMacroAssembler::CodeLocationCall::calleeReturnAddressValue): (JSC::AbstractMacroAssembler::CodeLocationDataLabel32::CodeLocationDataLabel32): (JSC::AbstractMacroAssembler::CodeLocationDataLabel32::repatch): (JSC::AbstractMacroAssembler::CodeLocationDataLabelPtr::CodeLocationDataLabelPtr): (JSC::AbstractMacroAssembler::CodeLocationDataLabelPtr::repatch): (JSC::AbstractMacroAssembler::ProcessorReturnAddress::ProcessorReturnAddress): (JSC::AbstractMacroAssembler::ProcessorReturnAddress::relinkCallerToFunction): (JSC::AbstractMacroAssembler::ProcessorReturnAddress::operator void*): (JSC::AbstractMacroAssembler::PatchBuffer::entry): (JSC::AbstractMacroAssembler::PatchBuffer::trampolineAt): (JSC::AbstractMacroAssembler::PatchBuffer::link): (JSC::AbstractMacroAssembler::PatchBuffer::linkTailRecursive): (JSC::AbstractMacroAssembler::PatchBuffer::patch): (JSC::AbstractMacroAssembler::PatchBuffer::locationOf): (JSC::AbstractMacroAssembler::PatchBuffer::returnAddressOffset): (JSC::AbstractMacroAssembler::differenceBetween): (JSC::::CodeLocationCommon::labelAtOffset): (JSC::::CodeLocationCommon::jumpAtOffset): (JSC::::CodeLocationCommon::callAtOffset): (JSC::::CodeLocationCommon::dataLabelPtrAtOffset): (JSC::::CodeLocationCommon::dataLabel32AtOffset):
  • assembler/MacroAssemblerX86Common.h: (JSC::MacroAssemblerX86Common::call):
  • assembler/X86Assembler.h: (JSC::X86Assembler::getCallReturnOffset):
  • bytecode/CodeBlock.h: (JSC::CallLinkInfo::CallLinkInfo): (JSC::getStructureStubInfoReturnLocation): (JSC::getCallLinkInfoReturnLocation):
  • bytecode/Instruction.h: (JSC::PolymorphicAccessStructureList::PolymorphicStubInfo::set): (JSC::PolymorphicAccessStructureList::PolymorphicAccessStructureList):
  • bytecode/JumpTable.h: (JSC::StringJumpTable::ctiForValue): (JSC::SimpleJumpTable::ctiForValue):
  • bytecode/StructureStubInfo.h: (JSC::StructureStubInfo::StructureStubInfo):
  • bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::emitCatch): (JSC::prepareJumpTableForStringSwitch):
  • interpreter/Interpreter.cpp: (JSC::Interpreter::cti_op_get_by_id_self_fail): (JSC::getPolymorphicAccessStructureListSlot): (JSC::Interpreter::cti_op_throw): (JSC::Interpreter::cti_op_switch_imm): (JSC::Interpreter::cti_op_switch_char): (JSC::Interpreter::cti_op_switch_string): (JSC::Interpreter::cti_vm_throw):
  • jit/JIT.cpp: (JSC::ctiSetReturnAddress): (JSC::ctiPatchCallByReturnAddress): (JSC::JIT::privateCompile): (JSC::JIT::privateCompileCTIMachineTrampolines):
  • jit/JIT.h: (JSC::CallRecord::CallRecord): (JSC::JIT::compileGetByIdSelf): (JSC::JIT::compileGetByIdProto): (JSC::JIT::compileGetByIdChain): (JSC::JIT::compilePutByIdReplace): (JSC::JIT::compilePutByIdTransition): (JSC::JIT::compilePatchGetArrayLength): (JSC::JIT::emitCTICall):
  • jit/JITCall.cpp: (JSC::JIT::unlinkCall): (JSC::JIT::linkCall):
  • jit/JITInlineMethods.h: (JSC::JIT::emitNakedCall): (JSC::JIT::emitCTICall_internal):
  • jit/JITPropertyAccess.cpp: (JSC::JIT::compileGetByIdSlowCase): (JSC::JIT::compilePutByIdSlowCase): (JSC::JIT::privateCompilePutByIdTransition): (JSC::JIT::patchGetByIdSelf): (JSC::JIT::patchPutByIdReplace): (JSC::JIT::privateCompilePatchGetArrayLength): (JSC::JIT::privateCompileGetByIdSelf): (JSC::JIT::privateCompileGetByIdProto): (JSC::JIT::privateCompileGetByIdSelfList): (JSC::JIT::privateCompileGetByIdProtoList): (JSC::JIT::privateCompileGetByIdChainList): (JSC::JIT::privateCompileGetByIdChain): (JSC::JIT::privateCompilePutByIdReplace):
Location:
trunk/JavaScriptCore/assembler
Files:
3 edited

Legend:

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

    r40813 r40846  
    3535template <class AssemblerType>
    3636class AbstractMacroAssembler {
    37 protected:
    38     AssemblerType m_assembler;
    39 
    4037public:
     38    class Jump;
     39    class PatchBuffer;
     40    class CodeLocationLabel;
     41    class CodeLocationJump;
     42    class CodeLocationCall;
     43    class CodeLocationDataLabel32;
     44    class CodeLocationDataLabelPtr;
     45
    4146    typedef typename AssemblerType::RegisterID RegisterID;
    4247    typedef typename AssemblerType::JmpSrc JmpSrc;
    4348    typedef typename AssemblerType::JmpDst JmpDst;
     49
     50
     51    // Section 1: MacroAssembler operand types
     52    //
     53    // The following types are used as operands to MacroAssembler operations,
     54    // describing immediate  and memory operands to the instructions to be planted.
     55
    4456
    4557    enum Scale {
     
    126138    };
    127139
    128 
    129     class Jump;
    130     class PatchBuffer;
    131 
    132     // DataLabelPtr:
    133     //
    134     // A DataLabelPtr is used to refer to a location in the code containing a pointer to be
    135     // patched after the code has been generated.
    136     class DataLabelPtr {
    137         template<class AssemblerType_T>
    138         friend class AbstractMacroAssembler;
    139         friend class PatchBuffer;
    140 
    141     public:
    142         DataLabelPtr()
    143         {
    144         }
    145 
    146         DataLabelPtr(AbstractMacroAssembler<AssemblerType>* masm)
    147             : m_label(masm->m_assembler.label())
    148         {
    149         }
    150 
    151         static void patch(void* address, void* value)
    152         {
    153             AssemblerType::patchPointer(reinterpret_cast<intptr_t>(address), reinterpret_cast<intptr_t>(value));
    154         }
    155        
    156     private:
    157         JmpDst m_label;
    158     };
    159 
    160     // DataLabel32:
    161     //
    162     // A DataLabelPtr is used to refer to a location in the code containing a pointer to be
    163     // patched after the code has been generated.
    164     class DataLabel32 {
    165         template<class AssemblerType_T>
    166         friend class AbstractMacroAssembler;
    167         friend class PatchBuffer;
    168 
    169     public:
    170         DataLabel32()
    171         {
    172         }
    173 
    174         DataLabel32(AbstractMacroAssembler<AssemblerType>* masm)
    175             : m_label(masm->m_assembler.label())
    176         {
    177         }
    178 
    179         static void patch(void* address, int32_t value)
    180         {
    181             AssemblerType::patchImmediate(reinterpret_cast<intptr_t>(address), value);
    182         }
    183 
    184     private:
    185         JmpDst m_label;
    186     };
    187 
    188     // Label:
    189     //
    190     // A Label records a point in the generated instruction stream, typically such that
    191     // it may be used as a destination for a jump.
    192     class Label {
    193         friend class Jump;
    194         template<class AssemblerType_T>
    195         friend class AbstractMacroAssembler;
    196         friend class PatchBuffer;
    197 
    198     public:
    199         Label()
    200         {
    201         }
    202 
    203         Label(AbstractMacroAssembler<AssemblerType>* masm)
    204             : m_label(masm->m_assembler.label())
    205         {
    206         }
    207        
    208     private:
    209         JmpDst m_label;
    210     };
    211 
    212 
    213     // Jump:
    214     //
    215     // A jump object is a reference to a jump instruction that has been planted
    216     // into the code buffer - it is typically used to link the jump, setting the
    217     // relative offset such that when executed it will jump to the desired
    218     // destination.
    219     //
    220     // Jump objects retain a pointer to the assembler for syntactic purposes -
    221     // to allow the jump object to be able to link itself, e.g.:
    222     //
    223     //     Jump forwardsBranch = jne32(Imm32(0), reg1);
    224     //     // ...
    225     //     forwardsBranch.link();
    226     //
    227     // Jumps may also be linked to a Label.
    228     class Jump {
    229         friend class PatchBuffer;
    230         template<class AssemblerType_T>
    231         friend class AbstractMacroAssembler;
    232 
    233     public:
    234         Jump()
    235         {
    236         }
    237        
    238         Jump(JmpSrc jmp)
    239             : m_jmp(jmp)
    240         {
    241         }
    242        
    243         void link(AbstractMacroAssembler<AssemblerType>* masm)
    244         {
    245             masm->m_assembler.link(m_jmp, masm->m_assembler.label());
    246         }
    247        
    248         void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm)
    249         {
    250             masm->m_assembler.link(m_jmp, label.m_label);
    251         }
    252        
    253         static void patch(void* address, void* destination)
    254         {
    255             AssemblerType::patchBranchOffset(reinterpret_cast<intptr_t>(address), destination);
    256         }
    257 
    258     private:
    259         JmpSrc m_jmp;
    260     };
    261 
    262     // JumpList:
    263     //
    264     // A JumpList is a set of Jump objects.
    265     // All jumps in the set will be linked to the same destination.
    266     class JumpList {
    267         friend class PatchBuffer;
    268 
    269     public:
    270         void link(AbstractMacroAssembler<AssemblerType>* masm)
    271         {
    272             size_t size = m_jumps.size();
    273             for (size_t i = 0; i < size; ++i)
    274                 m_jumps[i].link(masm);
    275             m_jumps.clear();
    276         }
    277        
    278         void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm)
    279         {
    280             size_t size = m_jumps.size();
    281             for (size_t i = 0; i < size; ++i)
    282                 m_jumps[i].linkTo(label, masm);
    283             m_jumps.clear();
    284         }
    285        
    286         void append(Jump jump)
    287         {
    288             m_jumps.append(jump);
    289         }
    290        
    291         void append(JumpList& other)
    292         {
    293             m_jumps.append(other.m_jumps.begin(), other.m_jumps.size());
    294         }
    295 
    296         bool empty()
    297         {
    298             return !m_jumps.size();
    299         }
    300 
    301     private:
    302         Vector<Jump, 16> m_jumps;
    303     };
    304 
    305 
    306     // PatchBuffer:
    307     //
    308     // This class assists in linking code generated by the macro assembler, once code generation
    309     // has been completed, and the code has been copied to is final location in memory.  At this
    310     // time pointers to labels within the code may be resolved, and relative offsets to external
    311     // addresses may be fixed.
    312     //
    313     // Specifically:
    314     //   * Jump objects may be linked to external targets,
    315     //   * The address of Jump objects may taken, such that it can later be relinked.
    316     //   * The return address of a Jump object representing a call may be acquired.
    317     //   * The address of a Label pointing into the code may be resolved.
    318     //   * The value referenced by a DataLabel may be fixed.
    319     //
    320     // FIXME: distinguish between Calls & Jumps (make a specific call to obtain the return
    321     // address of calls, as opposed to a point that can be used to later relink a Jump -
    322     // possibly wrap the later up in an object that can do just that).
    323     class PatchBuffer {
    324     public:
    325         PatchBuffer(void* code)
    326             : m_code(code)
    327         {
    328         }
    329 
    330         void link(Jump jump, void* target)
    331         {
    332             AssemblerType::link(m_code, jump.m_jmp, target);
    333         }
    334 
    335         void link(JumpList list, void* target)
    336         {
    337             for (unsigned i = 0; i < list.m_jumps.size(); ++i)
    338                 AssemblerType::link(m_code, list.m_jumps[i].m_jmp, target);
    339         }
    340 
    341         void* addressOf(Jump jump)
    342         {
    343             return AssemblerType::getRelocatedAddress(m_code, jump.m_jmp);
    344         }
    345 
    346         void* addressOf(Label label)
    347         {
    348             return AssemblerType::getRelocatedAddress(m_code, label.m_label);
    349         }
    350 
    351         void* addressOf(DataLabelPtr label)
    352         {
    353             return AssemblerType::getRelocatedAddress(m_code, label.m_label);
    354         }
    355 
    356         void* addressOf(DataLabel32 label)
    357         {
    358             return AssemblerType::getRelocatedAddress(m_code, label.m_label);
    359         }
    360 
    361         ptrdiff_t returnAddressOffset(Jump call)
    362         {
    363             return AssemblerType::getCallReturnOffset(call.m_jmp);
    364         }
    365 
    366         void setPtr(DataLabelPtr label, void* value)
    367         {
    368             AssemblerType::patchAddress(m_code, label.m_label, value);
    369         }
    370 
    371     private:
    372         void* m_code;
    373     };
    374  
    375 
    376140    // ImmPtr:
    377141    //
     
    415179    };
    416180
     181
     182    // Section 2: MacroAssembler code buffer handles
     183    //
     184    // The following types are used to reference items in the code buffer
     185    // during JIT code generation.  For example, the type Jump is used to
     186    // track the location of a jump instruction so that it may later be
     187    // linked to a label marking its destination.
     188
     189
     190    // Label:
     191    //
     192    // A Label records a point in the generated instruction stream, typically such that
     193    // it may be used as a destination for a jump.
     194    class Label {
     195        friend class Jump;
     196        template<class AssemblerType_T>
     197        friend class AbstractMacroAssembler;
     198        friend class PatchBuffer;
     199
     200    public:
     201        Label()
     202        {
     203        }
     204
     205        Label(AbstractMacroAssembler<AssemblerType>* masm)
     206            : m_label(masm->m_assembler.label())
     207        {
     208        }
     209       
     210    private:
     211        JmpDst m_label;
     212    };
     213
     214    // DataLabelPtr:
     215    //
     216    // A DataLabelPtr is used to refer to a location in the code containing a pointer to be
     217    // patched after the code has been generated.
     218    class DataLabelPtr {
     219        template<class AssemblerType_T>
     220        friend class AbstractMacroAssembler;
     221        friend class PatchBuffer;
     222
     223    public:
     224        DataLabelPtr()
     225        {
     226        }
     227
     228        DataLabelPtr(AbstractMacroAssembler<AssemblerType>* masm)
     229            : m_label(masm->m_assembler.label())
     230        {
     231        }
     232       
     233    private:
     234        JmpDst m_label;
     235    };
     236
     237    // DataLabel32:
     238    //
     239    // A DataLabelPtr is used to refer to a location in the code containing a pointer to be
     240    // patched after the code has been generated.
     241    class DataLabel32 {
     242        template<class AssemblerType_T>
     243        friend class AbstractMacroAssembler;
     244        friend class PatchBuffer;
     245
     246    public:
     247        DataLabel32()
     248        {
     249        }
     250
     251        DataLabel32(AbstractMacroAssembler<AssemblerType>* masm)
     252            : m_label(masm->m_assembler.label())
     253        {
     254        }
     255
     256    private:
     257        JmpDst m_label;
     258    };
     259
     260    // Call:
     261    //
     262    // A Call object is a reference to a call instruction that has been planted
     263    // into the code buffer - it is typically used to link the call, setting the
     264    // relative offset such that when executed it will call to the desired
     265    // destination.
     266    //
     267    // Call objects retain a pointer to the assembler for syntactic purposes -
     268    // to allow the Call object to be able to link itself, e.g.:
     269    //
     270    //     Call forwardsBranch = jne32(Imm32(0), reg1);
     271    //     // ...
     272    //     forwardsBranch.link();
     273    //
     274    // Calls may also be linked to a Label.
     275    class Call {
     276        friend class PatchBuffer;
     277        template<class AssemblerType_T>
     278        friend class AbstractMacroAssembler;
     279
     280    public:
     281        Call()
     282        {
     283        }
     284       
     285        Call(JmpSrc jmp, bool isRelative)
     286            : m_jmp(jmp)
     287#ifndef NDEBUG
     288            , isRelative(isRelative)
     289#endif
     290        {
     291#ifdef NDEBUG
     292#pragma unused(isRelative)
     293#endif
     294        }
     295       
     296        void link(AbstractMacroAssembler<AssemblerType>* masm)
     297        {
     298            ASSERT(isRelative);
     299            masm->m_assembler.link(m_jmp, masm->m_assembler.label());
     300        }
     301       
     302        void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm)
     303        {
     304            ASSERT(isRelative);
     305            masm->m_assembler.link(m_jmp, label.m_label);
     306        }
     307
     308    private:
     309        JmpSrc m_jmp;
     310#ifndef NDEBUG
     311        bool isRelative;
     312#endif
     313    };
     314
     315    // Jump:
     316    //
     317    // A jump object is a reference to a jump instruction that has been planted
     318    // into the code buffer - it is typically used to link the jump, setting the
     319    // relative offset such that when executed it will jump to the desired
     320    // destination.
     321    //
     322    // Jump objects retain a pointer to the assembler for syntactic purposes -
     323    // to allow the jump object to be able to link itself, e.g.:
     324    //
     325    //     Jump forwardsBranch = jne32(Imm32(0), reg1);
     326    //     // ...
     327    //     forwardsBranch.link();
     328    //
     329    // Jumps may also be linked to a Label.
     330    class Jump {
     331        friend class PatchBuffer;
     332        template<class AssemblerType_T>
     333        friend class AbstractMacroAssembler;
     334
     335    public:
     336        Jump()
     337        {
     338        }
     339       
     340        Jump(JmpSrc jmp)   
     341            : m_jmp(jmp)
     342        {
     343        }
     344       
     345        void link(AbstractMacroAssembler<AssemblerType>* masm)
     346        {
     347            masm->m_assembler.link(m_jmp, masm->m_assembler.label());
     348        }
     349       
     350        void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm)
     351        {
     352            masm->m_assembler.link(m_jmp, label.m_label);
     353        }
     354
     355    private:
     356        JmpSrc m_jmp;
     357    };
     358
     359    // JumpList:
     360    //
     361    // A JumpList is a set of Jump objects.
     362    // All jumps in the set will be linked to the same destination.
     363    class JumpList {
     364        friend class PatchBuffer;
     365
     366    public:
     367        void link(AbstractMacroAssembler<AssemblerType>* masm)
     368        {
     369            size_t size = m_jumps.size();
     370            for (size_t i = 0; i < size; ++i)
     371                m_jumps[i].link(masm);
     372            m_jumps.clear();
     373        }
     374       
     375        void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm)
     376        {
     377            size_t size = m_jumps.size();
     378            for (size_t i = 0; i < size; ++i)
     379                m_jumps[i].linkTo(label, masm);
     380            m_jumps.clear();
     381        }
     382       
     383        void append(Jump jump)
     384        {
     385            m_jumps.append(jump);
     386        }
     387       
     388        void append(JumpList& other)
     389        {
     390            m_jumps.append(other.m_jumps.begin(), other.m_jumps.size());
     391        }
     392
     393        bool empty()
     394        {
     395            return !m_jumps.size();
     396        }
     397
     398    private:
     399        Vector<Jump, 16> m_jumps;
     400    };
     401
     402
     403    // Section 3: MacroAssembler JIT instruction stream handles.
     404    //
     405    // The MacroAssembler supported facilities to modify an JIT generated
     406    // instruction stream after it has been generated (relinking calls and
     407    // jumps, and repatching data values).  The following types are used
     408    // to store handles into the underlying instruction stream, the type
     409    // providing semantic information as to what it is that is in the
     410    // instruction stream at this point, and thus wha operations my be
     411    // performed on it.
     412
     413
     414    // CodeLocationCommon:
     415    //
     416    // Base type for other CodeLocation* types.  A postion in the JIT genertaed
     417    // instruction stream, without any semantic information.
     418    class CodeLocationCommon {
     419    public:
     420        CodeLocationCommon()
     421            : location(0)
     422        {
     423        }
     424
     425        // In order to avoid the need to store multiple handles into the
     426        // instructions stream, where the code generation is deterministic
     427        // and the labels will always be a fixed distance apart, these
     428        // methods may be used to recover a handle that has nopw been
     429        // retained, based on a known fixed relative offset from one that has.
     430        CodeLocationLabel labelAtOffset(int offset);
     431        CodeLocationJump jumpAtOffset(int offset);
     432        CodeLocationCall callAtOffset(int offset);
     433        CodeLocationDataLabelPtr dataLabelPtrAtOffset(int offset);
     434        CodeLocationDataLabel32 dataLabel32AtOffset(int offset);
     435
     436        operator bool() { return location; }
     437        void reset() { location = 0; }
     438
     439    protected:
     440        explicit CodeLocationCommon(void* location)
     441            : location(location)
     442        {
     443        }
     444
     445        void* location;
     446    };
     447
     448    // CodeLocationLabel:
     449    //
     450    // A point in the JIT code maked with a label.
     451    class CodeLocationLabel : public CodeLocationCommon {
     452        friend class CodeLocationCommon;
     453        friend class CodeLocationJump;
     454        friend class PatchBuffer;
     455
     456    public:
     457        CodeLocationLabel()
     458        {
     459        }
     460
     461        void* addressForSwitch() { return this->location; }
     462        void* addressForExceptionHandler() { return this->location; }
     463        void* addressForJSR() { return this->location; }
     464
     465    private:
     466        explicit CodeLocationLabel(void* location)
     467            : CodeLocationCommon(location)
     468        {
     469        }
     470
     471        void* getJumpDestination() { return this->location; }
     472    };
     473
     474    // CodeLocationJump:
     475    //
     476    // A point in the JIT code at which there is a jump instruction.
     477    class CodeLocationJump : public CodeLocationCommon {
     478        friend class CodeLocationCommon;
     479        friend class PatchBuffer;
     480    public:
     481        CodeLocationJump()
     482        {
     483        }
     484
     485        void relink(CodeLocationLabel destination)
     486        {
     487            AssemblerType::patchBranchOffset(reinterpret_cast<intptr_t>(this->location), destination.location);
     488        }
     489
     490    private:
     491        explicit CodeLocationJump(void* location) : CodeLocationCommon(location) {}
     492    };
     493
     494    // CodeLocationCall:
     495    //
     496    // A point in the JIT code at which there is a call instruction.
     497    class CodeLocationCall : public CodeLocationCommon {
     498        friend class CodeLocationCommon;
     499        friend class PatchBuffer;
     500    public:
     501        CodeLocationCall()
     502        {
     503        }
     504
     505        template<typename FunctionSig>
     506        void relink(FunctionSig* function)
     507        {
     508            AssemblerType::patchBranchOffset(reinterpret_cast<intptr_t>(this->location), reinterpret_cast<void*>(function));
     509        }
     510
     511        // This methods returns the value that will be set as the return address
     512        // within a function that has been called from this call instruction.
     513        void* calleeReturnAddressValue()
     514        {
     515            return this->location;
     516        }
     517
     518    private:
     519        explicit CodeLocationCall(void* location) : CodeLocationCommon(location) {}
     520    };
     521
     522    // CodeLocationDataLabel32:
     523    //
     524    // A point in the JIT code at which there is an int32_t immediate that may be repatched.
     525    class CodeLocationDataLabel32 : public CodeLocationCommon {
     526        friend class CodeLocationCommon;
     527        friend class PatchBuffer;
     528    public:
     529        CodeLocationDataLabel32()
     530        {
     531        }
     532
     533        void repatch(int32_t value)
     534        {
     535            AssemblerType::patchImmediate(reinterpret_cast<intptr_t>(this->location), value);
     536        }
     537
     538    private:
     539        explicit CodeLocationDataLabel32(void* location) : CodeLocationCommon(location) {}
     540    };
     541
     542    // CodeLocationDataLabelPtr:
     543    //
     544    // A point in the JIT code at which there is a void* immediate that may be repatched.
     545    class CodeLocationDataLabelPtr : public CodeLocationCommon {
     546        friend class CodeLocationCommon;
     547        friend class PatchBuffer;
     548    public:
     549        CodeLocationDataLabelPtr()
     550        {
     551        }
     552
     553        void repatch(void* value)
     554        {
     555            AssemblerType::patchPointer(reinterpret_cast<intptr_t>(this->location), reinterpret_cast<intptr_t>(value));
     556        }
     557
     558    private:
     559        explicit CodeLocationDataLabelPtr(void* location) : CodeLocationCommon(location) {}
     560    };
     561
     562    // ProcessorReturnAddress:
     563    //
     564    // This class can be used to relink a call identified by its return address.
     565    class ProcessorReturnAddress {
     566    public:
     567        ProcessorReturnAddress(void* location) : location(location) {}
     568       
     569        template<typename FunctionSig>
     570        void relinkCallerToFunction(FunctionSig* newCalleeFunction)
     571        {
     572            AssemblerType::patchBranchOffset(reinterpret_cast<intptr_t>(this->location), reinterpret_cast<void*>(newCalleeFunction));
     573        }
     574       
     575        operator void*()
     576        {
     577            return location;
     578        }
     579
     580    private:
     581        void* location;
     582    };
     583
     584
     585    // Section 4: The patch buffer - utility to finalize code generation.
     586
     587
     588    // PatchBuffer:
     589    //
     590    // This class assists in linking code generated by the macro assembler, once code generation
     591    // has been completed, and the code has been copied to is final location in memory.  At this
     592    // time pointers to labels within the code may be resolved, and relative offsets to external
     593    // addresses may be fixed.
     594    //
     595    // Specifically:
     596    //   * Jump objects may be linked to external targets,
     597    //   * The address of Jump objects may taken, such that it can later be relinked.
     598    //   * The return address of a Jump object representing a call may be acquired.
     599    //   * The address of a Label pointing into the code may be resolved.
     600    //   * The value referenced by a DataLabel may be fixed.
     601    //
     602    // FIXME: distinguish between Calls & Jumps (make a specific call to obtain the return
     603    // address of calls, as opposed to a point that can be used to later relink a Jump -
     604    // possibly wrap the later up in an object that can do just that).
     605    class PatchBuffer {
     606    public:
     607        PatchBuffer(void* code)
     608            : m_code(code)
     609        {
     610        }
     611
     612        CodeLocationLabel entry()
     613        {
     614            return CodeLocationLabel(m_code);
     615        }
     616
     617        void* trampolineAt(Label label)
     618        {
     619            return AssemblerType::getRelocatedAddress(m_code, label.m_label);
     620        }
     621       
     622        // These methods are used to link or set values at code generation time.
     623
     624        template<typename FunctionSig>
     625        void link(Call call, FunctionSig* function)
     626        {
     627            AssemblerType::link(m_code, call.m_jmp, reinterpret_cast<void*>(function));
     628        }
     629       
     630        template<typename FunctionSig>
     631        void linkTailRecursive(Jump jump, FunctionSig* function)
     632        {
     633            AssemblerType::link(m_code, jump.m_jmp, reinterpret_cast<void*>(function));
     634        }
     635
     636        template<typename FunctionSig>
     637        void linkTailRecursive(JumpList list, FunctionSig* function)
     638        {
     639            for (unsigned i = 0; i < list.m_jumps.size(); ++i)
     640                AssemblerType::link(m_code, list.m_jumps[i].m_jmp, reinterpret_cast<void*>(function));
     641        }
     642
     643        void link(Jump jump, CodeLocationLabel label)
     644        {
     645            AssemblerType::link(m_code, jump.m_jmp, label.location);
     646        }
     647
     648        void link(JumpList list, CodeLocationLabel label)
     649        {
     650            for (unsigned i = 0; i < list.m_jumps.size(); ++i)
     651                AssemblerType::link(m_code, list.m_jumps[i].m_jmp, label.location);
     652        }
     653
     654        void patch(DataLabelPtr label, void* value)
     655        {
     656            AssemblerType::patchAddress(m_code, label.m_label, value);
     657        }
     658
     659        // These methods are used to obtain handles to allow the code to be relinked / repatched later.
     660
     661        CodeLocationCall locationOf(Call call)
     662        {
     663            ASSERT(call.isRelative);
     664            return CodeLocationCall(AssemblerType::getRelocatedAddress(m_code, call.m_jmp));
     665        }
     666
     667        CodeLocationLabel locationOf(Label label)
     668        {
     669            return CodeLocationLabel(AssemblerType::getRelocatedAddress(m_code, label.m_label));
     670        }
     671
     672        CodeLocationDataLabelPtr locationOf(DataLabelPtr label)
     673        {
     674            return CodeLocationDataLabelPtr(AssemblerType::getRelocatedAddress(m_code, label.m_label));
     675        }
     676
     677        CodeLocationDataLabel32 locationOf(DataLabel32 label)
     678        {
     679            return CodeLocationDataLabel32(AssemblerType::getRelocatedAddress(m_code, label.m_label));
     680        }
     681
     682        // This method obtains the return address of the call, given as an offset from
     683        // the start of the code.
     684        unsigned returnAddressOffset(Call call)
     685        {
     686            return AssemblerType::getCallReturnOffset(call.m_jmp);
     687        }
     688
     689    private:
     690        void* m_code;
     691    };
     692
     693
     694    // Section 5: Misc admin methods
     695
    417696    size_t size()
    418697    {
     
    441720    }
    442721
     722    ptrdiff_t differenceBetween(Label from, Call to)
     723    {
     724        return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
     725    }
     726
    443727    ptrdiff_t differenceBetween(Label from, Label to)
    444728    {
     
    461745    }
    462746
     747protected:
     748
     749    AssemblerType m_assembler;
    463750};
    464751
     752
     753template <class AssemblerType>
     754typename AbstractMacroAssembler<AssemblerType>::CodeLocationLabel AbstractMacroAssembler<AssemblerType>::CodeLocationCommon::labelAtOffset(int offset) {
     755    return typename AbstractMacroAssembler::CodeLocationLabel(reinterpret_cast<char*>(location) + offset);
     756}
     757template <class AssemblerType>
     758typename AbstractMacroAssembler<AssemblerType>::CodeLocationJump AbstractMacroAssembler<AssemblerType>::CodeLocationCommon::jumpAtOffset(int offset) {
     759    return typename AbstractMacroAssembler::CodeLocationJump(reinterpret_cast<char*>(location) + offset);
     760}
     761template <class AssemblerType>
     762typename AbstractMacroAssembler<AssemblerType>::CodeLocationCall AbstractMacroAssembler<AssemblerType>::CodeLocationCommon::callAtOffset(int offset) {
     763    return typename AbstractMacroAssembler::CodeLocationCall(reinterpret_cast<char*>(location) + offset);
     764}
     765template <class AssemblerType>
     766typename AbstractMacroAssembler<AssemblerType>::CodeLocationDataLabelPtr AbstractMacroAssembler<AssemblerType>::CodeLocationCommon::dataLabelPtrAtOffset(int offset) {
     767    return typename AbstractMacroAssembler::CodeLocationDataLabelPtr(reinterpret_cast<char*>(location) + offset);
     768}
     769template <class AssemblerType>
     770typename AbstractMacroAssembler<AssemblerType>::CodeLocationDataLabel32 AbstractMacroAssembler<AssemblerType>::CodeLocationCommon::dataLabel32AtOffset(int offset) {
     771    return typename AbstractMacroAssembler::CodeLocationDataLabel32(reinterpret_cast<char*>(location) + offset);
     772}
     773
     774
    465775} // namespace JSC
    466776
  • trunk/JavaScriptCore/assembler/MacroAssemblerX86Common.h

    r40660 r40846  
    549549    }
    550550
    551     Jump call()
    552     {
    553         return Jump(m_assembler.call());
    554     }
    555 
    556     // FIXME: why does this return a Jump object? - it can't be linked.
    557     // This may be to get a reference to the return address of the call.
    558     //
    559     // This should probably be handled by a separate label type to a regular
    560     // jump.  Todo: add a CallLabel type, for the regular call - can be linked
    561     // like a jump (possibly a subclass of jump?, or possibly casts to a Jump).
    562     // Also add a CallReturnLabel type for this to return (just a more JmpDsty
    563     // form of label, can get the void* after the code has been linked, but can't
    564     // try to link it like a Jump object), and let the CallLabel be cast into a
    565     // CallReturnLabel.
    566     Jump call(RegisterID target)
    567     {
    568         return Jump(m_assembler.call(target));
     551    Call call()
     552    {
     553        return Call(m_assembler.call(), true);
     554    }
     555
     556    Call call(RegisterID target)
     557    {
     558        return Call(m_assembler.call(target), false);
    569559    }
    570560
  • trunk/JavaScriptCore/assembler/X86Assembler.h

    r40813 r40846  
    12471247    }
    12481248   
    1249     static ptrdiff_t getCallReturnOffset(JmpSrc call)
    1250     {
     1249    static unsigned getCallReturnOffset(JmpSrc call)
     1250    {
     1251        ASSERT(call.m_offset >= 0);
    12511252        return call.m_offset;
    12521253    }
Note: See TracChangeset for help on using the changeset viewer.