Ignore:
Timestamp:
Aug 9, 2010, 8:19:19 PM (15 years ago)
Author:
[email protected]
Message:

2010-08-09 Oliver Hunt <[email protected]>

Reviewed by Gavin Barraclough.

Allow an assembler/macroassembler to compact branches to more concise forms when linking
https://bugs.webkit.org/show_bug.cgi?id=43745

This patch makes it possible for an assembler to convert jumps into a different
(presumably more efficient) form at link time. Currently implemented in the
ARMv7 JIT as that already had logic to delay linking of jumps until the end of
compilation already. The ARMv7 JIT chooses between either a 4 byte short jump
or a full 32-bit offset (and rewrites ITTT instructions as appropriate), so does
not yet produce the most compact form possible. The general design of the linker
should make it relatively simple to introduce new branch types with little effort,
as the linker has no knowledge of the exact form of any of the branches.

  • JavaScriptCore.xcodeproj/project.pbxproj:
  • assembler/ARMv7Assembler.cpp: Added. (JSC::): Record jump sizes
  • assembler/ARMv7Assembler.h: (JSC::ARMv7Assembler::LinkRecord::LinkRecord): (JSC::ARMv7Assembler::LinkRecord::from): (JSC::ARMv7Assembler::LinkRecord::setFrom): (JSC::ARMv7Assembler::LinkRecord::to): (JSC::ARMv7Assembler::LinkRecord::type): (JSC::ARMv7Assembler::LinkRecord::linkType): (JSC::ARMv7Assembler::LinkRecord::setLinkType): Encapsulate LinkRecord fields so we can compress the values somewhat

(JSC::ARMv7Assembler::JmpSrc::JmpSrc):

Need to record the jump type now

(JSC::ARMv7Assembler::b):
(JSC::ARMv7Assembler::blx):
(JSC::ARMv7Assembler::bx):

Need to pass the jump types

(JSC::ARMv7Assembler::executableOffsetFor):
(JSC::ARMv7Assembler::jumpSizeDelta):
(JSC::ARMv7Assembler::linkRecordSourceComparator):
(JSC::ARMv7Assembler::computeJumpType):
(JSC::ARMv7Assembler::convertJumpTo):
(JSC::ARMv7Assembler::recordLinkOffsets):
(JSC::ARMv7Assembler::jumpsToLink):
(JSC::ARMv7Assembler::link):
(JSC::ARMv7Assembler::unlinkedCode):

Helper functions for the linker

(JSC::ARMv7Assembler::linkJump):
(JSC::ARMv7Assembler::canBeShortJump):
(JSC::ARMv7Assembler::linkLongJump):
(JSC::ARMv7Assembler::linkShortJump):
(JSC::ARMv7Assembler::linkJumpAbsolute):

Moving code around for the various jump linking functions

  • assembler/AbstractMacroAssembler.h: (JSC::AbstractMacroAssembler::beginUninterruptedSequence): (JSC::AbstractMacroAssembler::endUninterruptedSequence): We have to track uninterrupted sequences in any assembler that compacts branches as that's not something we're allowed to do in such sequences. AbstractMacroAssembler has a nop version of these functions as it makes the code elsewhere nicer.
  • assembler/LinkBuffer.h: (JSC::LinkBuffer::LinkBuffer): (JSC::LinkBuffer::link): (JSC::LinkBuffer::patch): (JSC::LinkBuffer::locationOf): (JSC::LinkBuffer::locationOfNearCall): (JSC::LinkBuffer::returnAddressOffset): (JSC::LinkBuffer::trampolineAt): Updated these functions to adjust for any changed offsets in the linked code

(JSC::LinkBuffer::applyOffset):

A helper function to deal with the now potentially moved labels

(JSC::LinkBuffer::linkCode):

The new and mighty linker function

  • assembler/MacroAssemblerARMv7.h: (JSC::MacroAssemblerARMv7::MacroAssemblerARMv7): (JSC::MacroAssemblerARMv7::beginUninterruptedSequence): (JSC::MacroAssemblerARMv7::endUninterruptedSequence): (JSC::MacroAssemblerARMv7::jumpsToLink): (JSC::MacroAssemblerARMv7::unlinkedCode): (JSC::MacroAssemblerARMv7::computeJumpType): (JSC::MacroAssemblerARMv7::convertJumpTo): (JSC::MacroAssemblerARMv7::recordLinkOffsets): (JSC::MacroAssemblerARMv7::jumpSizeDelta): (JSC::MacroAssemblerARMv7::link): (JSC::MacroAssemblerARMv7::jump): (JSC::MacroAssemblerARMv7::branchMul32): (JSC::MacroAssemblerARMv7::breakpoint): (JSC::MacroAssemblerARMv7::nearCall): (JSC::MacroAssemblerARMv7::call): (JSC::MacroAssemblerARMv7::ret): (JSC::MacroAssemblerARMv7::tailRecursiveCall): (JSC::MacroAssemblerARMv7::executableOffsetFor): (JSC::MacroAssemblerARMv7::inUninterruptedSequence): (JSC::MacroAssemblerARMv7::makeJump): (JSC::MacroAssemblerARMv7::makeBranch):

All branches need to pass on their type now

  • jit/ExecutableAllocator.h: (JSC::ExecutablePool::returnLastBytes):

We can't know ahead of time how much space will be necessary to
hold the linked code if we're compacting branches, this new
function allows us to return the unused bytes at the end of linking

  • jit/JIT.cpp: (JSC::JIT::JIT): (JSC::JIT::privateCompile):
  • jit/JIT.h: (JSC::JIT::compile):

The JIT class now needs to take a linker offset so that recompilation
can generate the same jumps when using branch compaction.

  • jit/JITArithmetic32_64.cpp: (JSC::JIT::emitSlow_op_mod):
  • jit/JITOpcodes.cpp: (JSC::JIT::privateCompileCTIMachineTrampolines):
  • jit/JITOpcodes32_64.cpp: (JSC::JIT::privateCompileCTIMachineTrampolines): (JSC::JIT::privateCompileCTINativeCall): Update for new trampolineAt changes
  • wtf/FastMalloc.cpp: (WTF::TCMallocStats::):
  • wtf/Platform.h:
File:
1 edited

Legend:

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

    r62419 r65042  
    4646
    4747public:
     48    typedef ARMv7Assembler::LinkRecord LinkRecord;
     49    typedef ARMv7Assembler::JumpLinkType JumpLinkType;
     50
     51    MacroAssemblerARMv7()
     52        : m_inUninterruptedSequence(false)
     53    {
     54    }
     55   
     56    void beginUninterruptedSequence() { m_inUninterruptedSequence = true; }
     57    void endUninterruptedSequence() { m_inUninterruptedSequence = false; }
     58    Vector<LinkRecord>& jumpsToLink() { return m_assembler.jumpsToLink(); }
     59    void* unlinkedCode() { return m_assembler.unlinkedCode(); }
     60    JumpLinkType computeJumpType(LinkRecord& record, const uint8_t* from, const uint8_t* to) { return m_assembler.computeJumpType(record, from, to); }
     61    void recordLinkOffsets(int32_t regionStart, int32_t regionEnd, int32_t offset) {return m_assembler.recordLinkOffsets(regionStart, regionEnd, offset); }
     62    int jumpSizeDelta(JumpLinkType jumpLinkType) { return m_assembler.jumpSizeDelta(jumpLinkType); }
     63    void link(LinkRecord& record, uint8_t* from, uint8_t* to) { return m_assembler.link(record, from, to); }
     64
    4865    struct ArmAddress {
    4966        enum AddressType {
     
    970987    void jump(RegisterID target)
    971988    {
    972         m_assembler.bx(target);
     989        m_assembler.bx(target, inUninterruptedSequence() ? ARMv7Assembler::JumpFullSize : ARMv7Assembler::JumpNoCondition);
    973990    }
    974991
     
    977994    {
    978995        load32(address, dataTempRegister);
    979         m_assembler.bx(dataTempRegister);
     996        m_assembler.bx(dataTempRegister, inUninterruptedSequence() ? ARMv7Assembler::JumpFullSize : ARMv7Assembler::JumpNoCondition);
    980997    }
    981998
     
    10131030    Jump branchMul32(Condition cond, RegisterID src, RegisterID dest)
    10141031    {
    1015         ASSERT(cond == Overflow);
     1032        ASSERT_UNUSED(cond, cond == Overflow);
    10161033        m_assembler.smull(dest, dataTempRegister, dest, src);
    10171034        m_assembler.asr(addressTempRegister, dest, 31);
     
    10211038    Jump branchMul32(Condition cond, Imm32 imm, RegisterID src, RegisterID dest)
    10221039    {
    1023         ASSERT(cond == Overflow);
     1040        ASSERT_UNUSED(cond, cond == Overflow);
    10241041        move(imm, dataTempRegister);
    10251042        m_assembler.smull(dest, dataTempRegister, src, dataTempRegister);
     
    10601077    void breakpoint()
    10611078    {
    1062         m_assembler.bkpt();
     1079        m_assembler.bkpt(0);
    10631080    }
    10641081
     
    10661083    {
    10671084        moveFixedWidthEncoding(Imm32(0), dataTempRegister);
    1068         return Call(m_assembler.blx(dataTempRegister), Call::LinkableNear);
     1085        return Call(m_assembler.blx(dataTempRegister, ARMv7Assembler::JumpFullSize), Call::LinkableNear);
    10691086    }
    10701087
     
    10721089    {
    10731090        moveFixedWidthEncoding(Imm32(0), dataTempRegister);
    1074         return Call(m_assembler.blx(dataTempRegister), Call::Linkable);
     1091        return Call(m_assembler.blx(dataTempRegister, ARMv7Assembler::JumpFullSize), Call::Linkable);
    10751092    }
    10761093
    10771094    Call call(RegisterID target)
    10781095    {
    1079         return Call(m_assembler.blx(target), Call::None);
     1096        return Call(m_assembler.blx(target, ARMv7Assembler::JumpFullSize), Call::None);
    10801097    }
    10811098
     
    10831100    {
    10841101        load32(address, dataTempRegister);
    1085         return Call(m_assembler.blx(dataTempRegister), Call::None);
     1102        return Call(m_assembler.blx(dataTempRegister, ARMv7Assembler::JumpFullSize), Call::None);
    10861103    }
    10871104
    10881105    void ret()
    10891106    {
    1090         m_assembler.bx(linkRegister);
     1107        m_assembler.bx(linkRegister, ARMv7Assembler::JumpFullSize);
    10911108    }
    10921109
     
    11881205        // Like a normal call, but don't link.
    11891206        moveFixedWidthEncoding(Imm32(0), dataTempRegister);
    1190         return Call(m_assembler.bx(dataTempRegister), Call::Linkable);
     1207        return Call(m_assembler.bx(dataTempRegister, ARMv7Assembler::JumpFullSize), Call::Linkable);
    11911208    }
    11921209
     
    11971214    }
    11981215
     1216   
     1217    int executableOffsetFor(int location)
     1218    {
     1219        return m_assembler.executableOffsetFor(location);
     1220    }
    11991221
    12001222protected:
     1223    bool inUninterruptedSequence()
     1224    {
     1225        return m_inUninterruptedSequence;
     1226    }
     1227
    12011228    ARMv7Assembler::JmpSrc makeJump()
    12021229    {
    12031230        moveFixedWidthEncoding(Imm32(0), dataTempRegister);
    1204         return m_assembler.bx(dataTempRegister);
     1231        return m_assembler.bx(dataTempRegister, inUninterruptedSequence() ? ARMv7Assembler::JumpFullSize : ARMv7Assembler::JumpNoCondition);
    12051232    }
    12061233
     
    12091236        m_assembler.it(cond, true, true);
    12101237        moveFixedWidthEncoding(Imm32(0), dataTempRegister);
    1211         return m_assembler.bx(dataTempRegister);
     1238        return m_assembler.bx(dataTempRegister, inUninterruptedSequence() ? ARMv7Assembler::JumpFullSize : ARMv7Assembler::JumpCondition, cond);
    12121239    }
    12131240    ARMv7Assembler::JmpSrc makeBranch(Condition cond) { return makeBranch(armV7Condition(cond)); }
     
    12991326        ARMv7Assembler::relinkCall(call.dataLocation(), destination.executableAddress());
    13001327    }
     1328   
     1329    bool m_inUninterruptedSequence;
    13011330};
    13021331
Note: See TracChangeset for help on using the changeset viewer.