Ignore:
Timestamp:
Jun 15, 2009, 10:35:32 PM (16 years ago)
Author:
[email protected]
Message:

2009-06-15 Gavin Barraclough <[email protected]>

Reviewed by Sam Weinig.

Having moved most of their functionality into the RepatchBuffer class,
we can simplify the CodeLocation* classes.

The CodeLocation* classes are currently a tangle of templatey and friendly
badness, burried in the middle of AbstractMacroAssembler. Having moved
the ability to repatch out into RepatchBufer they are now do-nothing wrappers
on CodePtr (MacroAssemblerCodePtr), that only exist to provide type-safety.

Simplify the code, and move them off into their own header.

  • JavaScriptCore.xcodeproj/project.pbxproj:
  • assembler/AbstractMacroAssembler.h: (JSC::AbstractMacroAssembler::PatchBuffer::patch):
  • assembler/CodeLocation.h: Copied from assembler/AbstractMacroAssembler.h. (JSC::CodeLocationCommon::CodeLocationCommon): (JSC::CodeLocationInstruction::CodeLocationInstruction): (JSC::CodeLocationLabel::CodeLocationLabel): (JSC::CodeLocationJump::CodeLocationJump): (JSC::CodeLocationCall::CodeLocationCall): (JSC::CodeLocationNearCall::CodeLocationNearCall): (JSC::CodeLocationDataLabel32::CodeLocationDataLabel32): (JSC::CodeLocationDataLabelPtr::CodeLocationDataLabelPtr): (JSC::CodeLocationCommon::instructionAtOffset): (JSC::CodeLocationCommon::labelAtOffset): (JSC::CodeLocationCommon::jumpAtOffset): (JSC::CodeLocationCommon::callAtOffset): (JSC::CodeLocationCommon::nearCallAtOffset): (JSC::CodeLocationCommon::dataLabelPtrAtOffset): (JSC::CodeLocationCommon::dataLabel32AtOffset):
  • assembler/MacroAssemblerCodeRef.h: (JSC::MacroAssemblerCodePtr::operator!):
  • bytecode/CodeBlock.h: (JSC::getStructureStubInfoReturnLocation): (JSC::getCallLinkInfoReturnLocation): (JSC::getMethodCallLinkInfoReturnLocation):
  • bytecode/Instruction.h:
  • bytecode/JumpTable.h: (JSC::StringJumpTable::ctiForValue): (JSC::SimpleJumpTable::ctiForValue):
  • bytecode/StructureStubInfo.h:
  • bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::emitCatch):
  • jit/JIT.cpp: (JSC::JIT::privateCompile):
  • jit/JITStubs.cpp: (JSC::JITStubs::DEFINE_STUB_FUNCTION): (JSC::JITStubs::getPolymorphicAccessStructureListSlot):
File:
1 copied

Legend:

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

    r44705 r44711  
    11/*
    2  * Copyright (C) 2008 Apple Inc. All rights reserved.
     2 * Copyright (C) 2009 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2424 */
    2525
    26 #ifndef AbstractMacroAssembler_h
    27 #define AbstractMacroAssembler_h
     26#ifndef CodeLocation_h
     27#define CodeLocation_h
    2828
    2929#include <wtf/Platform.h>
    3030
    3131#include <MacroAssemblerCodeRef.h>
    32 #include <wtf/Noncopyable.h>
    33 #include <wtf/UnusedParam.h>
    3432
    3533#if ENABLE(ASSEMBLER)
    3634
    37 // FIXME: keep transitioning this out into MacroAssemblerX86_64.
    38 #if PLATFORM(X86_64)
    39 #define REPTACH_OFFSET_CALL_R11 3
    40 #endif
    41 
    4235namespace JSC {
    4336
    44 template <class AssemblerType>
    45 class AbstractMacroAssembler {
     37class CodeLocationInstruction;
     38class CodeLocationLabel;
     39class CodeLocationJump;
     40class CodeLocationCall;
     41class CodeLocationNearCall;
     42class CodeLocationDataLabel32;
     43class CodeLocationDataLabelPtr;
     44
     45// The CodeLocation* types are all pretty much do-nothing wrappers around
     46// CodePtr (or MacroAssemblerCodePtr, to give it its full name).  These
     47// classes only exist to provide type-safety when linking and patching code.
     48//
     49// The one new piece of functionallity introduced by these classes is the
     50// ability to create (or put another way, to re-discover) another CodeLocation
     51// at an offset from one you already know.  When patching code to optimize it
     52// we often want to patch a number of instructions that are short, fixed
     53// offsets apart.  To reduce memory overhead we will only retain a pointer to
     54// one of the instructions, and we will use the *AtOffset methods provided by
     55// CodeLocationCommon to find the other points in the code to modify.
     56class CodeLocationCommon : public MacroAssemblerCodePtr {
    4657public:
    47     typedef MacroAssemblerCodePtr CodePtr;
    48     typedef MacroAssemblerCodeRef CodeRef;
     58    CodeLocationInstruction instructionAtOffset(int offset);
     59    CodeLocationLabel labelAtOffset(int offset);
     60    CodeLocationJump jumpAtOffset(int offset);
     61    CodeLocationCall callAtOffset(int offset);
     62    CodeLocationNearCall nearCallAtOffset(int offset);
     63    CodeLocationDataLabelPtr dataLabelPtrAtOffset(int offset);
     64    CodeLocationDataLabel32 dataLabel32AtOffset(int offset);
    4965
    50     class Jump;
    51     class PatchBuffer;
    52     class RepatchBuffer;
    53     class CodeLocationInstruction;
    54     class CodeLocationLabel;
    55     class CodeLocationJump;
    56     class CodeLocationCall;
    57     class CodeLocationNearCall;
    58     class CodeLocationDataLabel32;
    59     class CodeLocationDataLabelPtr;
    60 
    61     typedef typename AssemblerType::RegisterID RegisterID;
    62     typedef typename AssemblerType::FPRegisterID FPRegisterID;
    63     typedef typename AssemblerType::JmpSrc JmpSrc;
    64     typedef typename AssemblerType::JmpDst JmpDst;
    65 
    66 
    67     // Section 1: MacroAssembler operand types
    68     //
    69     // The following types are used as operands to MacroAssembler operations,
    70     // describing immediate  and memory operands to the instructions to be planted.
    71 
    72 
    73     enum Scale {
    74         TimesOne,
    75         TimesTwo,
    76         TimesFour,
    77         TimesEight,
    78     };
    79 
    80     // Address:
    81     //
    82     // Describes a simple base-offset address.
    83     struct Address {
    84         explicit Address(RegisterID base, int32_t offset = 0)
    85             : base(base)
    86             , offset(offset)
    87         {
    88         }
    89 
    90         RegisterID base;
    91         int32_t offset;
    92     };
    93 
    94     // ImplicitAddress:
    95     //
    96     // This class is used for explicit 'load' and 'store' operations
    97     // (as opposed to situations in which a memory operand is provided
    98     // to a generic operation, such as an integer arithmetic instruction).
    99     //
    100     // In the case of a load (or store) operation we want to permit
    101     // addresses to be implicitly constructed, e.g. the two calls:
    102     //
    103     //     load32(Address(addrReg), destReg);
    104     //     load32(addrReg, destReg);
    105     //
    106     // Are equivalent, and the explicit wrapping of the Address in the former
    107     // is unnecessary.
    108     struct ImplicitAddress {
    109         ImplicitAddress(RegisterID base)
    110             : base(base)
    111             , offset(0)
    112         {
    113         }
    114 
    115         ImplicitAddress(Address address)
    116             : base(address.base)
    117             , offset(address.offset)
    118         {
    119         }
    120 
    121         RegisterID base;
    122         int32_t offset;
    123     };
    124 
    125     // BaseIndex:
    126     //
    127     // Describes a complex addressing mode.
    128     struct BaseIndex {
    129         BaseIndex(RegisterID base, RegisterID index, Scale scale, int32_t offset = 0)
    130             : base(base)
    131             , index(index)
    132             , scale(scale)
    133             , offset(offset)
    134         {
    135         }
    136 
    137         RegisterID base;
    138         RegisterID index;
    139         Scale scale;
    140         int32_t offset;
    141     };
    142 
    143     // AbsoluteAddress:
    144     //
    145     // Describes an memory operand given by a pointer.  For regular load & store
    146     // operations an unwrapped void* will be used, rather than using this.
    147     struct AbsoluteAddress {
    148         explicit AbsoluteAddress(void* ptr)
    149             : m_ptr(ptr)
    150         {
    151         }
    152 
    153         void* m_ptr;
    154     };
    155 
    156     // ImmPtr:
    157     //
    158     // A pointer sized immediate operand to an instruction - this is wrapped
    159     // in a class requiring explicit construction in order to differentiate
    160     // from pointers used as absolute addresses to memory operations
    161     struct ImmPtr {
    162         explicit ImmPtr(void* value)
    163             : m_value(value)
    164         {
    165         }
    166 
    167         intptr_t asIntptr()
    168         {
    169             return reinterpret_cast<intptr_t>(m_value);
    170         }
    171 
    172         void* m_value;
    173     };
    174 
    175     // Imm32:
    176     //
    177     // A 32bit immediate operand to an instruction - this is wrapped in a
    178     // class requiring explicit construction in order to prevent RegisterIDs
    179     // (which are implemented as an enum) from accidentally being passed as
    180     // immediate values.
    181     struct Imm32 {
    182         explicit Imm32(int32_t value)
    183             : m_value(value)
    184 #if PLATFORM(ARM_V7)
    185             , m_isPointer(false)
    186 #endif
    187         {
    188         }
    189 
    190 #if !PLATFORM(X86_64)
    191         explicit Imm32(ImmPtr ptr)
    192             : m_value(ptr.asIntptr())
    193 #if PLATFORM(ARM_V7)
    194             , m_isPointer(true)
    195 #endif
    196         {
    197         }
    198 #endif
    199 
    200         int32_t m_value;
    201 #if PLATFORM(ARM_V7)
    202         // We rely on being able to regenerate code to recover exception handling
    203         // information.  Since ARMv7 supports 16-bit immediates there is a danger
    204         // that if pointer values change the layout of the generated code will change.
    205         // To avoid this problem, always generate pointers (and thus Imm32s constructed
    206         // from ImmPtrs) with a code sequence that is able  to represent  any pointer
    207         // value - don't use a more compact form in these cases.
    208         bool m_isPointer;
    209 #endif
    210     };
    211 
    212 
    213     // Section 2: MacroAssembler code buffer handles
    214     //
    215     // The following types are used to reference items in the code buffer
    216     // during JIT code generation.  For example, the type Jump is used to
    217     // track the location of a jump instruction so that it may later be
    218     // linked to a label marking its destination.
    219 
    220 
    221     // Label:
    222     //
    223     // A Label records a point in the generated instruction stream, typically such that
    224     // it may be used as a destination for a jump.
    225     class Label {
    226         template<class TemplateAssemblerType>
    227         friend class AbstractMacroAssembler;
    228         friend class Jump;
    229         friend class MacroAssemblerCodeRef;
    230         friend class PatchBuffer;
    231 
    232     public:
    233         Label()
    234         {
    235         }
    236 
    237         Label(AbstractMacroAssembler<AssemblerType>* masm)
    238             : m_label(masm->m_assembler.label())
    239         {
    240         }
    241        
    242         bool isUsed() const { return m_label.isUsed(); }
    243         void used() { m_label.used(); }
    244     private:
    245         JmpDst m_label;
    246     };
    247 
    248     // DataLabelPtr:
    249     //
    250     // A DataLabelPtr is used to refer to a location in the code containing a pointer to be
    251     // patched after the code has been generated.
    252     class DataLabelPtr {
    253         template<class TemplateAssemblerType>
    254         friend class AbstractMacroAssembler;
    255         friend class PatchBuffer;
    256     public:
    257         DataLabelPtr()
    258         {
    259         }
    260 
    261         DataLabelPtr(AbstractMacroAssembler<AssemblerType>* masm)
    262             : m_label(masm->m_assembler.label())
    263         {
    264         }
    265        
    266     private:
    267         JmpDst m_label;
    268     };
    269 
    270     // DataLabel32:
    271     //
    272     // A DataLabelPtr is used to refer to a location in the code containing a pointer to be
    273     // patched after the code has been generated.
    274     class DataLabel32 {
    275         template<class TemplateAssemblerType>
    276         friend class AbstractMacroAssembler;
    277         friend class PatchBuffer;
    278     public:
    279         DataLabel32()
    280         {
    281         }
    282 
    283         DataLabel32(AbstractMacroAssembler<AssemblerType>* masm)
    284             : m_label(masm->m_assembler.label())
    285         {
    286         }
    287 
    288     private:
    289         JmpDst m_label;
    290     };
    291 
    292     // Call:
    293     //
    294     // A Call object is a reference to a call instruction that has been planted
    295     // into the code buffer - it is typically used to link the call, setting the
    296     // relative offset such that when executed it will call to the desired
    297     // destination.
    298     class Call {
    299         template<class TemplateAssemblerType>
    300         friend class AbstractMacroAssembler;
    301         friend class PatchBuffer;
    302     public:
    303         enum Flags {
    304             None = 0x0,
    305             Linkable = 0x1,
    306             Near = 0x2,
    307             LinkableNear = 0x3,
    308         };
    309 
    310         Call()
    311             : m_flags(None)
    312         {
    313         }
    314        
    315         Call(JmpSrc jmp, Flags flags)
    316             : m_jmp(jmp)
    317             , m_flags(flags)
    318         {
    319         }
    320 
    321         bool isFlagSet(Flags flag)
    322         {
    323             return m_flags & flag;
    324         }
    325 
    326         static Call fromTailJump(Jump jump)
    327         {
    328             return Call(jump.m_jmp, Linkable);
    329         }
    330 
    331     private:
    332         JmpSrc m_jmp;
    333         Flags m_flags;
    334     };
    335 
    336     // Jump:
    337     //
    338     // A jump object is a reference to a jump instruction that has been planted
    339     // into the code buffer - it is typically used to link the jump, setting the
    340     // relative offset such that when executed it will jump to the desired
    341     // destination.
    342     class Jump {
    343         template<class TemplateAssemblerType>
    344         friend class AbstractMacroAssembler;
    345         friend class Call;
    346         friend class PatchBuffer;
    347     public:
    348         Jump()
    349         {
    350         }
    351        
    352         Jump(JmpSrc jmp)   
    353             : m_jmp(jmp)
    354         {
    355         }
    356        
    357         void link(AbstractMacroAssembler<AssemblerType>* masm)
    358         {
    359             masm->m_assembler.linkJump(m_jmp, masm->m_assembler.label());
    360         }
    361        
    362         void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm)
    363         {
    364             masm->m_assembler.linkJump(m_jmp, label.m_label);
    365         }
    366 
    367     private:
    368         JmpSrc m_jmp;
    369     };
    370 
    371     // JumpList:
    372     //
    373     // A JumpList is a set of Jump objects.
    374     // All jumps in the set will be linked to the same destination.
    375     class JumpList {
    376         friend class PatchBuffer;
    377 
    378     public:
    379         void link(AbstractMacroAssembler<AssemblerType>* masm)
    380         {
    381             size_t size = m_jumps.size();
    382             for (size_t i = 0; i < size; ++i)
    383                 m_jumps[i].link(masm);
    384             m_jumps.clear();
    385         }
    386        
    387         void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm)
    388         {
    389             size_t size = m_jumps.size();
    390             for (size_t i = 0; i < size; ++i)
    391                 m_jumps[i].linkTo(label, masm);
    392             m_jumps.clear();
    393         }
    394        
    395         void append(Jump jump)
    396         {
    397             m_jumps.append(jump);
    398         }
    399        
    400         void append(JumpList& other)
    401         {
    402             m_jumps.append(other.m_jumps.begin(), other.m_jumps.size());
    403         }
    404 
    405         bool empty()
    406         {
    407             return !m_jumps.size();
    408         }
    409 
    410     private:
    411         Vector<Jump, 16> m_jumps;
    412     };
    413 
    414 
    415     // Section 3: MacroAssembler JIT instruction stream handles.
    416     //
    417     // The MacroAssembler supported facilities to modify a JIT generated
    418     // instruction stream after it has been generated (relinking calls and
    419     // jumps, and repatching data values).  The following types are used
    420     // to store handles into the underlying instruction stream, the type
    421     // providing semantic information as to what it is that is in the
    422     // instruction stream at this point, and thus what operations may be
    423     // performed on it.
    424 
    425 
    426     // CodeLocationCommon:
    427     //
    428     // Base type for other CodeLocation* types.  A postion in the JIT genertaed
    429     // instruction stream, without any semantic information.
    430     class CodeLocationCommon {
    431         friend class RepatchBuffer;
    432 
    433     public:
    434         CodeLocationCommon()
    435         {
    436         }
    437 
    438         // In order to avoid the need to store multiple handles into the
    439         // instructions stream, where the code generation is deterministic
    440         // and the labels will always be a fixed distance apart, these
    441         // methods may be used to recover a handle that has nopw been
    442         // retained, based on a known fixed relative offset from one that has.
    443         CodeLocationInstruction instructionAtOffset(int offset);
    444         CodeLocationLabel labelAtOffset(int offset);
    445         CodeLocationJump jumpAtOffset(int offset);
    446         CodeLocationCall callAtOffset(int offset);
    447         CodeLocationNearCall nearCallAtOffset(int offset);
    448         CodeLocationDataLabelPtr dataLabelPtrAtOffset(int offset);
    449         CodeLocationDataLabel32 dataLabel32AtOffset(int offset);
    450 
    451     protected:
    452         explicit CodeLocationCommon(CodePtr location)
    453             : m_location(location)
    454         {
    455         }
    456 
    457         void* dataLocation() { return m_location.dataLocation(); }
    458         void* executableAddress() { return m_location.executableAddress(); }
    459    
    460         void reset()
    461         {
    462             m_location = CodePtr();
    463         }
    464 
    465     private:
    466         CodePtr m_location;
    467     };
    468 
    469     // CodeLocationInstruction:
    470     //
    471     // An arbitrary instruction in the JIT code.
    472     class CodeLocationInstruction : public CodeLocationCommon {
    473     public:
    474         CodeLocationInstruction()
    475         {
    476         }
    477 
    478         explicit CodeLocationInstruction(void* location)
    479             : CodeLocationCommon(CodePtr(location))
    480         {
    481         }
    482     };
    483 
    484     // CodeLocationLabel:
    485     //
    486     // A point in the JIT code maked with a label.
    487     class CodeLocationLabel : public CodeLocationCommon {
    488         friend class CodeLocationCommon;
    489         friend class CodeLocationJump;
    490         friend class CodeLocationCall;
    491         friend class CodeLocationNearCall;
    492         friend class PatchBuffer;
    493         friend class RepatchBuffer;
    494 
    495     public:
    496         CodeLocationLabel()
    497         {
    498         }
    499 
    500         void* addressForSwitch() { return this->executableAddress(); }
    501         void* addressForExceptionHandler() { return this->executableAddress(); }
    502         void* addressForJSR() { return this->executableAddress(); }
    503 
    504         bool operator!()
    505         {
    506             return !this->executableAddress();
    507         }
    508 
    509         void reset()
    510         {
    511             CodeLocationCommon::reset();
    512         }
    513 
    514     private:
    515         explicit CodeLocationLabel(CodePtr location)
    516             : CodeLocationCommon(location)
    517         {
    518         }
    519 
    520         explicit CodeLocationLabel(void* location)
    521             : CodeLocationCommon(CodePtr(location))
    522         {
    523         }
    524 
    525         void* getJumpDestination() { return this->executableAddress(); }
    526     };
    527 
    528     // CodeLocationJump:
    529     //
    530     // A point in the JIT code at which there is a jump instruction.
    531     class CodeLocationJump : public CodeLocationCommon {
    532         friend class CodeLocationCommon;
    533         friend class PatchBuffer;
    534     public:
    535         CodeLocationJump()
    536         {
    537         }
    538 
    539         explicit CodeLocationJump(void* location)
    540             : CodeLocationCommon(CodePtr(location))
    541         {
    542         }
    543     };
    544 
    545     // CodeLocationCall:
    546     //
    547     // A point in the JIT code at which there is a call instruction.
    548     class CodeLocationCall : public CodeLocationCommon {
    549     public:
    550         CodeLocationCall()
    551         {
    552         }
    553 
    554         explicit CodeLocationCall(CodePtr location)
    555             : CodeLocationCommon(location)
    556         {
    557         }
    558 
    559         explicit CodeLocationCall(void* location)
    560             : CodeLocationCommon(CodePtr(location))
    561         {
    562         }
    563 
    564         // This methods returns the value that will be set as the return address
    565         // within a function that has been called from this call instruction.
    566         void* calleeReturnAddressValue()
    567         {
    568             return this->executableAddress();
    569         }
    570 
    571     };
    572 
    573     // CodeLocationNearCall:
    574     //
    575     // A point in the JIT code at which there is a call instruction with near linkage.
    576     class CodeLocationNearCall : public CodeLocationCommon {
    577     public:
    578         CodeLocationNearCall()
    579         {
    580         }
    581 
    582         explicit CodeLocationNearCall(CodePtr location)
    583             : CodeLocationCommon(location)
    584         {
    585         }
    586 
    587         explicit CodeLocationNearCall(void* location)
    588             : CodeLocationCommon(CodePtr(location))
    589         {
    590         }
    591 
    592         // This methods returns the value that will be set as the return address
    593         // within a function that has been called from this call instruction.
    594         void* calleeReturnAddressValue()
    595         {
    596             return this->executableAddress();
    597         }
    598     };
    599 
    600     // CodeLocationDataLabel32:
    601     //
    602     // A point in the JIT code at which there is an int32_t immediate that may be repatched.
    603     class CodeLocationDataLabel32 : public CodeLocationCommon {
    604     public:
    605         CodeLocationDataLabel32()
    606         {
    607         }
    608 
    609         explicit CodeLocationDataLabel32(void* location)
    610             : CodeLocationCommon(CodePtr(location))
    611         {
    612         }
    613     };
    614 
    615     // CodeLocationDataLabelPtr:
    616     //
    617     // A point in the JIT code at which there is a void* immediate that may be repatched.
    618     class CodeLocationDataLabelPtr : public CodeLocationCommon {
    619     public:
    620         CodeLocationDataLabelPtr()
    621         {
    622         }
    623 
    624         explicit CodeLocationDataLabelPtr(void* location)
    625             : CodeLocationCommon(CodePtr(location))
    626         {
    627         }
    628     };
    629 
    630 
    631     // Section 4: PatchBuffer - utility to finalize code generation.
    632 
    633     static CodePtr trampolineAt(CodeRef ref, Label label)
     66protected:
     67    CodeLocationCommon()
    63468    {
    635         return CodePtr(AssemblerType::getRelocatedAddress(ref.m_code.dataLocation(), label.m_label));
    63669    }
    63770
    638     // PatchBuffer:
    639     //
    640     // This class assists in linking code generated by the macro assembler, once code generation
    641     // has been completed, and the code has been copied to is final location in memory.  At this
    642     // time pointers to labels within the code may be resolved, and relative offsets to external
    643     // addresses may be fixed.
    644     //
    645     // Specifically:
    646     //   * Jump objects may be linked to external targets,
    647     //   * The address of Jump objects may taken, such that it can later be relinked.
    648     //   * The return address of a Jump object representing a call may be acquired.
    649     //   * The address of a Label pointing into the code may be resolved.
    650     //   * The value referenced by a DataLabel may be fixed.
    651     //
    652     // FIXME: distinguish between Calls & Jumps (make a specific call to obtain the return
    653     // address of calls, as opposed to a point that can be used to later relink a Jump -
    654     // possibly wrap the later up in an object that can do just that).
    655     class PatchBuffer : public Noncopyable {
    656     public:
    657         // Note: Initialization sequence is significant, since executablePool is a PassRefPtr.
    658         //       First, executablePool is copied into m_executablePool, then the initialization of
    659         //       m_code uses m_executablePool, *not* executablePool, since this is no longer valid.
    660         PatchBuffer(AbstractMacroAssembler<AssemblerType>* masm, PassRefPtr<ExecutablePool> executablePool)
    661             : m_executablePool(executablePool)
    662             , m_code(masm->m_assembler.executableCopy(m_executablePool.get()))
    663             , m_size(masm->m_assembler.size())
    664 #ifndef NDEBUG
    665             , m_completed(false)
    666 #endif
    667         {
    668         }
    669 
    670         ~PatchBuffer()
    671         {
    672             ASSERT(m_completed);
    673         }
    674 
    675         // These methods are used to link or set values at code generation time.
    676 
    677         void link(Call call, FunctionPtr function)
    678         {
    679             ASSERT(call.isFlagSet(Call::Linkable));
    680 #if PLATFORM(X86_64)
    681             if (!call.isFlagSet(Call::Near)) {
    682                 char* callLocation = reinterpret_cast<char*>(AssemblerType::getRelocatedAddress(code(), call.m_jmp)) - REPTACH_OFFSET_CALL_R11;
    683                 AssemblerType::patchPointerForCall(callLocation, function.value());
    684             } else
    685 #endif
    686             AssemblerType::linkCall(code(), call.m_jmp, function.value());
    687         }
    688        
    689         void link(Jump jump, CodeLocationLabel label)
    690         {
    691             AssemblerType::linkJump(code(), jump.m_jmp, label.dataLocation());
    692         }
    693 
    694         void link(JumpList list, CodeLocationLabel label)
    695         {
    696             for (unsigned i = 0; i < list.m_jumps.size(); ++i)
    697                 AssemblerType::linkJump(code(), list.m_jumps[i].m_jmp, label.dataLocation());
    698         }
    699 
    700         void patch(DataLabelPtr label, void* value)
    701         {
    702             AssemblerType::patchPointer(code(), label.m_label, value);
    703         }
    704 
    705         void patch(DataLabelPtr label, CodeLocationLabel value)
    706         {
    707             AssemblerType::patchPointer(code(), label.m_label, value.getJumpDestination());
    708         }
    709 
    710         // These methods are used to obtain handles to allow the code to be relinked / repatched later.
    711 
    712         CodeLocationCall locationOf(Call call)
    713         {
    714             ASSERT(call.isFlagSet(Call::Linkable));
    715             ASSERT(!call.isFlagSet(Call::Near));
    716             return CodeLocationCall(AssemblerType::getRelocatedAddress(code(), call.m_jmp));
    717         }
    718 
    719         CodeLocationNearCall locationOfNearCall(Call call)
    720         {
    721             ASSERT(call.isFlagSet(Call::Linkable));
    722             ASSERT(call.isFlagSet(Call::Near));
    723             return CodeLocationNearCall(AssemblerType::getRelocatedAddress(code(), call.m_jmp));
    724         }
    725 
    726         CodeLocationLabel locationOf(Label label)
    727         {
    728             return CodeLocationLabel(AssemblerType::getRelocatedAddress(code(), label.m_label));
    729         }
    730 
    731         CodeLocationDataLabelPtr locationOf(DataLabelPtr label)
    732         {
    733             return CodeLocationDataLabelPtr(AssemblerType::getRelocatedAddress(code(), label.m_label));
    734         }
    735 
    736         CodeLocationDataLabel32 locationOf(DataLabel32 label)
    737         {
    738             return CodeLocationDataLabel32(AssemblerType::getRelocatedAddress(code(), label.m_label));
    739         }
    740 
    741         // This method obtains the return address of the call, given as an offset from
    742         // the start of the code.
    743         unsigned returnAddressOffset(Call call)
    744         {
    745             return AssemblerType::getCallReturnOffset(call.m_jmp);
    746         }
    747 
    748         // Upon completion of all patching either 'finalizeCode()' or 'finalizeCodeAddendum()' should be called
    749         // once to complete generation of the code.  'finalizeCode()' is suited to situations
    750         // where the executable pool must also be retained, the lighter-weight 'finalizeCodeAddendum()' is
    751         // suited to adding to an existing allocation.
    752         CodeRef finalizeCode()
    753         {
    754             performFinalization();
    755 
    756             return CodeRef(m_code, m_executablePool, m_size);
    757         }
    758         CodeLocationLabel finalizeCodeAddendum()
    759         {
    760             performFinalization();
    761 
    762             return CodeLocationLabel(code());
    763         }
    764 
    765     private:
    766         // Keep this private! - the underlying code should only be obtained externally via
    767         // finalizeCode() or finalizeCodeAddendum().
    768         void* code()
    769         {
    770             return m_code;
    771         }
    772 
    773         void performFinalization()
    774         {
    775 #ifndef NDEBUG
    776             ASSERT(!m_completed);
    777             m_completed = true;
    778 #endif
    779 
    780             ExecutableAllocator::makeExecutable(code(), m_size);
    781         }
    782 
    783         RefPtr<ExecutablePool> m_executablePool;
    784         void* m_code;
    785         size_t m_size;
    786 #ifndef NDEBUG
    787         bool m_completed;
    788 #endif
    789     };
    790 
    791     class RepatchBuffer {
    792     public:
    793         RepatchBuffer()
    794         {
    795         }
    796 
    797         void relink(CodeLocationJump jump, CodeLocationLabel destination)
    798         {
    799             AssemblerType::relinkJump(jump.dataLocation(), destination.dataLocation());
    800         }
    801 
    802         void relink(CodeLocationCall call, CodeLocationLabel destination)
    803         {
    804 #if PLATFORM(X86_64)
    805             repatch(call.dataLabelPtrAtOffset(-REPTACH_OFFSET_CALL_R11), destination.executableAddress());
    806 #else
    807             AssemblerType::relinkCall(call.dataLocation(), destination.executableAddress());
    808 #endif
    809         }
    810 
    811         void relink(CodeLocationCall call, FunctionPtr destination)
    812         {
    813 #if PLATFORM(X86_64)
    814             repatch(call.dataLabelPtrAtOffset(-REPTACH_OFFSET_CALL_R11), destination.executableAddress());
    815 #else
    816             AssemblerType::relinkCall(call.dataLocation(), destination.executableAddress());
    817 #endif
    818         }
    819 
    820         void relink(CodeLocationNearCall nearCall, CodePtr destination)
    821         {
    822             AssemblerType::relinkCall(nearCall.dataLocation(), destination.executableAddress());
    823         }
    824 
    825         void relink(CodeLocationNearCall nearCall, CodeLocationLabel destination)
    826         {
    827             AssemblerType::relinkCall(nearCall.dataLocation(), destination.executableAddress());
    828         }
    829 
    830         void relink(CodeLocationNearCall nearCall, FunctionPtr destination)
    831         {
    832             AssemblerType::relinkCall(nearCall.dataLocation(), destination.executableAddress());
    833         }
    834 
    835         void repatch(CodeLocationDataLabel32 dataLabel32, int32_t value)
    836         {
    837             AssemblerType::repatchInt32(dataLabel32.dataLocation(), value);
    838         }
    839 
    840         void repatch(CodeLocationDataLabelPtr dataLabelPtr, void* value)
    841         {
    842             AssemblerType::repatchPointer(dataLabelPtr.dataLocation(), value);
    843         }
    844 
    845         void relinkCallerToTrampoline(ReturnAddressPtr returnAddress, CodeLocationLabel label)
    846         {
    847             relink(CodeLocationCall(CodePtr(returnAddress)), label);
    848         }
    849        
    850         void relinkCallerToTrampoline(ReturnAddressPtr returnAddress, CodePtr newCalleeFunction)
    851         {
    852             relinkCallerToTrampoline(returnAddress, CodeLocationLabel(newCalleeFunction));
    853         }
    854 
    855         void relinkCallerToFunction(ReturnAddressPtr returnAddress, FunctionPtr function)
    856         {
    857             relink(CodeLocationCall(CodePtr(returnAddress)), function);
    858         }
    859        
    860         void relinkNearCallerToTrampoline(ReturnAddressPtr returnAddress, CodeLocationLabel label)
    861         {
    862             relink(CodeLocationNearCall(CodePtr(returnAddress)), label);
    863         }
    864        
    865         void relinkNearCallerToTrampoline(ReturnAddressPtr returnAddress, CodePtr newCalleeFunction)
    866         {
    867             relinkNearCallerToTrampoline(returnAddress, CodeLocationLabel(newCalleeFunction));
    868         }
    869 
    870         void repatchLoadPtrToLEA(CodeLocationInstruction instruction)
    871         {
    872             AssemblerType::repatchLoadPtrToLEA(instruction.dataLocation());
    873         }
    874     };
    875 
    876 
    877     // Section 5: Misc admin methods
    878 
    879     size_t size()
     71    CodeLocationCommon(MacroAssemblerCodePtr location)
     72        : MacroAssemblerCodePtr(location)
    88073    {
    881         return m_assembler.size();
    88274    }
    883 
    884     Label label()
    885     {
    886         return Label(this);
    887     }
    888    
    889     Label align()
    890     {
    891         m_assembler.align(16);
    892         return Label(this);
    893     }
    894 
    895     ptrdiff_t differenceBetween(Label from, Jump to)
    896     {
    897         return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
    898     }
    899 
    900     ptrdiff_t differenceBetween(Label from, Call to)
    901     {
    902         return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
    903     }
    904 
    905     ptrdiff_t differenceBetween(Label from, Label to)
    906     {
    907         return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
    908     }
    909 
    910     ptrdiff_t differenceBetween(Label from, DataLabelPtr to)
    911     {
    912         return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
    913     }
    914 
    915     ptrdiff_t differenceBetween(Label from, DataLabel32 to)
    916     {
    917         return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
    918     }
    919 
    920     ptrdiff_t differenceBetween(DataLabelPtr from, Jump to)
    921     {
    922         return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
    923     }
    924 
    925     ptrdiff_t differenceBetween(DataLabelPtr from, DataLabelPtr to)
    926     {
    927         return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
    928     }
    929 
    930     ptrdiff_t differenceBetween(DataLabelPtr from, Call to)
    931     {
    932         return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
    933     }
    934 
    935 protected:
    936     AssemblerType m_assembler;
    93775};
    93876
     77class CodeLocationInstruction : public CodeLocationCommon {
     78public:
     79    CodeLocationInstruction() {}
     80    explicit CodeLocationInstruction(MacroAssemblerCodePtr location)
     81        : CodeLocationCommon(location) {}
     82    explicit CodeLocationInstruction(void* location)
     83        : CodeLocationCommon(MacroAssemblerCodePtr(location)) {}
     84};
    93985
    940 template <class AssemblerType>
    941 typename AbstractMacroAssembler<AssemblerType>::CodeLocationInstruction AbstractMacroAssembler<AssemblerType>::CodeLocationCommon::instructionAtOffset(int offset)
     86class CodeLocationLabel : public CodeLocationCommon {
     87public:
     88    CodeLocationLabel() {}
     89    explicit CodeLocationLabel(MacroAssemblerCodePtr location)
     90        : CodeLocationCommon(location) {}
     91    explicit CodeLocationLabel(void* location)
     92        : CodeLocationCommon(MacroAssemblerCodePtr(location)) {}
     93};
     94
     95class CodeLocationJump : public CodeLocationCommon {
     96public:
     97    CodeLocationJump() {}
     98    explicit CodeLocationJump(MacroAssemblerCodePtr location)
     99        : CodeLocationCommon(location) {}
     100    explicit CodeLocationJump(void* location)
     101        : CodeLocationCommon(MacroAssemblerCodePtr(location)) {}
     102};
     103
     104class CodeLocationCall : public CodeLocationCommon {
     105public:
     106    CodeLocationCall() {}
     107    explicit CodeLocationCall(MacroAssemblerCodePtr location)
     108        : CodeLocationCommon(location) {}
     109    explicit CodeLocationCall(void* location)
     110        : CodeLocationCommon(MacroAssemblerCodePtr(location)) {}
     111};
     112
     113class CodeLocationNearCall : public CodeLocationCommon {
     114public:
     115    CodeLocationNearCall() {}
     116    explicit CodeLocationNearCall(MacroAssemblerCodePtr location)
     117        : CodeLocationCommon(location) {}
     118    explicit CodeLocationNearCall(void* location)
     119        : CodeLocationCommon(MacroAssemblerCodePtr(location)) {}
     120};
     121
     122class CodeLocationDataLabel32 : public CodeLocationCommon {
     123public:
     124    CodeLocationDataLabel32() {}
     125    explicit CodeLocationDataLabel32(MacroAssemblerCodePtr location)
     126        : CodeLocationCommon(location) {}
     127    explicit CodeLocationDataLabel32(void* location)
     128        : CodeLocationCommon(MacroAssemblerCodePtr(location)) {}
     129};
     130
     131class CodeLocationDataLabelPtr : public CodeLocationCommon {
     132public:
     133    CodeLocationDataLabelPtr() {}
     134    explicit CodeLocationDataLabelPtr(MacroAssemblerCodePtr location)
     135        : CodeLocationCommon(location) {}
     136    explicit CodeLocationDataLabelPtr(void* location)
     137        : CodeLocationCommon(MacroAssemblerCodePtr(location)) {}
     138};
     139
     140inline CodeLocationInstruction CodeLocationCommon::instructionAtOffset(int offset)
    942141{
    943     return typename AbstractMacroAssembler::CodeLocationInstruction(reinterpret_cast<char*>(dataLocation()) + offset);
     142    ASSERT_VALID_CODE_OFFSET(offset);
     143    return CodeLocationInstruction(reinterpret_cast<char*>(dataLocation()) + offset);
    944144}
    945145
    946 template <class AssemblerType>
    947 typename AbstractMacroAssembler<AssemblerType>::CodeLocationLabel AbstractMacroAssembler<AssemblerType>::CodeLocationCommon::labelAtOffset(int offset)
     146inline CodeLocationLabel CodeLocationCommon::labelAtOffset(int offset)
    948147{
    949     return typename AbstractMacroAssembler::CodeLocationLabel(reinterpret_cast<char*>(dataLocation()) + offset);
     148    ASSERT_VALID_CODE_OFFSET(offset);
     149    return CodeLocationLabel(reinterpret_cast<char*>(dataLocation()) + offset);
    950150}
    951151
    952 template <class AssemblerType>
    953 typename AbstractMacroAssembler<AssemblerType>::CodeLocationJump AbstractMacroAssembler<AssemblerType>::CodeLocationCommon::jumpAtOffset(int offset)
     152inline CodeLocationJump CodeLocationCommon::jumpAtOffset(int offset)
    954153{
    955     return typename AbstractMacroAssembler::CodeLocationJump(reinterpret_cast<char*>(dataLocation()) + offset);
     154    ASSERT_VALID_CODE_OFFSET(offset);
     155    return CodeLocationJump(reinterpret_cast<char*>(dataLocation()) + offset);
    956156}
    957157
    958 template <class AssemblerType>
    959 typename AbstractMacroAssembler<AssemblerType>::CodeLocationCall AbstractMacroAssembler<AssemblerType>::CodeLocationCommon::callAtOffset(int offset)
     158inline CodeLocationCall CodeLocationCommon::callAtOffset(int offset)
    960159{
    961     return typename AbstractMacroAssembler::CodeLocationCall(reinterpret_cast<char*>(dataLocation()) + offset);
     160    ASSERT_VALID_CODE_OFFSET(offset);
     161    return CodeLocationCall(reinterpret_cast<char*>(dataLocation()) + offset);
    962162}
    963163
    964 template <class AssemblerType>
    965 typename AbstractMacroAssembler<AssemblerType>::CodeLocationNearCall AbstractMacroAssembler<AssemblerType>::CodeLocationCommon::nearCallAtOffset(int offset)
     164inline CodeLocationNearCall CodeLocationCommon::nearCallAtOffset(int offset)
    966165{
    967     return typename AbstractMacroAssembler::CodeLocationNearCall(reinterpret_cast<char*>(dataLocation()) + offset);
     166    ASSERT_VALID_CODE_OFFSET(offset);
     167    return CodeLocationNearCall(reinterpret_cast<char*>(dataLocation()) + offset);
    968168}
    969169
    970 template <class AssemblerType>
    971 typename AbstractMacroAssembler<AssemblerType>::CodeLocationDataLabelPtr AbstractMacroAssembler<AssemblerType>::CodeLocationCommon::dataLabelPtrAtOffset(int offset)
     170inline CodeLocationDataLabelPtr CodeLocationCommon::dataLabelPtrAtOffset(int offset)
    972171{
    973     return typename AbstractMacroAssembler::CodeLocationDataLabelPtr(reinterpret_cast<char*>(dataLocation()) + offset);
     172    ASSERT_VALID_CODE_OFFSET(offset);
     173    return CodeLocationDataLabelPtr(reinterpret_cast<char*>(dataLocation()) + offset);
    974174}
    975175
    976 template <class AssemblerType>
    977 typename AbstractMacroAssembler<AssemblerType>::CodeLocationDataLabel32 AbstractMacroAssembler<AssemblerType>::CodeLocationCommon::dataLabel32AtOffset(int offset)
     176inline CodeLocationDataLabel32 CodeLocationCommon::dataLabel32AtOffset(int offset)
    978177{
    979     return typename AbstractMacroAssembler::CodeLocationDataLabel32(reinterpret_cast<char*>(dataLocation()) + offset);
     178    ASSERT_VALID_CODE_OFFSET(offset);
     179    return CodeLocationDataLabel32(reinterpret_cast<char*>(dataLocation()) + offset);
    980180}
    981181
     
    984184#endif // ENABLE(ASSEMBLER)
    985185
    986 #endif // AbstractMacroAssembler_h
     186#endif // CodeLocation_h
Note: See TracChangeset for help on using the changeset viewer.