Changeset 69743 in webkit


Ignore:
Timestamp:
Oct 13, 2010 11:45:26 PM (14 years ago)
Author:
commit-queue@webkit.org
Message:

2010-10-13 David Goodwin <david_goodwin@apple.com>

Reviewed by Oliver Hunt.

ARMv7 JIT should generated conditional branches when possible
https://bugs.webkit.org/show_bug.cgi?id=47384

Use different jump padding sizes for conditional and unconditional
jumps (12 bytes and 10 bytes respectively). This allows the JIT to
include the IT instruction as part of the conditional jump sequence
which in turn allows it to optimize away the IT using an ARMv7
conditional branch instruction. Use 2-byte B(T1) and 4-byte B(T3) for
conditional branches when displacement is in range. Also use IT/B(T4)
for conditional branch when displacement does not fit in B(T3).

For unconditional jump, instruction selection options are:
B(T2), B(T4), MOVW/MOVT/BX. For conditional jump, instruction selection
options are: B(T1), B(T3), IT/B(T4), ITTT/MOVW/MOVT/BX.

  • assembler/ARMv7Assembler.cpp:
  • assembler/ARMv7Assembler.h: (JSC::ARMv7Assembler::JmpSrc::JmpSrc): (JSC::ARMv7Assembler::ifThenElse): (JSC::ARMv7Assembler::jumpSizeDelta): (JSC::ARMv7Assembler::canCompact): (JSC::ARMv7Assembler::computeJumpType): (JSC::ARMv7Assembler::link): (JSC::ARMv7Assembler::canBeJumpT1): (JSC::ARMv7Assembler::canBeJumpT3): (JSC::ARMv7Assembler::canBeJumpT4): (JSC::ARMv7Assembler::linkJumpT1): (JSC::ARMv7Assembler::linkJumpT3): (JSC::ARMv7Assembler::linkJumpT4): (JSC::ARMv7Assembler::linkConditionalJumpT4): (JSC::ARMv7Assembler::linkBX): (JSC::ARMv7Assembler::linkConditionalBX): (JSC::ARMv7Assembler::linkJumpAbsolute):
  • assembler/LinkBuffer.h: (JSC::LinkBuffer::linkCode):
  • assembler/MacroAssemblerARMv7.h: (JSC::MacroAssemblerARMv7::canCompact): (JSC::MacroAssemblerARMv7::computeJumpType): (JSC::MacroAssemblerARMv7::jumpSizeDelta): (JSC::MacroAssemblerARMv7::jump): (JSC::MacroAssemblerARMv7::nearCall): (JSC::MacroAssemblerARMv7::call): (JSC::MacroAssemblerARMv7::ret): (JSC::MacroAssemblerARMv7::tailRecursiveCall): (JSC::MacroAssemblerARMv7::makeJump): (JSC::MacroAssemblerARMv7::makeBranch):
Location:
trunk/JavaScriptCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r69728 r69743  
     12010-10-13  David Goodwin  <david_goodwin@apple.com>
     2
     3        Reviewed by Oliver Hunt.
     4
     5        ARMv7 JIT should generated conditional branches when possible
     6        https://bugs.webkit.org/show_bug.cgi?id=47384
     7
     8        Use different jump padding sizes for conditional and unconditional
     9        jumps (12 bytes and 10 bytes respectively). This allows the JIT to
     10        include the IT instruction as part of the conditional jump sequence
     11        which in turn allows it to optimize away the IT using an ARMv7
     12        conditional branch instruction. Use 2-byte B(T1) and 4-byte B(T3) for
     13        conditional branches when displacement is in range. Also use IT/B(T4)
     14        for conditional branch when displacement does not fit in B(T3).
     15
     16        For unconditional jump, instruction selection options are:
     17        B(T2), B(T4), MOVW/MOVT/BX. For conditional jump, instruction selection
     18        options are: B(T1), B(T3), IT/B(T4), ITTT/MOVW/MOVT/BX.
     19
     20        * assembler/ARMv7Assembler.cpp:
     21        * assembler/ARMv7Assembler.h:
     22        (JSC::ARMv7Assembler::JmpSrc::JmpSrc):
     23        (JSC::ARMv7Assembler::ifThenElse):
     24        (JSC::ARMv7Assembler::jumpSizeDelta):
     25        (JSC::ARMv7Assembler::canCompact):
     26        (JSC::ARMv7Assembler::computeJumpType):
     27        (JSC::ARMv7Assembler::link):
     28        (JSC::ARMv7Assembler::canBeJumpT1):
     29        (JSC::ARMv7Assembler::canBeJumpT3):
     30        (JSC::ARMv7Assembler::canBeJumpT4):
     31        (JSC::ARMv7Assembler::linkJumpT1):
     32        (JSC::ARMv7Assembler::linkJumpT3):
     33        (JSC::ARMv7Assembler::linkJumpT4):
     34        (JSC::ARMv7Assembler::linkConditionalJumpT4):
     35        (JSC::ARMv7Assembler::linkBX):
     36        (JSC::ARMv7Assembler::linkConditionalBX):
     37        (JSC::ARMv7Assembler::linkJumpAbsolute):
     38        * assembler/LinkBuffer.h:
     39        (JSC::LinkBuffer::linkCode):
     40        * assembler/MacroAssemblerARMv7.h:
     41        (JSC::MacroAssemblerARMv7::canCompact):
     42        (JSC::MacroAssemblerARMv7::computeJumpType):
     43        (JSC::MacroAssemblerARMv7::jumpSizeDelta):
     44        (JSC::MacroAssemblerARMv7::jump):
     45        (JSC::MacroAssemblerARMv7::nearCall):
     46        (JSC::MacroAssemblerARMv7::call):
     47        (JSC::MacroAssemblerARMv7::ret):
     48        (JSC::MacroAssemblerARMv7::tailRecursiveCall):
     49        (JSC::MacroAssemblerARMv7::makeJump):
     50        (JSC::MacroAssemblerARMv7::makeBranch):
     51
    1522010-10-13  Fridrich Strba  <fridrich.strba@bluewin.ch>
    253
  • trunk/JavaScriptCore/assembler/ARMv7Assembler.cpp

    r69080 r69743  
    3333
    3434const int ARMv7Assembler::JumpSizes[] = { 0xffffffff, sizeof(uint16_t), sizeof(uint16_t),
    35     2 * sizeof(uint16_t), 2 * sizeof(uint16_t), 5 * sizeof(uint16_t) };
     35    2 * sizeof(uint16_t), 2 * sizeof(uint16_t), 3 * sizeof(uint16_t), 5 * sizeof(uint16_t), 6 * sizeof(uint16_t) };
     36const int ARMv7Assembler::JumpPaddingSizes[] = { 0, 5 * sizeof(uint16_t), 6 * sizeof(uint16_t),
     37    5 * sizeof(uint16_t), 6 * sizeof(uint16_t) };
    3638
    3739}
  • trunk/JavaScriptCore/assembler/ARMv7Assembler.h

    r69372 r69743  
    479479    } Condition;
    480480
    481     enum JumpType { JumpNoCondition, JumpCondition, JumpFullSize };
    482     enum JumpLinkType { LinkInvalid, LinkJumpT2, LinkConditionalJumpT2,
    483         LinkJumpT4, LinkConditionalJumpT4, LinkBX, JumpTypeCount };
    484     static const int JumpSizes[JumpTypeCount];
    485     enum { JumpPaddingSize = 5 * sizeof(uint16_t) };
     481    enum JumpType { JumpFixed, JumpNoCondition, JumpCondition, JumpNoConditionFixedSize, JumpConditionFixedSize, JumpTypeCount };
     482    enum JumpLinkType { LinkInvalid, LinkJumpT1, LinkJumpT2, LinkJumpT3,
     483        LinkJumpT4, LinkConditionalJumpT4, LinkBX, LinkConditionalBX, JumpLinkTypeCount };
     484    static const int JumpSizes[JumpLinkTypeCount];
     485    static const int JumpPaddingSizes[JumpTypeCount];
    486486    class LinkRecord {
    487487    public:
     
    504504        intptr_t m_from : 31;
    505505        intptr_t m_to : 31;
    506         JumpType m_type : 2;
    507         JumpLinkType m_linkType : 3;
     506        JumpType m_type : 3;
     507        JumpLinkType m_linkType : 4;
    508508        Condition m_condition : 16;
    509509    };
     
    525525            , m_type(type)
    526526        {
    527             ASSERT(m_type != JumpCondition);
     527            ASSERT(m_type == JumpFixed || m_type == JumpNoCondition || m_type == JumpNoConditionFixedSize);
    528528        }
    529529
     
    533533            , m_type(type)
    534534        {
    535             ASSERT(m_type == JumpCondition || m_type == JumpFullSize);
     535            ASSERT(m_type == JumpFixed || m_type == JumpCondition || m_type == JumpConditionFixedSize);
    536536        }
    537537
     
    630630
    631631    typedef enum {
     632        OP_B_T1         = 0xD000,
    632633        OP_B_T2         = 0xE000,
    633634        OP_AND_reg_T2   = 0xEA00,
     
    658659        OP_VMOV_IMM_T2  = 0xEEB0,
    659660        OP_VMRS         = 0xEEB0,
     661        OP_B_T3a        = 0xF000,
    660662        OP_B_T4a        = 0xF000,
    661663        OP_AND_imm_T1   = 0xF000,
     
    710712        OP_VSUB_T2b     = 0x0A40,
    711713        OP_NOP_T2b      = 0x8000,
     714        OP_B_T3b        = 0x8000,
    712715        OP_B_T4b        = 0x9000,
    713716    } OpcodeID2;
     
    746749            | (ifThenElseConditionBit(condition, inst4if) << 1)
    747750            | 1;
    748         ASSERT((condition != ConditionAL) || (mask & (mask - 1)));
     751        ASSERT((condition != ConditionAL) || !(mask & (mask - 1)));
    749752        return (condition << 4) | mask;
    750753    }
     
    754757            | (ifThenElseConditionBit(condition, inst3if) << 2)
    755758            | 2;
    756         ASSERT((condition != ConditionAL) || (mask & (mask - 1)));
     759        ASSERT((condition != ConditionAL) || !(mask & (mask - 1)));
    757760        return (condition << 4) | mask;
    758761    }
     
    761764        int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
    762765            | 4;
    763         ASSERT((condition != ConditionAL) || (mask & (mask - 1)));
     766        ASSERT((condition != ConditionAL) || !(mask & (mask - 1)));
    764767        return (condition << 4) | mask;
    765768    }
     
    768771    {
    769772        int mask = 8;
    770         ASSERT((condition != ConditionAL) || (mask & (mask - 1)));
    771773        return (condition << 4) | mask;
    772774    }
     
    16651667    }
    16661668   
    1667     int jumpSizeDelta(JumpLinkType jumpLinkType) { return JumpPaddingSize - JumpSizes[jumpLinkType]; }
     1669    int jumpSizeDelta(JumpType jumpType, JumpLinkType jumpLinkType) { return JumpPaddingSizes[jumpType] - JumpSizes[jumpLinkType]; }
    16681670   
    16691671    // Assembler admin methods:
     
    16791681    }
    16801682
     1683    bool canCompact(JumpType jumpType)
     1684    {
     1685        // The following cannot be compacted:
     1686        //   JumpFixed: represents custom jump sequence
     1687        //   JumpNoConditionFixedSize: represents unconditional jump that must remain a fixed size
     1688        //   JumpConditionFixedSize: represents conditional jump that must remain a fixed size
     1689        return (jumpType == JumpNoCondition) || (jumpType == JumpCondition);
     1690    }
     1691   
     1692    JumpLinkType computeJumpType(JumpType jumpType, const uint8_t* from, const uint8_t* to)
     1693    {
     1694        if (jumpType == JumpFixed)
     1695            return LinkInvalid;
     1696       
     1697        // for patchable jump we must leave space for the longest code sequence
     1698        if (jumpType == JumpNoConditionFixedSize)
     1699            return LinkBX;
     1700        if (jumpType == JumpConditionFixedSize)
     1701            return LinkConditionalBX;
     1702       
     1703        const int paddingSize = JumpPaddingSizes[jumpType];
     1704        bool mayTriggerErrata = false;
     1705       
     1706        if (jumpType == JumpCondition) {
     1707            // 2-byte conditional T1
     1708            const uint16_t* jumpT1Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkJumpT1]));
     1709            if (canBeJumpT1(jumpT1Location, to))
     1710                return LinkJumpT1;
     1711            // 4-byte conditional T3
     1712            const uint16_t* jumpT3Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkJumpT3]));
     1713            if (canBeJumpT3(jumpT3Location, to, mayTriggerErrata)) {
     1714                if (!mayTriggerErrata)
     1715                    return LinkJumpT3;
     1716            }
     1717            // 4-byte conditional T4 with IT
     1718            const uint16_t* conditionalJumpT4Location =
     1719            reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkConditionalJumpT4]));
     1720            if (canBeJumpT4(conditionalJumpT4Location, to, mayTriggerErrata)) {
     1721                if (!mayTriggerErrata)
     1722                    return LinkConditionalJumpT4;
     1723            }
     1724        } else {
     1725            // 2-byte unconditional T2
     1726            const uint16_t* jumpT2Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkJumpT2]));
     1727            if (canBeJumpT2(jumpT2Location, to))
     1728                return LinkJumpT2;
     1729            // 4-byte unconditional T4
     1730            const uint16_t* jumpT4Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JumpSizes[LinkJumpT4]));
     1731            if (canBeJumpT4(jumpT4Location, to, mayTriggerErrata)) {
     1732                if (!mayTriggerErrata)
     1733                    return LinkJumpT4;
     1734            }
     1735            // use long jump sequence
     1736            return LinkBX;
     1737        }
     1738       
     1739        ASSERT(jumpType == JumpCondition);
     1740        return LinkConditionalBX;
     1741    }
     1742   
    16811743    JumpLinkType computeJumpType(LinkRecord& record, const uint8_t* from, const uint8_t* to)
    16821744    {
    1683         if (record.type() >= JumpFullSize) {
    1684             record.setLinkType(LinkBX);
    1685             return LinkBX;
    1686         }
    1687         const uint16_t* jumpT2Location = reinterpret_cast<const uint16_t*>(from  - (JumpPaddingSize - JumpSizes[LinkJumpT2]));
    1688         if (canBeJumpT2(jumpT2Location, to)) {
    1689             if (record.type() == JumpCondition) {
    1690                 record.setLinkType(LinkConditionalJumpT2);
    1691                 return LinkConditionalJumpT2;
    1692             }
    1693             record.setLinkType(LinkJumpT2);
    1694             return LinkJumpT2;
    1695         }
    1696         bool mayTriggerErrata = false;
    1697         const uint16_t* jumpT4Location = reinterpret_cast<const uint16_t*>(from  - (JumpPaddingSize - JumpSizes[LinkJumpT4]));
    1698         if (!canBeJumpT4(jumpT4Location, to, mayTriggerErrata)) {
    1699             record.setLinkType(LinkBX);
    1700             return LinkBX;
    1701         }
    1702         if (mayTriggerErrata) {
    1703             record.setLinkType(LinkBX);
    1704             return LinkBX;
    1705         }
    1706         if (record.type() == JumpCondition) {
    1707             record.setLinkType(LinkConditionalJumpT4);
    1708             return LinkConditionalJumpT4;
    1709         }
    1710         record.setLinkType(LinkJumpT4);
    1711         return LinkJumpT4;
    1712     }
    1713 
     1745        JumpLinkType linkType = computeJumpType(record.type(), from, to);
     1746        record.setLinkType(linkType);
     1747        return linkType;
     1748    }
     1749   
    17141750    void recordLinkOffsets(int32_t regionStart, int32_t regionEnd, int32_t offset)
    17151751    {
     
    17291765    void link(LinkRecord& record, uint8_t* from, uint8_t* to)
    17301766    {
    1731         JumpLinkType linkType = record.linkType();
    1732         ASSERT(linkType != LinkInvalid);
    1733         if ((linkType == LinkConditionalJumpT2) || (linkType == LinkConditionalJumpT4)) {
    1734             uint16_t* itttLocation = reinterpret_cast<uint16_t*>(from - JumpSizes[linkType] - 2);
    1735             itttLocation[0] = ifThenElse(record.condition()) | OP_IT;
    1736         }
    1737         switch (linkType) {
     1767        switch (record.linkType()) {
     1768        case LinkJumpT1:
     1769            linkJumpT1(record.condition(), reinterpret_cast<uint16_t*>(from), to);
     1770            break;
    17381771        case LinkJumpT2:
    1739         case LinkConditionalJumpT2:
    17401772            linkJumpT2(reinterpret_cast<uint16_t*>(from), to);
    17411773            break;
     1774        case LinkJumpT3:
     1775            linkJumpT3(record.condition(), reinterpret_cast<uint16_t*>(from), to);
     1776            break;
    17421777        case LinkJumpT4:
     1778            linkJumpT4(reinterpret_cast<uint16_t*>(from), to);
     1779            break;
    17431780        case LinkConditionalJumpT4:
    1744             linkJumpT4(reinterpret_cast<uint16_t*>(from), to);
     1781            linkConditionalJumpT4(record.condition(), reinterpret_cast<uint16_t*>(from), to);
     1782            break;
     1783        case LinkConditionalBX:
     1784            linkConditionalBX(record.condition(), reinterpret_cast<uint16_t*>(from), to);
    17451785            break;
    17461786        case LinkBX:
     
    19702010    }
    19712011
     2012    static bool canBeJumpT1(const uint16_t* instruction, const void* target)
     2013    {
     2014        ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
     2015        ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
     2016       
     2017        intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
     2018        // It does not appear to be documented in the ARM ARM (big surprise), but
     2019        // for OP_B_T1 the branch displacement encoded in the instruction is 2
     2020        // less than the actual displacement.
     2021        relative -= 2;
     2022        return ((relative << 23) >> 23) == relative;
     2023    }
     2024   
    19722025    static bool canBeJumpT2(const uint16_t* instruction, const void* target)
    19732026    {
     
    19812034        relative -= 2;
    19822035        return ((relative << 20) >> 20) == relative;
     2036    }
     2037   
     2038    static bool canBeJumpT3(const uint16_t* instruction, const void* target, bool& mayTriggerErrata)
     2039    {
     2040        ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
     2041        ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
     2042       
     2043        intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
     2044        // From Cortex-A8 errata:
     2045        // If the 32-bit Thumb-2 branch instruction spans two 4KiB regions and
     2046        // the target of the branch falls within the first region it is
     2047        // possible for the processor to incorrectly determine the branch
     2048        // instruction, and it is also possible in some cases for the processor
     2049        // to enter a deadlock state.
     2050        // The instruction is spanning two pages if it ends at an address ending 0x002
     2051        bool spansTwo4K = ((reinterpret_cast<intptr_t>(instruction) & 0xfff) == 0x002);
     2052        mayTriggerErrata = spansTwo4K;
     2053        // The target is in the first page if the jump branch back by [3..0x1002] bytes
     2054        bool targetInFirstPage = (relative >= -0x1002) && (relative < -2);
     2055        bool wouldTriggerA8Errata = spansTwo4K && targetInFirstPage;
     2056        return ((relative << 11) >> 11) == relative && !wouldTriggerA8Errata;
    19832057    }
    19842058   
     
    20032077        return ((relative << 7) >> 7) == relative && !wouldTriggerA8Errata;
    20042078    }
    2005 
    2006     static void linkBX(uint16_t* instruction, void* target)
    2007     {
    2008         linkJumpAbsolute(instruction, target);
    2009     }
    2010    
    2011     static void linkJumpT4(uint16_t* instruction, void* target)
     2079   
     2080    void linkJumpT1(Condition cond, uint16_t* instruction, void* target)
    20122081    {
    20132082        // FIMXE: this should be up in the MacroAssembler layer. :-(       
    20142083        ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
    20152084        ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
     2085        ASSERT(canBeJumpT1(instruction, target));
    20162086       
    20172087        intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
    2018         bool scratch;
    2019         UNUSED_PARAM(scratch);
    2020         ASSERT(canBeJumpT4(instruction, target, scratch));
    2021         // ARM encoding for the top two bits below the sign bit is 'peculiar'.
    2022         if (relative >= 0)
    2023             relative ^= 0xC00000;
    2024 
     2088        // It does not appear to be documented in the ARM ARM (big surprise), but
     2089        // for OP_B_T1 the branch displacement encoded in the instruction is 2
     2090        // less than the actual displacement.
     2091        relative -= 2;
     2092       
    20252093        // All branch offsets should be an even distance.
    20262094        ASSERT(!(relative & 1));
    2027         instruction[-2] = OP_B_T4a | ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12);
    2028         instruction[-1] = OP_B_T4b | ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1);
    2029     }
    2030 
     2095        instruction[-1] = OP_B_T1 | ((cond & 0xf) << 8) | ((relative & 0x1fe) >> 1);
     2096    }
     2097   
    20312098    static void linkJumpT2(uint16_t* instruction, void* target)
    20322099    {
     
    20472114    }
    20482115   
    2049     static void linkJumpAbsolute(uint16_t* instruction, void* target)
     2116    void linkJumpT3(Condition cond, uint16_t* instruction, void* target)
    20502117    {
    20512118        // FIMXE: this should be up in the MacroAssembler layer. :-(
    20522119        ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
    20532120        ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
    2054 
     2121        bool scratch;
     2122        UNUSED_PARAM(scratch);
     2123        ASSERT(canBeJumpT3(instruction, target, scratch));
     2124       
     2125        intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
     2126       
     2127        // All branch offsets should be an even distance.
     2128        ASSERT(!(relative & 1));
     2129        instruction[-2] = OP_B_T3a | ((relative & 0x100000) >> 10) | ((cond & 0xf) << 6) | ((relative & 0x3f000) >> 12);
     2130        instruction[-1] = OP_B_T3b | ((relative & 0x80000) >> 8) | ((relative & 0x40000) >> 5) | ((relative & 0xffe) >> 1);
     2131    }
     2132   
     2133    static void linkJumpT4(uint16_t* instruction, void* target)
     2134    {
     2135        // FIMXE: this should be up in the MacroAssembler layer. :-(       
     2136        ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
     2137        ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
     2138        bool scratch;
     2139        UNUSED_PARAM(scratch);
     2140        ASSERT(canBeJumpT4(instruction, target, scratch));
     2141       
     2142        intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
     2143        // ARM encoding for the top two bits below the sign bit is 'peculiar'.
     2144        if (relative >= 0)
     2145            relative ^= 0xC00000;
     2146       
     2147        // All branch offsets should be an even distance.
     2148        ASSERT(!(relative & 1));
     2149        instruction[-2] = OP_B_T4a | ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12);
     2150        instruction[-1] = OP_B_T4b | ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1);
     2151    }
     2152   
     2153    void linkConditionalJumpT4(Condition cond, uint16_t* instruction, void* target)
     2154    {
     2155        // FIMXE: this should be up in the MacroAssembler layer. :-(       
     2156        ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
     2157        ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
     2158       
     2159        instruction[-3] = ifThenElse(cond) | OP_IT;
     2160        linkJumpT4(instruction, target);
     2161    }
     2162   
     2163    static void linkBX(uint16_t* instruction, void* target)
     2164    {
     2165        // FIMXE: this should be up in the MacroAssembler layer. :-(
     2166        ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
     2167        ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
     2168       
     2169        const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip;
     2170        ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) + 1));
     2171        ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) >> 16));
     2172        instruction[-5] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16);
     2173        instruction[-4] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, lo16);
     2174        instruction[-3] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16);
     2175        instruction[-2] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16);
     2176        instruction[-1] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3);
     2177    }
     2178   
     2179    void linkConditionalBX(Condition cond, uint16_t* instruction, void* target)
     2180    {
     2181        // FIMXE: this should be up in the MacroAssembler layer. :-(       
     2182        ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
     2183        ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
     2184       
     2185        linkBX(instruction, target);
     2186        instruction[-6] = ifThenElse(cond, true, true) | OP_IT;
     2187    }
     2188   
     2189    static void linkJumpAbsolute(uint16_t* instruction, void* target)
     2190    {
     2191        // FIMXE: this should be up in the MacroAssembler layer. :-(
     2192        ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
     2193        ASSERT(!(reinterpret_cast<intptr_t>(target) & 1));
     2194       
    20552195        ASSERT((isMOV_imm_T3(instruction - 5) && isMOVT(instruction - 3) && isBX(instruction - 1))
    2056             || (isNOP_T1(instruction - 5) && isNOP_T2(instruction - 4) && isB(instruction - 2)));
    2057 
    2058         intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction));
     2196               || (isNOP_T1(instruction - 5) && isNOP_T2(instruction - 4) && isB(instruction - 2)));
     2197       
    20592198        bool scratch;
    20602199        if (canBeJumpT4(instruction, target, scratch)) {
    2061             // ARM encoding for the top two bits below the sign bit is 'peculiar'.
    2062             if (relative >= 0)
    2063                 relative ^= 0xC00000;
    2064 
    2065             // All branch offsets should be an even distance.
    2066             ASSERT(!(relative & 1));
    20672200            // There may be a better way to fix this, but right now put the NOPs first, since in the
    20682201            // case of an conditional branch this will be coming after an ITTT predicating *three*
     
    20732206            instruction[-4] = OP_NOP_T2a;
    20742207            instruction[-3] = OP_NOP_T2b;
    2075             instruction[-2] = OP_B_T4a | ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12);
    2076             instruction[-1] = OP_B_T4b | ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1);
     2208            linkJumpT4(instruction, target);
    20772209        } else {
    20782210            const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip;
     
    20862218        }
    20872219    }
    2088 
     2220   
    20892221    static uint16_t twoWordOp5i6Imm4Reg4EncodedImmFirst(uint16_t op, ARMThumbImmediate imm)
    20902222    {
  • trunk/JavaScriptCore/assembler/LinkBuffer.h

    r66150 r69743  
    11/*
    2  * Copyright (C) 2009 Apple Inc. All rights reserved.
     2 * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    236236           
    237237            JumpLinkType jumpLinkType = m_assembler->computeJumpType(jumpsToLink[i], linkBase + writePtr, target);
    238 
    239             // Step back in the write stream
    240             int32_t delta = m_assembler->jumpSizeDelta(jumpLinkType);
    241             if (delta) {
    242                 writePtr -= delta;
    243                 m_assembler->recordLinkOffsets(jumpsToLink[i].from() - delta, readPtr, readPtr - writePtr);
     238            // Compact branch if we can...
     239            if (m_assembler->canCompact(jumpsToLink[i].type())) {
     240                // Step back in the write stream
     241                int32_t delta = m_assembler->jumpSizeDelta(jumpsToLink[i].type(), jumpLinkType);
     242                if (delta) {
     243                    writePtr -= delta;
     244                    m_assembler->recordLinkOffsets(jumpsToLink[i].from() - delta, readPtr, readPtr - writePtr);
     245                }
    244246            }
    245247            jumpsToLink[i].setFrom(writePtr);
  • trunk/JavaScriptCore/assembler/MacroAssemblerARMv7.h

    r65042 r69743  
    11/*
    2  * Copyright (C) 2009 Apple Inc. All rights reserved.
     2 * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
    33 * Copyright (C) 2010 University of Szeged
    44 *
     
    4747public:
    4848    typedef ARMv7Assembler::LinkRecord LinkRecord;
     49    typedef ARMv7Assembler::JumpType JumpType;
    4950    typedef ARMv7Assembler::JumpLinkType JumpLinkType;
    5051
     
    5859    Vector<LinkRecord>& jumpsToLink() { return m_assembler.jumpsToLink(); }
    5960    void* unlinkedCode() { return m_assembler.unlinkedCode(); }
     61    bool canCompact(JumpType jumpType) { return m_assembler.canCompact(jumpType); }
     62    JumpLinkType computeJumpType(JumpType jumpType, const uint8_t* from, const uint8_t* to) { return m_assembler.computeJumpType(jumpType, from, to); }
    6063    JumpLinkType computeJumpType(LinkRecord& record, const uint8_t* from, const uint8_t* to) { return m_assembler.computeJumpType(record, from, to); }
    6164    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); }
     65    int jumpSizeDelta(JumpType jumpType, JumpLinkType jumpLinkType) { return m_assembler.jumpSizeDelta(jumpType, jumpLinkType); }
    6366    void link(LinkRecord& record, uint8_t* from, uint8_t* to) { return m_assembler.link(record, from, to); }
    6467
     
    987990    void jump(RegisterID target)
    988991    {
    989         m_assembler.bx(target, inUninterruptedSequence() ? ARMv7Assembler::JumpFullSize : ARMv7Assembler::JumpNoCondition);
     992        m_assembler.bx(target, ARMv7Assembler::JumpFixed);
    990993    }
    991994
     
    994997    {
    995998        load32(address, dataTempRegister);
    996         m_assembler.bx(dataTempRegister, inUninterruptedSequence() ? ARMv7Assembler::JumpFullSize : ARMv7Assembler::JumpNoCondition);
     999        m_assembler.bx(dataTempRegister, ARMv7Assembler::JumpFixed);
    9971000    }
    9981001
     
    10831086    {
    10841087        moveFixedWidthEncoding(Imm32(0), dataTempRegister);
    1085         return Call(m_assembler.blx(dataTempRegister, ARMv7Assembler::JumpFullSize), Call::LinkableNear);
     1088        return Call(m_assembler.blx(dataTempRegister, ARMv7Assembler::JumpFixed), Call::LinkableNear);
    10861089    }
    10871090
     
    10891092    {
    10901093        moveFixedWidthEncoding(Imm32(0), dataTempRegister);
    1091         return Call(m_assembler.blx(dataTempRegister, ARMv7Assembler::JumpFullSize), Call::Linkable);
     1094        return Call(m_assembler.blx(dataTempRegister, ARMv7Assembler::JumpFixed), Call::Linkable);
    10921095    }
    10931096
    10941097    Call call(RegisterID target)
    10951098    {
    1096         return Call(m_assembler.blx(target, ARMv7Assembler::JumpFullSize), Call::None);
     1099        return Call(m_assembler.blx(target, ARMv7Assembler::JumpFixed), Call::None);
    10971100    }
    10981101
     
    11001103    {
    11011104        load32(address, dataTempRegister);
    1102         return Call(m_assembler.blx(dataTempRegister, ARMv7Assembler::JumpFullSize), Call::None);
     1105        return Call(m_assembler.blx(dataTempRegister, ARMv7Assembler::JumpFixed), Call::None);
    11031106    }
    11041107
    11051108    void ret()
    11061109    {
    1107         m_assembler.bx(linkRegister, ARMv7Assembler::JumpFullSize);
     1110        m_assembler.bx(linkRegister, ARMv7Assembler::JumpFixed);
    11081111    }
    11091112
     
    12051208        // Like a normal call, but don't link.
    12061209        moveFixedWidthEncoding(Imm32(0), dataTempRegister);
    1207         return Call(m_assembler.bx(dataTempRegister, ARMv7Assembler::JumpFullSize), Call::Linkable);
     1210        return Call(m_assembler.bx(dataTempRegister, ARMv7Assembler::JumpFixed), Call::Linkable);
    12081211    }
    12091212
     
    12291232    {
    12301233        moveFixedWidthEncoding(Imm32(0), dataTempRegister);
    1231         return m_assembler.bx(dataTempRegister, inUninterruptedSequence() ? ARMv7Assembler::JumpFullSize : ARMv7Assembler::JumpNoCondition);
     1234        return m_assembler.bx(dataTempRegister, inUninterruptedSequence() ? ARMv7Assembler::JumpNoConditionFixedSize : ARMv7Assembler::JumpNoCondition);
    12321235    }
    12331236
     
    12361239        m_assembler.it(cond, true, true);
    12371240        moveFixedWidthEncoding(Imm32(0), dataTempRegister);
    1238         return m_assembler.bx(dataTempRegister, inUninterruptedSequence() ? ARMv7Assembler::JumpFullSize : ARMv7Assembler::JumpCondition, cond);
     1241        return m_assembler.bx(dataTempRegister, inUninterruptedSequence() ? ARMv7Assembler::JumpConditionFixedSize : ARMv7Assembler::JumpCondition, cond);
    12391242    }
    12401243    ARMv7Assembler::JmpSrc makeBranch(Condition cond) { return makeBranch(armV7Condition(cond)); }
Note: See TracChangeset for help on using the changeset viewer.