Changeset 65042 in webkit


Ignore:
Timestamp:
Aug 9, 2010 8:19:19 PM (14 years ago)
Author:
oliver@apple.com
Message:

2010-08-09 Oliver Hunt <oliver@apple.com>

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:
Location:
trunk/JavaScriptCore
Files:
1 added
19 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r65032 r65042  
     12010-08-09  Oliver Hunt  <oliver@apple.com>
     2
     3        Reviewed by Gavin Barraclough.
     4
     5        Allow an assembler/macroassembler to compact branches to more concise forms when linking
     6        https://bugs.webkit.org/show_bug.cgi?id=43745
     7
     8        This patch makes it possible for an assembler to convert jumps into a different
     9        (presumably more efficient) form at link time.  Currently implemented in the
     10        ARMv7 JIT as that already had logic to delay linking of jumps until the end of
     11        compilation already.  The ARMv7 JIT chooses between either a 4 byte short jump
     12        or a full 32-bit offset (and rewrites ITTT instructions as appropriate), so does
     13        not yet produce the most compact form possible.  The general design of the linker
     14        should make it relatively simple to introduce new branch types with little effort,
     15        as the linker has no knowledge of the exact form of any of the branches.
     16
     17        * JavaScriptCore.xcodeproj/project.pbxproj:
     18        * assembler/ARMv7Assembler.cpp: Added.
     19        (JSC::):
     20          Record jump sizes
     21
     22        * assembler/ARMv7Assembler.h:
     23        (JSC::ARMv7Assembler::LinkRecord::LinkRecord):
     24        (JSC::ARMv7Assembler::LinkRecord::from):
     25        (JSC::ARMv7Assembler::LinkRecord::setFrom):
     26        (JSC::ARMv7Assembler::LinkRecord::to):
     27        (JSC::ARMv7Assembler::LinkRecord::type):
     28        (JSC::ARMv7Assembler::LinkRecord::linkType):
     29        (JSC::ARMv7Assembler::LinkRecord::setLinkType):
     30          Encapsulate LinkRecord fields so we can compress the values somewhat
     31
     32        (JSC::ARMv7Assembler::JmpSrc::JmpSrc):
     33          Need to record the jump type now
     34
     35        (JSC::ARMv7Assembler::b):
     36        (JSC::ARMv7Assembler::blx):
     37        (JSC::ARMv7Assembler::bx):
     38          Need to pass the jump types
     39
     40        (JSC::ARMv7Assembler::executableOffsetFor):
     41        (JSC::ARMv7Assembler::jumpSizeDelta):
     42        (JSC::ARMv7Assembler::linkRecordSourceComparator):
     43        (JSC::ARMv7Assembler::computeJumpType):
     44        (JSC::ARMv7Assembler::convertJumpTo):
     45        (JSC::ARMv7Assembler::recordLinkOffsets):
     46        (JSC::ARMv7Assembler::jumpsToLink):
     47        (JSC::ARMv7Assembler::link):
     48        (JSC::ARMv7Assembler::unlinkedCode):
     49          Helper functions for the linker
     50
     51        (JSC::ARMv7Assembler::linkJump):
     52        (JSC::ARMv7Assembler::canBeShortJump):
     53        (JSC::ARMv7Assembler::linkLongJump):
     54        (JSC::ARMv7Assembler::linkShortJump):
     55        (JSC::ARMv7Assembler::linkJumpAbsolute):
     56           Moving code around for the various jump linking functions
     57
     58        * assembler/AbstractMacroAssembler.h:
     59        (JSC::AbstractMacroAssembler::beginUninterruptedSequence):
     60        (JSC::AbstractMacroAssembler::endUninterruptedSequence):
     61          We have to track uninterrupted sequences in any assembler that compacts
     62          branches as that's not something we're allowed to do in such sequences.
     63          AbstractMacroAssembler has a nop version of these functions as it makes the
     64          code elsewhere nicer.
     65
     66        * assembler/LinkBuffer.h:
     67        (JSC::LinkBuffer::LinkBuffer):
     68        (JSC::LinkBuffer::link):
     69        (JSC::LinkBuffer::patch):
     70        (JSC::LinkBuffer::locationOf):
     71        (JSC::LinkBuffer::locationOfNearCall):
     72        (JSC::LinkBuffer::returnAddressOffset):
     73        (JSC::LinkBuffer::trampolineAt):
     74          Updated these functions to adjust for any changed offsets in the linked code
     75
     76        (JSC::LinkBuffer::applyOffset):
     77          A helper function to deal with the now potentially moved labels
     78
     79        (JSC::LinkBuffer::linkCode):
     80          The new and mighty linker function
     81
     82        * assembler/MacroAssemblerARMv7.h:
     83        (JSC::MacroAssemblerARMv7::MacroAssemblerARMv7):
     84        (JSC::MacroAssemblerARMv7::beginUninterruptedSequence):
     85        (JSC::MacroAssemblerARMv7::endUninterruptedSequence):
     86        (JSC::MacroAssemblerARMv7::jumpsToLink):
     87        (JSC::MacroAssemblerARMv7::unlinkedCode):
     88        (JSC::MacroAssemblerARMv7::computeJumpType):
     89        (JSC::MacroAssemblerARMv7::convertJumpTo):
     90        (JSC::MacroAssemblerARMv7::recordLinkOffsets):
     91        (JSC::MacroAssemblerARMv7::jumpSizeDelta):
     92        (JSC::MacroAssemblerARMv7::link):
     93        (JSC::MacroAssemblerARMv7::jump):
     94        (JSC::MacroAssemblerARMv7::branchMul32):
     95        (JSC::MacroAssemblerARMv7::breakpoint):
     96        (JSC::MacroAssemblerARMv7::nearCall):
     97        (JSC::MacroAssemblerARMv7::call):
     98        (JSC::MacroAssemblerARMv7::ret):
     99        (JSC::MacroAssemblerARMv7::tailRecursiveCall):
     100        (JSC::MacroAssemblerARMv7::executableOffsetFor):
     101        (JSC::MacroAssemblerARMv7::inUninterruptedSequence):
     102        (JSC::MacroAssemblerARMv7::makeJump):
     103        (JSC::MacroAssemblerARMv7::makeBranch):
     104           All branches need to pass on their type now
     105
     106        * jit/ExecutableAllocator.h:
     107        (JSC::ExecutablePool::returnLastBytes):
     108           We can't know ahead of time how much space will be necessary to
     109           hold the linked code if we're compacting branches, this new
     110           function allows us to return the unused bytes at the end of linking
     111
     112        * jit/JIT.cpp:
     113        (JSC::JIT::JIT):
     114        (JSC::JIT::privateCompile):
     115        * jit/JIT.h:
     116        (JSC::JIT::compile):
     117           The JIT class now needs to take a linker offset so that recompilation
     118           can generate the same jumps when using branch compaction.
     119        * jit/JITArithmetic32_64.cpp:
     120        (JSC::JIT::emitSlow_op_mod):
     121        * jit/JITOpcodes.cpp:
     122        (JSC::JIT::privateCompileCTIMachineTrampolines):
     123        * jit/JITOpcodes32_64.cpp:
     124        (JSC::JIT::privateCompileCTIMachineTrampolines):
     125        (JSC::JIT::privateCompileCTINativeCall):
     126          Update for new trampolineAt changes
     127
     128        * wtf/FastMalloc.cpp:
     129        (WTF::TCMallocStats::):
     130        * wtf/Platform.h:
     131
    11322010-08-09  Gavin Barraclough  <barraclough@apple.com>
    2133
  • trunk/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r65021 r65042  
    312312                A7482E93116A7CAD003B0712 /* JSWeakObjectMapRefInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = A7482E37116A697B003B0712 /* JSWeakObjectMapRefInternal.h */; settings = {ATTRIBUTES = (Private, ); }; };
    313313                A74B3499102A5F8E0032AB98 /* MarkStack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A74B3498102A5F8E0032AB98 /* MarkStack.cpp */; };
     314                A74DE1D0120B875600D40D5B /* ARMv7Assembler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A74DE1CB120B86D600D40D5B /* ARMv7Assembler.cpp */; };
    314315                A75706DE118A2BCF0057F88F /* JITArithmetic32_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A75706DD118A2BCF0057F88F /* JITArithmetic32_64.cpp */; };
    315316                A766B44F0EE8DCD1009518CA /* ExecutableAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    928929                A7482E37116A697B003B0712 /* JSWeakObjectMapRefInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWeakObjectMapRefInternal.h; sourceTree = "<group>"; };
    929930                A74B3498102A5F8E0032AB98 /* MarkStack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MarkStack.cpp; sourceTree = "<group>"; };
     931                A74DE1CB120B86D600D40D5B /* ARMv7Assembler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ARMv7Assembler.cpp; sourceTree = "<group>"; };
    930932                A75706DD118A2BCF0057F88F /* JITArithmetic32_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITArithmetic32_64.cpp; sourceTree = "<group>"; };
    931933                A76C51741182748D00715B05 /* JSInterfaceJIT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSInterfaceJIT.h; sourceTree = "<group>"; };
     
    18491851                                86D3B2C010156BDE002865E7 /* ARMAssembler.h */,
    18501852                                86ADD1430FDDEA980006EEC2 /* ARMv7Assembler.h */,
     1853                                A74DE1CB120B86D600D40D5B /* ARMv7Assembler.cpp */,
    18511854                                9688CB130ED12B4E001D649F /* AssemblerBuffer.h */,
    18521855                                86D3B2C110156BDE002865E7 /* AssemblerBufferWithConstantPool.h */,
     
    26782681                                8627E5EB11F1281900A313B5 /* PageAllocation.cpp in Sources */,
    26792682                                DDE82AD71209D955005C1756 /* GCHandle.cpp in Sources */,
     2683                                A74DE1D0120B875600D40D5B /* ARMv7Assembler.cpp in Sources */,
    26802684                        );
    26812685                        runOnlyForDeploymentPostprocessing = 0;
  • trunk/JavaScriptCore/assembler/ARMv7Assembler.h

    r64608 r65042  
    382382        u.d = d;
    383383
    384         int sign = (u.i >> 63);
    385         int exponent = (u.i >> 52) & 0x7ff;
     384        int sign = static_cast<int>(u.i >> 63);
     385        int exponent = static_cast<int>(u.i >> 52) & 0x7ff;
    386386        uint64_t mantissa = u.i & 0x000fffffffffffffull;
    387387
     
    445445    } m_u;
    446446};
    447 
    448447
    449448class ARMv7Assembler {
     
    477476        ConditionLE,
    478477        ConditionAL,
    479 
     478       
    480479        ConditionCS = ConditionHS,
    481480        ConditionCC = ConditionLO,
    482481    } Condition;
    483482
     483    enum JumpType { JumpNoCondition, JumpCondition, JumpFullSize };
     484    enum JumpLinkType { LinkInvalid, LinkShortJump, LinkConditionalShortJump, LinkLongJump, JumpTypeCount };
     485    static const int JumpSizes[JumpTypeCount];
     486    enum { JumpPaddingSize = 5 * sizeof(uint16_t) };
     487    class LinkRecord {
     488    public:
     489        LinkRecord(intptr_t from, intptr_t to, JumpType type, Condition condition)
     490            : m_from(from)
     491            , m_to(to)
     492            , m_type(type)
     493            , m_linkType(LinkInvalid)
     494            , m_condition(condition)
     495        {
     496        }
     497        intptr_t from() const { return m_from; }
     498        void setFrom(intptr_t from) { m_from = from; }
     499        intptr_t to() const { return m_to; }
     500        JumpType type() const { return m_type; }
     501        JumpLinkType linkType() const { return m_linkType; }
     502        void setLinkType(JumpLinkType linkType) { ASSERT(m_linkType == LinkInvalid); m_linkType = linkType; }
     503        Condition condition() const { return m_condition; }
     504    private:
     505        intptr_t m_from : 31;
     506        intptr_t m_to : 31;
     507        JumpType m_type : 2;
     508        JumpLinkType m_linkType : 3;
     509        Condition m_condition : 16;
     510    };
     511   
    484512    class JmpSrc {
    485513        friend class ARMv7Assembler;
    486514        friend class ARMInstructionFormatter;
     515        friend class LinkBuffer;
    487516    public:
    488517        JmpSrc()
     
    492521
    493522    private:
    494         JmpSrc(int offset)
     523        JmpSrc(int offset, JumpType type)
    495524            : m_offset(offset)
    496         {
     525            , m_condition(0xffff)
     526            , m_type(type)
     527        {
     528            ASSERT(m_type != JumpCondition);
     529        }
     530
     531        JmpSrc(int offset, JumpType type, Condition condition)
     532            : m_offset(offset)
     533            , m_condition(condition)
     534            , m_type(type)
     535        {
     536            ASSERT(m_type == JumpCondition || m_type == JumpFullSize);
    497537        }
    498538
    499539        int m_offset;
     540        Condition m_condition : 16;
     541        JumpType m_type : 16;
     542       
    500543    };
    501544   
     
    503546        friend class ARMv7Assembler;
    504547        friend class ARMInstructionFormatter;
     548        friend class LinkBuffer;
    505549    public:
    506550        JmpDst()
     
    525569
    526570private:
    527 
    528     struct LinkRecord {
    529         LinkRecord(intptr_t from, intptr_t to)
    530             : from(from)
    531             , to(to)
    532         {
    533         }
    534 
    535         intptr_t from;
    536         intptr_t to;
    537     };
    538571
    539572    // ARMv7, Appx-A.6.3
     
    740773
    741774public:
    742 
     775   
    743776    void add(RegisterID rd, RegisterID rn, ARMThumbImmediate imm)
    744777    {
     
    879912        m_formatter.twoWordOp12Reg4FourFours(OP_ASR_reg_T2, rn, FourFours(0xf, rd, 0, rm));
    880913    }
    881 
     914   
    882915    // Only allowed in IT (if then) block if last instruction.
    883     JmpSrc b()
     916    JmpSrc b(JumpType type)
    884917    {
    885918        m_formatter.twoWordOp16Op16(OP_B_T4a, OP_B_T4b);
    886         return JmpSrc(m_formatter.size());
     919        return JmpSrc(m_formatter.size(), type);
    887920    }
    888921   
    889922    // Only allowed in IT (if then) block if last instruction.
    890     JmpSrc blx(RegisterID rm)
     923    JmpSrc blx(RegisterID rm, JumpType type)
    891924    {
    892925        ASSERT(rm != ARMRegisters::pc);
    893926        m_formatter.oneWordOp8RegReg143(OP_BLX, rm, (RegisterID)8);
    894         return JmpSrc(m_formatter.size());
     927        return JmpSrc(m_formatter.size(), type);
    895928    }
    896929
    897930    // Only allowed in IT (if then) block if last instruction.
    898     JmpSrc bx(RegisterID rm)
     931    JmpSrc bx(RegisterID rm, JumpType type, Condition condition)
    899932    {
    900933        m_formatter.oneWordOp8RegReg143(OP_BX, rm, (RegisterID)0);
    901         return JmpSrc(m_formatter.size());
     934        return JmpSrc(m_formatter.size(), type, condition);
     935    }
     936
     937    JmpSrc bx(RegisterID rm, JumpType type)
     938    {
     939        m_formatter.oneWordOp8RegReg143(OP_BX, rm, (RegisterID)0);
     940        return JmpSrc(m_formatter.size(), type);
    902941    }
    903942
     
    16181657        return dst.m_offset - src.m_offset;
    16191658    }
     1659
     1660    int executableOffsetFor(int location)
     1661    {
     1662        if (!location)
     1663            return 0;
     1664        return static_cast<int32_t*>(m_formatter.data())[location / sizeof(int32_t) - 1];
     1665    }
     1666   
     1667    int jumpSizeDelta(JumpLinkType jumpLinkType) { return JumpPaddingSize - JumpSizes[jumpLinkType]; }
    16201668   
    16211669    // Assembler admin methods:
     
    16261674    }
    16271675
    1628     void* executableCopy(ExecutablePool* allocator)
    1629     {
    1630         void* copy = m_formatter.executableCopy(allocator);
    1631         if (!copy)
    1632             return 0;
    1633 
    1634         unsigned jumpCount = m_jumpsToLink.size();
    1635         for (unsigned i = 0; i < jumpCount; ++i) {
    1636             uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(copy) + m_jumpsToLink[i].from);
    1637             uint16_t* target = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(copy) + m_jumpsToLink[i].to);
    1638             linkJumpAbsolute(location, target);
    1639         }
    1640         m_jumpsToLink.clear();
    1641 
    1642         return copy;
    1643     }
    1644 
     1676    static bool linkRecordSourceComparator(const LinkRecord& a, const LinkRecord& b)
     1677    {
     1678        return a.from() < b.from();
     1679    }
     1680
     1681    JumpLinkType computeJumpType(LinkRecord& record, const uint8_t* from, const uint8_t* to)
     1682    {
     1683        if (record.type() >= JumpFullSize) {
     1684            record.setLinkType(LinkLongJump);
     1685            return LinkLongJump;
     1686        }
     1687        bool mayTriggerErrata = false;
     1688        const uint16_t* shortJumpLocation = reinterpret_cast<const uint16_t*>(from  - (JumpPaddingSize - JumpSizes[LinkShortJump]));
     1689        if (!canBeShortJump(shortJumpLocation, to, mayTriggerErrata)) {
     1690            record.setLinkType(LinkLongJump);
     1691            return LinkLongJump;
     1692        }
     1693        if (mayTriggerErrata) {
     1694            record.setLinkType(LinkLongJump);
     1695            return LinkLongJump;
     1696        }
     1697        if (record.type() == JumpCondition) {
     1698            record.setLinkType(LinkConditionalShortJump);
     1699            return LinkConditionalShortJump;
     1700        }
     1701        record.setLinkType(LinkShortJump);
     1702        return LinkShortJump;
     1703    }
     1704
     1705    void recordLinkOffsets(int32_t regionStart, int32_t regionEnd, int32_t offset)
     1706    {
     1707        int32_t ptr = regionStart / sizeof(int32_t);
     1708        const int32_t end = regionEnd / sizeof(int32_t);
     1709        int32_t* offsets = static_cast<int32_t*>(m_formatter.data());
     1710        while (ptr < end)
     1711            offsets[ptr++] = offset;
     1712    }
     1713   
     1714    Vector<LinkRecord>& jumpsToLink()
     1715    {
     1716        std::sort(m_jumpsToLink.begin(), m_jumpsToLink.end(), linkRecordSourceComparator);
     1717        return m_jumpsToLink;
     1718    }
     1719
     1720    void link(LinkRecord& record, uint8_t* from, uint8_t* to)
     1721    {
     1722        uint16_t* itttLocation;
     1723        if (record.linkType() == LinkConditionalShortJump) {
     1724            itttLocation = reinterpret_cast<uint16_t*>(from - JumpSizes[LinkConditionalShortJump] - 2);
     1725            itttLocation[0] = ifThenElse(record.condition()) | OP_IT;
     1726        }
     1727        ASSERT(record.linkType() != LinkInvalid);
     1728        if (record.linkType() != LinkLongJump)
     1729            linkShortJump(reinterpret_cast<uint16_t*>(from), to);
     1730        else
     1731            linkLongJump(reinterpret_cast<uint16_t*>(from), to);
     1732    }
     1733
     1734    void* unlinkedCode() { return m_formatter.data(); }
     1735   
    16451736    static unsigned getCallReturnOffset(JmpSrc call)
    16461737    {
     
    16611752        ASSERT(to.m_offset != -1);
    16621753        ASSERT(from.m_offset != -1);
    1663         m_jumpsToLink.append(LinkRecord(from.m_offset, to.m_offset));
     1754        m_jumpsToLink.append(LinkRecord(from.m_offset, to.m_offset, from.m_type, from.m_condition));
    16641755    }
    16651756
     
    18641955    }
    18651956
    1866     static void linkJumpAbsolute(uint16_t* instruction, void* target)
    1867     {
    1868         // FIMXE: this should be up in the MacroAssembler layer. :-(
    1869         const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip;
    1870 
     1957    static bool canBeShortJump(const uint16_t* instruction, const void* target, bool& mayTriggerErrata)
     1958    {
    18711959        ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
    18721960        ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
    1873 
    1874         ASSERT( (isMOV_imm_T3(instruction - 5) && isMOVT(instruction - 3) && isBX(instruction - 1))
    1875             || (isNOP_T1(instruction - 5) && isNOP_T2(instruction - 4) && isB(instruction - 2)) );
    1876 
     1961       
    18771962        intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
    1878 
    18791963        // From Cortex-A8 errata:
    18801964        // If the 32-bit Thumb-2 branch instruction spans two 4KiB regions and
     
    18851969        // The instruction is spanning two pages if it ends at an address ending 0x002
    18861970        bool spansTwo4K = ((reinterpret_cast<intptr_t>(instruction) & 0xfff) == 0x002);
     1971        mayTriggerErrata = spansTwo4K;
    18871972        // The target is in the first page if the jump branch back by [3..0x1002] bytes
    18881973        bool targetInFirstPage = (relative >= -0x1002) && (relative < -2);
    18891974        bool wouldTriggerA8Errata = spansTwo4K && targetInFirstPage;
    1890 
    1891         if (((relative << 7) >> 7) == relative && !wouldTriggerA8Errata) {
     1975        return ((relative << 7) >> 7) == relative && !wouldTriggerA8Errata;
     1976    }
     1977
     1978    static void linkLongJump(uint16_t* instruction, void* target)
     1979    {
     1980        linkJumpAbsolute(instruction, target);
     1981    }
     1982   
     1983    static void linkShortJump(uint16_t* instruction, void* target)
     1984    {
     1985        // FIMXE: this should be up in the MacroAssembler layer. :-(       
     1986        ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
     1987        ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
     1988       
     1989        intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
     1990        bool scratch;
     1991        UNUSED_PARAM(scratch);
     1992        ASSERT(canBeShortJump(instruction, target, scratch));
     1993        // ARM encoding for the top two bits below the sign bit is 'peculiar'.
     1994        if (relative >= 0)
     1995            relative ^= 0xC00000;
     1996
     1997        // All branch offsets should be an even distance.
     1998        ASSERT(!(relative & 1));
     1999        instruction[-2] = OP_B_T4a | ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12);
     2000        instruction[-1] = OP_B_T4b | ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1);
     2001    }
     2002
     2003    static void linkJumpAbsolute(uint16_t* instruction, void* target)
     2004    {
     2005        // FIMXE: this should be up in the MacroAssembler layer. :-(
     2006        ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
     2007        ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
     2008
     2009        ASSERT((isMOV_imm_T3(instruction - 5) && isMOVT(instruction - 3) && isBX(instruction - 1))
     2010            || (isNOP_T1(instruction - 5) && isNOP_T2(instruction - 4) && isB(instruction - 2)));
     2011
     2012        intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
     2013        bool scratch;
     2014        if (canBeShortJump(instruction, target, scratch)) {
    18922015            // ARM encoding for the top two bits below the sign bit is 'peculiar'.
    18932016            if (relative >= 0)
     
    19072030            instruction[-1] = OP_B_T4b | ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1);
    19082031        } else {
     2032            const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip;
    19092033            ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) + 1));
    19102034            ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) >> 16));
     
    19212045        return op | (imm.m_value.i << 10) | imm.m_value.imm4;
    19222046    }
     2047
    19232048    static uint16_t twoWordOp5i6Imm4Reg4EncodedImmSecond(uint16_t rd, ARMThumbImmediate imm)
    19242049    {
     
    20372162
    20382163    Vector<LinkRecord> m_jumpsToLink;
     2164    Vector<int32_t> m_offsets;
    20392165};
    20402166
  • trunk/JavaScriptCore/assembler/AbstractMacroAssembler.h

    r64943 r65042  
    419419
    420420    // Section 3: Misc admin methods
    421 
    422     static CodePtr trampolineAt(CodeRef ref, Label label)
    423     {
    424         return CodePtr(AssemblerType::getRelocatedAddress(ref.m_code.dataLocation(), label.m_label));
    425     }
    426 
    427421    size_t size()
    428422    {
     
    480474        return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
    481475    }
     476   
     477    void beginUninterruptedSequence() { }
     478    void endUninterruptedSequence() { }
    482479
    483480protected:
  • trunk/JavaScriptCore/assembler/LinkBuffer.h

    r64608 r65042  
    5050class LinkBuffer : public Noncopyable {
    5151    typedef MacroAssemblerCodeRef CodeRef;
     52    typedef MacroAssemblerCodePtr CodePtr;
    5253    typedef MacroAssembler::Label Label;
    5354    typedef MacroAssembler::Jump Jump;
     
    5657    typedef MacroAssembler::DataLabel32 DataLabel32;
    5758    typedef MacroAssembler::DataLabelPtr DataLabelPtr;
     59    typedef MacroAssembler::JmpDst JmpDst;
     60#if ENABLE(BRANCH_COMPACTION)
     61    typedef MacroAssembler::LinkRecord LinkRecord;
     62    typedef MacroAssembler::JumpLinkType JumpLinkType;
     63#endif
    5864
    5965    enum LinkBufferState {
     
    6773    //       First, executablePool is copied into m_executablePool, then the initialization of
    6874    //       m_code uses m_executablePool, *not* executablePool, since this is no longer valid.
    69     LinkBuffer(MacroAssembler* masm, PassRefPtr<ExecutablePool> executablePool)
     75    // The linkOffset parameter should only be non-null when recompiling for exception info
     76    LinkBuffer(MacroAssembler* masm, PassRefPtr<ExecutablePool> executablePool, void* linkOffset)
    7077        : m_executablePool(executablePool)
    71         , m_code(masm->m_assembler.executableCopy(m_executablePool.get()))
    72         , m_size(masm->m_assembler.size())
     78        , m_size(0)
     79        , m_code(0)
     80        , m_assembler(masm)
    7381#ifndef NDEBUG
    7482        , m_state(StateInit)
    7583#endif
    7684    {
     85        linkCode(linkOffset);
    7786    }
    7887
     
    98107    {
    99108        ASSERT(call.isFlagSet(Call::Linkable));
     109        call.m_jmp = applyOffset(call.m_jmp);
    100110        MacroAssembler::linkCall(code(), call, function);
    101111    }
     
    103113    void link(Jump jump, CodeLocationLabel label)
    104114    {
     115        jump.m_jmp = applyOffset(jump.m_jmp);
    105116        MacroAssembler::linkJump(code(), jump, label);
    106117    }
     
    109120    {
    110121        for (unsigned i = 0; i < list.m_jumps.size(); ++i)
    111             MacroAssembler::linkJump(code(), list.m_jumps[i], label);
     122            link(list.m_jumps[i], label);
    112123    }
    113124
    114125    void patch(DataLabelPtr label, void* value)
    115126    {
    116         MacroAssembler::linkPointer(code(), label.m_label, value);
     127        JmpDst target = applyOffset(label.m_label);
     128        MacroAssembler::linkPointer(code(), target, value);
    117129    }
    118130
    119131    void patch(DataLabelPtr label, CodeLocationLabel value)
    120132    {
    121         MacroAssembler::linkPointer(code(), label.m_label, value.executableAddress());
     133        JmpDst target = applyOffset(label.m_label);
     134        MacroAssembler::linkPointer(code(), target, value.executableAddress());
    122135    }
    123136
     
    128141        ASSERT(call.isFlagSet(Call::Linkable));
    129142        ASSERT(!call.isFlagSet(Call::Near));
    130         return CodeLocationCall(MacroAssembler::getLinkerAddress(code(), call.m_jmp));
     143        return CodeLocationCall(MacroAssembler::getLinkerAddress(code(), applyOffset(call.m_jmp)));
    131144    }
    132145
     
    135148        ASSERT(call.isFlagSet(Call::Linkable));
    136149        ASSERT(call.isFlagSet(Call::Near));
    137         return CodeLocationNearCall(MacroAssembler::getLinkerAddress(code(), call.m_jmp));
     150        return CodeLocationNearCall(MacroAssembler::getLinkerAddress(code(), applyOffset(call.m_jmp)));
    138151    }
    139152
    140153    CodeLocationLabel locationOf(Label label)
    141154    {
    142         return CodeLocationLabel(MacroAssembler::getLinkerAddress(code(), label.m_label));
     155        return CodeLocationLabel(MacroAssembler::getLinkerAddress(code(), applyOffset(label.m_label)));
    143156    }
    144157
    145158    CodeLocationDataLabelPtr locationOf(DataLabelPtr label)
    146159    {
    147         return CodeLocationDataLabelPtr(MacroAssembler::getLinkerAddress(code(), label.m_label));
     160        return CodeLocationDataLabelPtr(MacroAssembler::getLinkerAddress(code(), applyOffset(label.m_label)));
    148161    }
    149162
    150163    CodeLocationDataLabel32 locationOf(DataLabel32 label)
    151164    {
    152         return CodeLocationDataLabel32(MacroAssembler::getLinkerAddress(code(), label.m_label));
     165        return CodeLocationDataLabel32(MacroAssembler::getLinkerAddress(code(), applyOffset(label.m_label)));
    153166    }
    154167
     
    157170    unsigned returnAddressOffset(Call call)
    158171    {
     172        call.m_jmp = applyOffset(call.m_jmp);
    159173        return MacroAssembler::getLinkerCallReturnOffset(call);
    160174    }
     
    170184        return CodeRef(m_code, m_executablePool, m_size);
    171185    }
     186
    172187    CodeLocationLabel finalizeCodeAddendum()
    173188    {
     
    177192    }
    178193
     194    CodePtr trampolineAt(Label label)
     195    {
     196        return CodePtr(MacroAssembler::AssemblerType_T::getRelocatedAddress(code(), applyOffset(label.m_label)));
     197    }
     198
    179199private:
     200    template <typename T> T applyOffset(T src)
     201    {
     202#if ENABLE(BRANCH_COMPACTION)
     203        src.m_offset -= m_assembler->executableOffsetFor(src.m_offset);
     204#endif
     205        return src;
     206    }
     207   
    180208    // Keep this private! - the underlying code should only be obtained externally via
    181209    // finalizeCode() or finalizeCodeAddendum().
     
    185213    }
    186214
     215    void linkCode(void* linkOffset)
     216    {
     217        UNUSED_PARAM(linkOffset);
     218        ASSERT(!m_code);
     219#if !ENABLE(BRANCH_COMPACTION)
     220        m_code = m_assembler->m_assembler.executableCopy(m_executablePool.get());
     221        m_size = m_assembler->size();
     222#else
     223        size_t initialSize = m_assembler->size();
     224        m_code = (uint8_t*)m_executablePool->alloc(initialSize);
     225        if (!m_code)
     226            return;
     227        ExecutableAllocator::makeWritable(m_code, m_assembler->size());
     228        uint8_t* inData = (uint8_t*)m_assembler->unlinkedCode();
     229        uint8_t* outData = reinterpret_cast<uint8_t*>(m_code);
     230        const uint8_t* linkBase = linkOffset ? reinterpret_cast<uint8_t*>(linkOffset) : outData;
     231        int readPtr = 0;
     232        int writePtr = 0;
     233        Vector<LinkRecord>& jumpsToLink = m_assembler->jumpsToLink();
     234        unsigned jumpCount = jumpsToLink.size();
     235        for (unsigned i = 0; i < jumpCount; ++i) {
     236            int offset = readPtr - writePtr;
     237            ASSERT(!(offset & 1));
     238           
     239            // Copy the instructions from the last jump to the current one.
     240            size_t regionSize = jumpsToLink[i].from() - readPtr;
     241            memcpy(outData + writePtr, inData + readPtr, regionSize);
     242            m_assembler->recordLinkOffsets(readPtr, jumpsToLink[i].from(), offset);
     243            readPtr += regionSize;
     244            writePtr += regionSize;
     245           
     246            // Calculate absolute address of the jump target, in the case of backwards
     247            // branches we need to be precise, forward branches we are pessimistic
     248            const uint8_t* target;
     249            if (jumpsToLink[i].to() >= jumpsToLink[i].from())
     250                target = linkBase + jumpsToLink[i].to() - offset; // Compensate for what we have collapsed so far
     251            else
     252                target = linkBase + jumpsToLink[i].to() - m_assembler->executableOffsetFor(jumpsToLink[i].to());
     253           
     254            JumpLinkType jumpLinkType = m_assembler->computeJumpType(jumpsToLink[i], linkBase + writePtr, target);
     255
     256            // Step back in the write stream
     257            int32_t delta = m_assembler->jumpSizeDelta(jumpLinkType);
     258            if (delta) {
     259                writePtr -= delta;
     260                m_assembler->recordLinkOffsets(jumpsToLink[i].from() - delta, readPtr, readPtr - writePtr);
     261            }
     262            jumpsToLink[i].setFrom(writePtr);
     263        }
     264        // Copy everything after the last jump
     265        memcpy(outData + writePtr, inData + readPtr, m_assembler->size() - readPtr);
     266        m_assembler->recordLinkOffsets(readPtr, m_assembler->size(), readPtr - writePtr);
     267       
     268        // Actually link everything (don't link if we've be given a linkoffset as it's a
     269        // waste of time: linkOffset is used for recompiling to get exception info)
     270        if (!linkOffset) {
     271            for (unsigned i = 0; i < jumpCount; ++i) {
     272                uint8_t* location = outData + jumpsToLink[i].from();
     273                uint8_t* target = outData + jumpsToLink[i].to() - m_assembler->executableOffsetFor(jumpsToLink[i].to());
     274                m_assembler->link(jumpsToLink[i], location, target);
     275            }
     276        }
     277
     278        jumpsToLink.clear();
     279        m_size = writePtr + m_assembler->size() - readPtr;
     280        m_executablePool->returnLastBytes(initialSize - m_size);
     281#endif
     282    }
     283
    187284    void performFinalization()
    188285    {
     
    197294
    198295    RefPtr<ExecutablePool> m_executablePool;
     296    size_t m_size;
    199297    void* m_code;
    200     size_t m_size;
     298    MacroAssembler* m_assembler;
    201299#ifndef NDEBUG
    202300    LinkBufferState m_state;
  • 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
  • trunk/JavaScriptCore/jit/ExecutableAllocator.h

    r64798 r65042  
    129129    }
    130130   
     131    void returnLastBytes(size_t count)
     132    {
     133        m_freePtr -= count;
     134    }
     135
    131136    ~ExecutablePool()
    132137    {
  • trunk/JavaScriptCore/jit/JIT.cpp

    r64608 r65042  
    7272}
    7373
    74 JIT::JIT(JSGlobalData* globalData, CodeBlock* codeBlock)
     74JIT::JIT(JSGlobalData* globalData, CodeBlock* codeBlock, void* linkerOffset)
    7575    : m_interpreter(globalData->interpreter)
    7676    , m_globalData(globalData)
     
    9090    , m_jumpTargetsPosition(0)
    9191#endif
     92    , m_linkerOffset(linkerOffset)
    9293{
    9394}
     
    512513    if (!executablePool)
    513514        return JITCode();
    514     LinkBuffer patchBuffer(this, executablePool.release());
     515    LinkBuffer patchBuffer(this, executablePool.release(), m_linkerOffset);
    515516    if (!patchBuffer.allocationSuccessful())
    516517        return JITCode();
  • trunk/JavaScriptCore/jit/JIT.h

    r64943 r65042  
    179179
    180180    public:
    181         static JITCode compile(JSGlobalData* globalData, CodeBlock* codeBlock, CodePtr* functionEntryArityCheck = 0)
    182         {
    183             return JIT(globalData, codeBlock).privateCompile(functionEntryArityCheck);
     181        static JITCode compile(JSGlobalData* globalData, CodeBlock* codeBlock, CodePtr* functionEntryArityCheck = 0, void* offsetBase = 0)
     182        {
     183            return JIT(globalData, codeBlock, offsetBase).privateCompile(functionEntryArityCheck);
    184184        }
    185185
     
    222222            if (!globalData->canUseJIT())
    223223                return;
    224             JIT jit(globalData);
     224            JIT jit(globalData, 0, 0);
    225225            jit.privateCompileCTIMachineTrampolines(executablePool, globalData, trampolines);
    226226        }
     
    230230            if (!globalData->canUseJIT())
    231231                return CodePtr();
    232             JIT jit(globalData);
     232            JIT jit(globalData, 0, 0);
    233233            return jit.privateCompileCTINativeCall(executablePool, globalData, func);
    234234        }
     
    260260        };
    261261
    262         JIT(JSGlobalData*, CodeBlock* = 0);
     262        JIT(JSGlobalData*, CodeBlock* = 0, void* = 0);
    263263
    264264        void privateCompileMainPass();
     
    667667#endif // USE(JSVALUE32_64)
    668668
    669 #if defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL
    670 #define BEGIN_UNINTERRUPTED_SEQUENCE(name) beginUninterruptedSequence(name ## InstructionSpace, name ## ConstantSpace)
    671 #define END_UNINTERRUPTED_SEQUENCE(name) endUninterruptedSequence(name ## InstructionSpace, name ## ConstantSpace)
     669#if (defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL)
     670#define BEGIN_UNINTERRUPTED_SEQUENCE(name) do { beginUninterruptedSequence(); beginUninterruptedSequence(name ## InstructionSpace, name ## ConstantSpace); } while (false)
     671#define END_UNINTERRUPTED_SEQUENCE(name) do { endUninterruptedSequence(name ## InstructionSpace, name ## ConstantSpace); endUninterruptedSequence(); } while (false)
    672672
    673673        void beginUninterruptedSequence(int, int);
     
    675675
    676676#else
    677 #define BEGIN_UNINTERRUPTED_SEQUENCE(name)
    678 #define END_UNINTERRUPTED_SEQUENCE(name)
     677#define BEGIN_UNINTERRUPTED_SEQUENCE(name)  do { beginUninterruptedSequence(); } while (false)
     678#define END_UNINTERRUPTED_SEQUENCE(name)  do { endUninterruptedSequence(); } while (false)
    679679#endif
    680680
     
    941941#endif
    942942#endif
     943        void* m_linkerOffset;
    943944        static CodePtr stringGetByValStubGenerator(JSGlobalData* globalData, ExecutablePool* pool);
    944945    } JIT_CLASS_ALIGNMENT;
  • trunk/JavaScriptCore/jit/JITArithmetic32_64.cpp

    r64176 r65042  
    13841384void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
    13851385{
     1386    UNUSED_PARAM(currentInstruction);
     1387    UNUSED_PARAM(iter);
    13861388#if ENABLE(JIT_USE_SOFT_MODULO)
    13871389    unsigned result = currentInstruction[1].u.operand;
  • trunk/JavaScriptCore/jit/JITOpcodes.cpp

    r64790 r65042  
    166166    if (!*executablePool)
    167167        CRASH();
    168     LinkBuffer patchBuffer(this, *executablePool);
     168    LinkBuffer patchBuffer(this, *executablePool, 0);
    169169    // We can't run without the JIT trampolines!
    170170    if (!patchBuffer.allocationSuccessful())
     
    185185    CodeRef finalCode = patchBuffer.finalizeCode();
    186186
    187     trampolines->ctiVirtualCallLink = trampolineAt(finalCode, virtualCallLinkBegin);
    188     trampolines->ctiVirtualConstructLink = trampolineAt(finalCode, virtualConstructLinkBegin);
    189     trampolines->ctiVirtualCall = trampolineAt(finalCode, virtualCallBegin);
    190     trampolines->ctiVirtualConstruct = trampolineAt(finalCode, virtualConstructBegin);
    191     trampolines->ctiNativeCall = trampolineAt(finalCode, nativeCallThunk);
    192     trampolines->ctiNativeConstruct = trampolineAt(finalCode, nativeConstructThunk);
     187    trampolines->ctiVirtualCallLink = patchBuffer.trampolineAt(virtualCallLinkBegin);
     188    trampolines->ctiVirtualConstructLink = patchBuffer.trampolineAt(virtualConstructLinkBegin);
     189    trampolines->ctiVirtualCall = patchBuffer.trampolineAt(virtualCallBegin);
     190    trampolines->ctiVirtualConstruct = patchBuffer.trampolineAt(virtualConstructBegin);
     191    trampolines->ctiNativeCall = patchBuffer.trampolineAt(nativeCallThunk);
     192    trampolines->ctiNativeConstruct = patchBuffer.trampolineAt(nativeConstructThunk);
    193193#if ENABLE(JIT_USE_SOFT_MODULO)
    194     trampolines->ctiSoftModulo = trampolineAt(finalCode, softModBegin);
     194    trampolines->ctiSoftModulo = patchBuffer.trampolineAt(softModBegin);
    195195#endif
    196196#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
    197     trampolines->ctiStringLengthTrampoline = trampolineAt(finalCode, stringLengthBegin);
     197    trampolines->ctiStringLengthTrampoline = patchBuffer.trampolineAt(stringLengthBegin);
    198198#endif
    199199}
  • trunk/JavaScriptCore/jit/JITOpcodes32_64.cpp

    r64790 r65042  
    164164    if (!*executablePool)
    165165        CRASH();
    166     LinkBuffer patchBuffer(this, *executablePool);
     166    LinkBuffer patchBuffer(this, *executablePool, 0);
    167167    // We can't run without the JIT trampolines!
    168168    if (!patchBuffer.allocationSuccessful())
     
    183183    CodeRef finalCode = patchBuffer.finalizeCode();
    184184
    185     trampolines->ctiVirtualCall = trampolineAt(finalCode, virtualCallBegin);
    186     trampolines->ctiVirtualConstruct = trampolineAt(finalCode, virtualConstructBegin);
    187     trampolines->ctiNativeCall = trampolineAt(finalCode, nativeCallThunk);
    188     trampolines->ctiNativeConstruct = trampolineAt(finalCode, nativeConstructThunk);
     185    trampolines->ctiVirtualCall = patchBuffer.trampolineAt(virtualCallBegin);
     186    trampolines->ctiVirtualConstruct = patchBuffer.trampolineAt(virtualConstructBegin);
     187    trampolines->ctiNativeCall = patchBuffer.trampolineAt(nativeCallThunk);
     188    trampolines->ctiNativeConstruct = patchBuffer.trampolineAt(nativeConstructThunk);
    189189#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
    190     trampolines->ctiStringLengthTrampoline = trampolineAt(finalCode, stringLengthBegin);
     190    trampolines->ctiStringLengthTrampoline = patchBuffer.trampolineAt(stringLengthBegin);
    191191#endif
    192192#if ENABLE(JIT_OPTIMIZE_CALL)
    193     trampolines->ctiVirtualCallLink = trampolineAt(finalCode, virtualCallLinkBegin);
    194     trampolines->ctiVirtualConstructLink = trampolineAt(finalCode, virtualConstructLinkBegin);
     193    trampolines->ctiVirtualCallLink = patchBuffer.trampolineAt(virtualCallLinkBegin);
     194    trampolines->ctiVirtualConstructLink = patchBuffer.trampolineAt(virtualConstructLinkBegin);
    195195#endif
    196196#if ENABLE(JIT_USE_SOFT_MODULO)
    197     trampolines->ctiSoftModulo = trampolineAt(finalCode, softModBegin);
     197    trampolines->ctiSoftModulo = patchBuffer.trampolineAt(softModBegin);
    198198#endif
    199199}
     
    363363
    364364    // All trampolines constructed! copy the code, link up calls, and set the pointers on the Machine object.
    365     LinkBuffer patchBuffer(this, executablePool);
     365    LinkBuffer patchBuffer(this, executablePool, 0);
    366366    // We can't continue if we can't call a function!
    367367    if (!patchBuffer.allocationSuccessful())
     
    369369
    370370    patchBuffer.link(nativeCall, FunctionPtr(func));
    371 
    372     CodeRef finalCode = patchBuffer.finalizeCode();
    373     return trampolineAt(finalCode, nativeCallThunk);
     371    patchBuffer.finalizeCode();
     372
     373    return patchBuffer.trampolineAt(nativeCallThunk);
    374374}
    375375
  • trunk/JavaScriptCore/jit/JITPropertyAccess.cpp

    r64943 r65042  
    7878    jit.ret();
    7979   
    80     LinkBuffer patchBuffer(&jit, pool);
     80    LinkBuffer patchBuffer(&jit, pool, 0);
    8181    // We can't run without the JIT trampolines!
    8282    if (!patchBuffer.allocationSuccessful())
     
    653653    Call failureCall = tailRecursiveCall();
    654654
    655     LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
     655    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
    656656    if (!patchBuffer.allocationSuccessful())
    657657        return false;
     
    744744    Jump success = jump();
    745745
    746     LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
     746    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
    747747    if (!patchBuffer.allocationSuccessful())
    748748        return false;
     
    810810        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
    811811    Jump success = jump();
    812     LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
     812    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
    813813    if (!patchBuffer.allocationSuccessful())
    814814        return false;
     
    873873    Jump success = jump();
    874874
    875     LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
     875    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
    876876    if (!patchBuffer.allocationSuccessful())
    877877        return false;
     
    951951    Jump success = jump();
    952952
    953     LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
     953    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
    954954    if (!patchBuffer.allocationSuccessful())
    955955        return false;
     
    10271027    Jump success = jump();
    10281028
    1029     LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
     1029    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
    10301030    if (!patchBuffer.allocationSuccessful())
    10311031        return false;
     
    11011101    Jump success = jump();
    11021102
    1103     LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
     1103    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
    11041104    if (!patchBuffer.allocationSuccessful())
    11051105        return false;
  • trunk/JavaScriptCore/jit/JITPropertyAccess32_64.cpp

    r64943 r65042  
    296296    jit.ret();
    297297   
    298     LinkBuffer patchBuffer(&jit, pool);
     298    LinkBuffer patchBuffer(&jit, pool, 0);
    299299    // We can't run without the JIT trampolines!
    300300    if (!patchBuffer.allocationSuccessful())
     
    657657    Call failureCall = tailRecursiveCall();
    658658   
    659     LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
     659    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
    660660    if (!patchBuffer.allocationSuccessful())
    661661        return false;
     
    753753    Jump success = jump();
    754754   
    755     LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
     755    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
    756756    if (!patchBuffer.allocationSuccessful())
    757757        return false;
     
    820820    Jump success = jump();
    821821   
    822     LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
     822    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
    823823    if (!patchBuffer.allocationSuccessful())
    824824        return false;
     
    887887    Jump success = jump();
    888888   
    889     LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
     889    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
    890890    if (!patchBuffer.allocationSuccessful())
    891891        return false;
     
    965965    Jump success = jump();
    966966   
    967     LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
     967    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
    968968    if (!patchBuffer.allocationSuccessful())
    969969        return false;
     
    10421042    Jump success = jump();
    10431043   
    1044     LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
     1044    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
    10451045    if (!patchBuffer.allocationSuccessful())
    10461046        return false;
     
    11161116    Jump success = jump();
    11171117   
    1118     LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
     1118    LinkBuffer patchBuffer(this, m_codeBlock->executablePool(), 0);
    11191119    if (!patchBuffer.allocationSuccessful())
    11201120        return false;
  • trunk/JavaScriptCore/jit/SpecializedThunkJIT.h

    r64608 r65042  
    130130        MacroAssemblerCodePtr finalize(MacroAssemblerCodePtr fallback)
    131131        {
    132             LinkBuffer patchBuffer(this, m_pool.get());
     132            LinkBuffer patchBuffer(this, m_pool.get(), 0);
    133133            // We can't continue if we can't call a function!
    134134            if (!patchBuffer.allocationSuccessful())
  • trunk/JavaScriptCore/runtime/Executable.cpp

    r64790 r65042  
    305305#if ENABLE(JIT)
    306306    if (globalData->canUseJIT()) {
    307         JITCode newJITCode = JIT::compile(globalData, newCodeBlock.get());
     307        JITCode newJITCode = JIT::compile(globalData, newCodeBlock.get(), 0, codeBlock->m_isConstructor ? generatedJITCodeForConstruct().start() : generatedJITCodeForCall().start());
    308308        if (!newJITCode) {
    309309            globalData->functionCodeBlockBeingReparsed = 0;
     
    338338#if ENABLE(JIT)
    339339    if (globalData->canUseJIT()) {
    340         JITCode newJITCode = JIT::compile(globalData, newCodeBlock.get());
     340        JITCode newJITCode = JIT::compile(globalData, newCodeBlock.get(), 0, generatedJITCodeForCall().start());
    341341        if (!newJITCode) {
    342342            globalData->functionCodeBlockBeingReparsed = 0;
  • trunk/JavaScriptCore/wtf/FastMalloc.cpp

    r64798 r65042  
    44554455    &FastMallocZone::log, &FastMallocZone::forceLock, &FastMallocZone::forceUnlock, &FastMallocZone::statistics
    44564456
    4457 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !OS(IOS)
     4457#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
    44584458    , 0 // zone_locked will not be called on the zone unless it advertises itself as version five or higher.
    44594459#endif
    4460 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) && !OS(IOS)
     4460#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
    44614461    , 0, 0, 0, 0 // These members will not be used unless the zone advertises itself as version seven or higher.
    44624462#endif
  • trunk/JavaScriptCore/wtf/Platform.h

    r64943 r65042  
    10951095#endif
    10961096
     1097#if CPU(ARM_THUMB2)
     1098#define ENABLE_BRANCH_COMPACTION 1
     1099#endif
     1100
    10971101#endif /* WTF_Platform_h */
  • trunk/JavaScriptCore/yarr/RegexJIT.cpp

    r64608 r65042  
    14731473        }
    14741474
    1475         LinkBuffer patchBuffer(this, executablePool.release());
     1475        LinkBuffer patchBuffer(this, executablePool.release(), 0);
    14761476        if (!patchBuffer.allocationSuccessful()) {
    14771477            m_shouldFallBack = true;
Note: See TracChangeset for help on using the changeset viewer.