Ignore:
Timestamp:
Dec 13, 2008, 3:58:58 PM (16 years ago)
Author:
[email protected]
Message:

2008-12-13 Gavin Barraclough <[email protected]>

Reviewed by Cameron Zwarich.

Port the remainder of the JIT, bar calling convention related code, and code
implementing optimizations which can be disabled, to use the MacroAssembler.

  • assembler/MacroAssembler.h: (JSC::MacroAssembler::DataLabelPtr::DataLabelPtr): (JSC::MacroAssembler::RepatchBuffer::RepatchBuffer): (JSC::MacroAssembler::RepatchBuffer::link): (JSC::MacroAssembler::RepatchBuffer::addressOf): (JSC::MacroAssembler::RepatchBuffer::setPtr): (JSC::MacroAssembler::addPtr): (JSC::MacroAssembler::lshift32): (JSC::MacroAssembler::mod32): (JSC::MacroAssembler::rshift32): (JSC::MacroAssembler::storePtrWithRepatch): (JSC::MacroAssembler::jnzPtr): (JSC::MacroAssembler::jzPtr): (JSC::MacroAssembler::jump): (JSC::MacroAssembler::label):
  • assembler/X86Assembler.h: (JSC::X86Assembler::): (JSC::X86Assembler::xchgl_rr): (JSC::X86Assembler::jmp_m): (JSC::X86Assembler::repatchAddress): (JSC::X86Assembler::getRelocatedAddress):
  • bytecode/CodeBlock.cpp: (JSC::CodeBlock::CodeBlock):
  • bytecode/CodeBlock.h: (JSC::JITCodeRef::JITCodeRef): (JSC::CodeBlock::setJITCode): (JSC::CodeBlock::jitCode): (JSC::CodeBlock::executablePool):
  • jit/JIT.cpp: (JSC::JIT::privateCompileMainPass): (JSC::JIT::privateCompileLinkPass): (JSC::JIT::privateCompile): (JSC::JIT::privateCompileCTIMachineTrampolines):
  • jit/JIT.h: (JSC::CallRecord::CallRecord): (JSC::JumpTable::JumpTable): (JSC::JIT::emitCTICall): (JSC::JIT::JSRInfo::JSRInfo):
  • jit/JITArithmetic.cpp:
  • jit/JITCall.cpp:
  • jit/JITInlineMethods.h: (JSC::JIT::emitNakedCall): (JSC::JIT::emitCTICall_internal): (JSC::JIT::checkStructure): (JSC::JIT::emitFastArithDeTagImmediateJumpIfZero): (JSC::JIT::addSlowCase): (JSC::JIT::addJump): (JSC::JIT::emitJumpSlowToHot):
  • jit/JITPropertyAccess.cpp: (JSC::JIT::privateCompileGetByIdChainList): (JSC::JIT::privateCompileGetByIdChain):
File:
1 edited

Legend:

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

    r39261 r39284  
    6666    }
    6767
     68
    6869    // Address:
    6970    //
     
    137138    };
    138139
     140
    139141    class Jump;
     142    class RepatchBuffer;
     143
     144    // DataLabelPtr:
     145    //
     146    // A DataLabelPtr is used to refer to a location in the code containing a pointer to be
     147    // repatched after the code has been generated.
     148    class DataLabelPtr {
     149        friend class MacroAssembler;
     150
     151    public:
     152        DataLabelPtr()
     153        {
     154        }
     155
     156        DataLabelPtr(MacroAssembler* masm)
     157            : m_label(masm->m_assembler.label())
     158        {
     159        }
     160
     161    private:
     162        X86Assembler::JmpDst m_label;
     163    };
    140164
    141165    // Label:
     
    146170        friend class Jump;
    147171        friend class MacroAssembler;
     172        friend class RepatchBuffer;
    148173
    149174    public:
     
    160185        X86Assembler::JmpDst m_label;
    161186    };
    162    
     187
     188
    163189    // Jump:
    164190    //
     
    177203    // Jumps may also be linked to a Label.
    178204    class Jump {
     205        friend class RepatchBuffer;
     206        friend class MacroAssembler;
     207
    179208    public:
    180209        Jump()
     
    182211        }
    183212       
     213        // FIXME: transitionary method, while we replace JmpSrces with Jumps.
    184214        Jump(X86Assembler::JmpSrc jmp)
    185215            : m_jmp(jmp)
     
    242272        Vector<Jump> m_jumps;
    243273    };
     274
     275
     276    // RepatchBuffer:
     277    //
     278    // This class assists in linking code generated by the macro assembler, once code generation
     279    // has been completed, and the code has been copied to is final location in memory.  At this
     280    // time pointers to labels within the code may be resolved, and relative offsets to external
     281    // addresses may be fixed.
     282    //
     283    // Specifically:
     284    //   * Jump objects may be linked to external targets,
     285    //   * The address of Jump objects may taken, such that it can later be relinked.
     286    //   * The return address of a Jump object representing a call may be acquired.
     287    //   * The address of a Label pointing into the code may be resolved.
     288    //   * The value referenced by a DataLabel may be fixed.
     289    //
     290    // FIXME: distinguish between Calls & Jumps (make a specific call to obtain the return
     291    // address of calls, as opposed to a point that can be used to later relink a Jump -
     292    // possibly wrap the later up in an object that can do just that).
     293    class RepatchBuffer {
     294    public:
     295        RepatchBuffer(void* code)
     296            : m_code(code)
     297        {
     298        }
     299
     300        void link(Jump jump, void* target)
     301        {
     302            X86Assembler::link(m_code, jump.m_jmp, target);
     303        }
     304       
     305        void* addressOf(Jump jump)
     306        {
     307            return X86Assembler::getRelocatedAddress(m_code, jump.m_jmp);
     308        }
     309       
     310        void* addressOf(Label label)
     311        {
     312            return X86Assembler::getRelocatedAddress(m_code, label.m_label);
     313        }
     314
     315        void setPtr(DataLabelPtr label, void* value)
     316        {
     317            X86Assembler::repatchAddress(m_code, label.m_label, value);
     318        }
     319
     320    private:
     321        void* m_code;
     322    };
     323 
    244324
    245325    // Imm32:
     
    258338    };
    259339
    260 
    261340    // ImmPtr:
    262341    //
     
    281360    // object).
    282361
    283     void addPtr(Imm32 imm, RegisterID dest)
     362    void addPtr(Imm32 imm, RegisterID srcDest)
    284363    {
    285364#if PLATFORM(X86_64)
    286365        if (CAN_SIGN_EXTEND_8_32(imm.m_value))
    287             m_assembler.addq_i8r(imm.m_value, dest);
    288         else
    289             m_assembler.addq_i32r(imm.m_value, dest);
     366            m_assembler.addq_i8r(imm.m_value, srcDest);
     367        else
     368            m_assembler.addq_i32r(imm.m_value, srcDest);
    290369#else
    291370        if (CAN_SIGN_EXTEND_8_32(imm.m_value))
    292             m_assembler.addl_i8r(imm.m_value, dest);
    293         else
    294             m_assembler.addl_i32r(imm.m_value, dest);
    295 #endif
     371            m_assembler.addl_i8r(imm.m_value, srcDest);
     372        else
     373            m_assembler.addl_i32r(imm.m_value, srcDest);
     374#endif
     375    }
     376
     377
     378    void addPtr(Imm32 imm, RegisterID src, RegisterID dest)
     379    {
     380        m_assembler.leal_mr(imm.m_value, src, dest);
    296381    }
    297382
     
    335420    }
    336421   
     422    void lshift32(RegisterID shift_amount, RegisterID dest)
     423    {
     424        // On x86 we can only shift by ecx; if asked to shift by another register we'll
     425        // need rejig the shift amount into ecx first, and restore the registers afterwards.
     426        if (shift_amount != X86::ecx) {
     427            m_assembler.xchgl_rr(shift_amount, X86::ecx);
     428
     429            // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx"
     430            if (dest == shift_amount)
     431                m_assembler.shll_CLr(X86::ecx);
     432            // E.g. transform "shll %eax, %ecx" -> "xchgl %eax, %ecx; shll %ecx, %eax; xchgl %eax, %ecx"
     433            else if (dest == X86::ecx)
     434                m_assembler.shll_CLr(shift_amount);
     435            // E.g. transform "shll %eax, %ebx" -> "xchgl %eax, %ecx; shll %ecx, %ebx; xchgl %eax, %ecx"
     436            else
     437                m_assembler.shll_CLr(dest);
     438       
     439            m_assembler.xchgl_rr(shift_amount, X86::ecx);
     440        } else
     441            m_assembler.shll_CLr(dest);
     442    }
     443   
     444    // Take the value from dividend, divide it by divisor, and put the remainder in remainder.
     445    // For now, this operation has specific register requirements, and the three register must
     446    // be unique.  It is unfortunate to expose this in the MacroAssembler interface, however
     447    // given the complexity to fix, the fact that it is not uncommmon  for processors to have
     448    // specific register requirements on this operation (e.g. Mips result in 'hi'), or to not
     449    // support a hardware divide at all, it may not be
     450    void mod32(RegisterID divisor, RegisterID dividend, RegisterID remainder)
     451    {
     452#ifdef NDEBUG
     453#pragma unused(dividend,remainder)
     454#else
     455        ASSERT((dividend == X86::eax) && (remainder == X86::edx));
     456        ASSERT((dividend != divisor) && (remainder != divisor));
     457#endif
     458
     459        m_assembler.cdq();
     460        m_assembler.idivl_r(divisor);
     461    }
     462
    337463    void mul32(Imm32 imm, RegisterID src, RegisterID dest)
    338464    {
     
    356482    {
    357483        m_assembler.sarl_i8r(imm.m_value, dest);
     484    }
     485
     486    void rshift32(RegisterID shift_amount, RegisterID dest)
     487    {
     488        // On x86 we can only shift by ecx; if asked to shift by another register we'll
     489        // need rejig the shift amount into ecx first, and restore the registers afterwards.
     490        if (shift_amount != X86::ecx) {
     491            m_assembler.xchgl_rr(shift_amount, X86::ecx);
     492
     493            // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx"
     494            if (dest == shift_amount)
     495                m_assembler.sarl_CLr(X86::ecx);
     496            // E.g. transform "shll %eax, %ecx" -> "xchgl %eax, %ecx; shll %ecx, %eax; xchgl %eax, %ecx"
     497            else if (dest == X86::ecx)
     498                m_assembler.sarl_CLr(shift_amount);
     499            // E.g. transform "shll %eax, %ebx" -> "xchgl %eax, %ecx; shll %ecx, %ebx; xchgl %eax, %ecx"
     500            else
     501                m_assembler.sarl_CLr(dest);
     502       
     503            m_assembler.xchgl_rr(shift_amount, X86::ecx);
     504        } else
     505            m_assembler.sarl_CLr(dest);
    358506    }
    359507
     
    478626        store32(src, address);
    479627    }
    480 #endif
    481    
     628
     629    DataLabelPtr storePtrWithRepatch(Address address)
     630    {
     631        if (address.offset)
     632            m_assembler.movl_i32m(0, address.offset, address.base);
     633        else
     634            m_assembler.movl_i32m(0, address.base);
     635        return DataLabelPtr(this);
     636    }
     637#endif
     638
    482639    void store32(RegisterID src, ImplicitAddress address)
    483640    {
     
    8651022        return jnz32(reg, mask);
    8661023    }
     1024
     1025    Jump jnzPtr(Address address, Imm32 mask = Imm32(-1))
     1026    {
     1027        return jnz32(address, mask);
     1028    }
    8671029#endif
    8681030
     
    8831045    {
    8841046        return jz32(reg, mask);
     1047    }
     1048
     1049    Jump jzPtr(Address address, Imm32 mask = Imm32(-1))
     1050    {
     1051        return jz32(address, mask);
    8851052    }
    8861053
     
    9801147    {
    9811148        m_assembler.link(m_assembler.jmp(), target.m_label);
     1149    }
     1150
     1151    void jump(RegisterID target)
     1152    {
     1153        m_assembler.jmp_r(target);
     1154    }
     1155
     1156    // Address is a memory location containing the address to jump to
     1157    void jump(Address address)
     1158    {
     1159        if (address.offset)
     1160            m_assembler.jmp_m(address.offset, address.base);
     1161        else
     1162            m_assembler.jmp_m(address.base);
    9821163    }
    9831164
     
    10571238    }
    10581239
    1059     void jump(RegisterID target)
    1060     {
    1061         m_assembler.jmp_r(target);
     1240    Label label()
     1241    {
     1242        return Label(this);
    10621243    }
    10631244
Note: See TracChangeset for help on using the changeset viewer.