Changeset 50255 in webkit for trunk/JavaScriptCore
- Timestamp:
- Oct 28, 2009, 6:40:09 PM (16 years ago)
- Location:
- trunk/JavaScriptCore
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r50254 r50255 1 2009-10-28 Gavin Barraclough <[email protected]> 2 3 Reviewed by Oliver Hunt. 4 5 JSC JIT on ARMv7 cannot link jumps >16Mb range 6 https://bugs.webkit.org/show_bug.cgi?id=30891 7 8 Start planing all relative jumps as move-32-bit-immediate-to-register-BX. 9 In the cases where the jump would fall within a relative jump range, use a relative jump. 10 11 * JavaScriptCore.xcodeproj/project.pbxproj: 12 * assembler/ARMv7Assembler.h: 13 (JSC::ARMv7Assembler::~ARMv7Assembler): 14 (JSC::ARMv7Assembler::LinkRecord::LinkRecord): 15 (JSC::ARMv7Assembler::): 16 (JSC::ARMv7Assembler::executableCopy): 17 (JSC::ARMv7Assembler::linkJump): 18 (JSC::ARMv7Assembler::relinkJump): 19 (JSC::ARMv7Assembler::setInt32): 20 (JSC::ARMv7Assembler::isB): 21 (JSC::ARMv7Assembler::isBX): 22 (JSC::ARMv7Assembler::isMOV_imm_T3): 23 (JSC::ARMv7Assembler::isMOVT): 24 (JSC::ARMv7Assembler::isNOP_T1): 25 (JSC::ARMv7Assembler::isNOP_T2): 26 (JSC::ARMv7Assembler::linkJumpAbsolute): 27 (JSC::ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmFirst): 28 (JSC::ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmSecond): 29 (JSC::ARMv7Assembler::ARMInstructionFormatter::twoWordOp5i6Imm4Reg4EncodedImm): 30 * assembler/MacroAssemblerARMv7.h: 31 (JSC::MacroAssemblerARMv7::makeJump): 32 (JSC::MacroAssemblerARMv7::makeBranch): 33 * jit/JIT.h: 34 * wtf/Platform.h: 35 1 36 2009-10-28 Oliver Hunt <[email protected]> 2 37 -
trunk/JavaScriptCore/assembler/ARMv7Assembler.h
r48525 r50255 408 408 class ARMv7Assembler { 409 409 public: 410 ~ARMv7Assembler() 411 { 412 ASSERT(m_jumpsToLink.isEmpty()); 413 } 414 410 415 typedef ARMRegisters::RegisterID RegisterID; 411 416 typedef ARMRegisters::FPRegisterID FPRegisterID; … … 477 482 478 483 private: 484 485 struct LinkRecord { 486 LinkRecord(intptr_t from, intptr_t to) 487 : from(from) 488 , to(to) 489 { 490 } 491 492 intptr_t from; 493 intptr_t to; 494 }; 479 495 480 496 // ARMv7, Appx-A.6.3 … … 575 591 OP_BKPT = 0xBE00, 576 592 OP_IT = 0xBF00, 593 OP_NOP_T1 = 0xBF00, 577 594 } OpcodeID; 578 595 … … 609 626 OP_SUB_imm_T4 = 0xF2A0, 610 627 OP_MOVT = 0xF2C0, 628 OP_NOP_T2a = 0xF3AF, 611 629 OP_LDRH_reg_T2 = 0xF830, 612 630 OP_LDRH_imm_T3 = 0xF830, … … 627 645 typedef enum { 628 646 OP_B_T4b = 0x9000, 647 OP_NOP_T2b = 0x8000, 629 648 } OpcodeID2; 630 649 … … 1482 1501 { 1483 1502 void* copy = m_formatter.executableCopy(allocator); 1503 1504 unsigned jumpCount = m_jumpsToLink.size(); 1505 for (unsigned i = 0; i < jumpCount; ++i) { 1506 uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(copy) + m_jumpsToLink[i].from); 1507 uint16_t* target = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(copy) + m_jumpsToLink[i].to); 1508 linkJumpAbsolute(location, target); 1509 } 1510 m_jumpsToLink.clear(); 1511 1484 1512 ASSERT(copy); 1485 1513 return copy; … … 1504 1532 ASSERT(to.m_offset != -1); 1505 1533 ASSERT(from.m_offset != -1); 1506 1507 uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(m_formatter.data()) + from.m_offset); 1508 intptr_t relative = to.m_offset - from.m_offset; 1509 1510 linkWithOffset(location, relative); 1534 m_jumpsToLink.append(LinkRecord(from.m_offset, to.m_offset)); 1511 1535 } 1512 1536 … … 1516 1540 1517 1541 uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset); 1518 intptr_t relative = reinterpret_cast<intptr_t>(to) - reinterpret_cast<intptr_t>(location); 1519 1520 linkWithOffset(location, relative); 1542 linkJumpAbsolute(location, to); 1521 1543 } 1522 1544 … … 1542 1564 ASSERT(!(reinterpret_cast<intptr_t>(to) & 1)); 1543 1565 1544 intptr_t relative = reinterpret_cast<intptr_t>(to) - reinterpret_cast<intptr_t>(from); 1545 linkWithOffset(reinterpret_cast<uint16_t*>(from), relative); 1546 1547 ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(from) - 2, 2 * sizeof(uint16_t)); 1566 linkJumpAbsolute(reinterpret_cast<uint16_t*>(from), to); 1567 1568 ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(from) - 5, 5 * sizeof(uint16_t)); 1548 1569 } 1549 1570 … … 1614 1635 { 1615 1636 uint16_t* location = reinterpret_cast<uint16_t*>(code); 1616 1617 uint16_t lo16 = value; 1618 uint16_t hi16 = value >> 16;1619 1620 spliceHi5(location - 4, lo16);1621 spliceLo11(location - 3, lo16);1622 spliceHi5(location - 2, hi16);1623 spliceLo11(location - 1, hi16);1637 ASSERT(isMOV_imm_T3(location - 4) && isMOVT(location - 2)); 1638 1639 ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(value)); 1640 ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(value >> 16)); 1641 location[-4] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16); 1642 location[-3] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-3] >> 8) & 0xf, lo16); 1643 location[-2] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16); 1644 location[-1] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-1] >> 8) & 0xf, hi16); 1624 1645 1625 1646 ExecutableAllocator::cacheFlush(location - 4, 4 * sizeof(uint16_t)); … … 1631 1652 } 1632 1653 1633 // Linking & patching: 1634 // This method assumes that the JmpSrc being linked is a T4 b instruction. 1635 static void linkWithOffset(uint16_t* instruction, intptr_t relative) 1636 { 1637 // Currently branches > 16m = mostly deathy. 1638 if (((relative << 7) >> 7) != relative) { 1639 // FIXME: This CRASH means we cannot turn the JIT on by default on arm-v7. 1640 fprintf(stderr, "Error: Cannot link T4b.\n"); 1641 CRASH(); 1642 } 1643 1644 // ARM encoding for the top two bits below the sign bit is 'peculiar'. 1645 if (relative >= 0) 1646 relative ^= 0xC00000; 1647 1648 // All branch offsets should be an even distance. 1649 ASSERT(!(relative & 1)); 1650 1651 int word1 = ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12); 1652 int word2 = ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1); 1653 1654 instruction[-2] = OP_B_T4a | word1; 1655 instruction[-1] = OP_B_T4b | word2; 1656 } 1657 1658 // These functions can be used to splice 16-bit immediates back into previously generated instructions. 1659 static void spliceHi5(uint16_t* where, uint16_t what) 1660 { 1661 uint16_t pattern = (what >> 12) | ((what & 0x0800) >> 1); 1662 *where = (*where & 0xFBF0) | pattern; 1663 } 1664 static void spliceLo11(uint16_t* where, uint16_t what) 1665 { 1666 uint16_t pattern = ((what & 0x0700) << 4) | (what & 0x00FF); 1667 *where = (*where & 0x8F00) | pattern; 1654 static bool isB(void* address) 1655 { 1656 uint16_t* instruction = static_cast<uint16_t*>(address); 1657 return ((instruction[0] & 0xf800) == OP_B_T4a) && ((instruction[1] & 0xd000) == OP_B_T4b); 1658 } 1659 1660 static bool isBX(void* address) 1661 { 1662 uint16_t* instruction = static_cast<uint16_t*>(address); 1663 return (instruction[0] & 0xff87) == OP_BX; 1664 } 1665 1666 static bool isMOV_imm_T3(void* address) 1667 { 1668 uint16_t* instruction = static_cast<uint16_t*>(address); 1669 return ((instruction[0] & 0xFBF0) == OP_MOV_imm_T3) && ((instruction[1] & 0x8000) == 0); 1670 } 1671 1672 static bool isMOVT(void* address) 1673 { 1674 uint16_t* instruction = static_cast<uint16_t*>(address); 1675 return ((instruction[0] & 0xFBF0) == OP_MOVT) && ((instruction[1] & 0x8000) == 0); 1676 } 1677 1678 static bool isNOP_T1(void* address) 1679 { 1680 uint16_t* instruction = static_cast<uint16_t*>(address); 1681 return instruction[0] == OP_NOP_T1; 1682 } 1683 1684 static bool isNOP_T2(void* address) 1685 { 1686 uint16_t* instruction = static_cast<uint16_t*>(address); 1687 return (instruction[0] == OP_NOP_T2a) && (instruction[1] == OP_NOP_T2b); 1688 } 1689 1690 static void linkJumpAbsolute(uint16_t* instruction, void* target) 1691 { 1692 // FIMXE: this should be up in the MacroAssembler layer. :-( 1693 const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip; 1694 1695 ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); 1696 ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); 1697 1698 ASSERT( (isMOV_imm_T3(instruction - 5) && isMOVT(instruction - 3) && isBX(instruction - 1)) 1699 || (isNOP_T1(instruction - 5) && isNOP_T2(instruction - 4) && isB(instruction - 2)) ); 1700 1701 intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction)); 1702 if (((relative << 7) >> 7) == relative) { 1703 // ARM encoding for the top two bits below the sign bit is 'peculiar'. 1704 if (relative >= 0) 1705 relative ^= 0xC00000; 1706 1707 // All branch offsets should be an even distance. 1708 ASSERT(!(relative & 1)); 1709 // There may be a better way to fix this, but right now put the NOPs first, since in the 1710 // case of an conditional branch this will be coming after an ITTT predicating *three* 1711 // instructions! Looking backwards to modify the ITTT to an IT is not easy, due to 1712 // variable wdith encoding - the previous instruction might *look* like an ITTT but 1713 // actually be the second half of a 2-word op. 1714 instruction[-5] = OP_NOP_T1; 1715 instruction[-4] = OP_NOP_T2a; 1716 instruction[-3] = OP_NOP_T2b; 1717 instruction[-2] = OP_B_T4a | ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12); 1718 instruction[-1] = OP_B_T4b | ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1); 1719 } else { 1720 ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) + 1)); 1721 ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) >> 16)); 1722 instruction[-5] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16); 1723 instruction[-4] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, lo16); 1724 instruction[-3] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16); 1725 instruction[-2] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16); 1726 instruction[-1] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3); 1727 } 1728 } 1729 1730 static uint16_t twoWordOp5i6Imm4Reg4EncodedImmFirst(uint16_t op, ARMThumbImmediate imm) 1731 { 1732 return op | (imm.m_value.i << 10) | imm.m_value.imm4; 1733 } 1734 static uint16_t twoWordOp5i6Imm4Reg4EncodedImmSecond(uint16_t rd, ARMThumbImmediate imm) 1735 { 1736 return (imm.m_value.imm3 << 12) | (rd << 8) | imm.m_value.imm8; 1668 1737 } 1669 1738 … … 1724 1793 void twoWordOp5i6Imm4Reg4EncodedImm(OpcodeID1 op, int imm4, RegisterID rd, ARMThumbImmediate imm) 1725 1794 { 1726 m_buffer.putShort(op | (imm.m_value.i << 10) | imm4); 1727 m_buffer.putShort((imm.m_value.imm3 << 12) | (rd << 8) | imm.m_value.imm8); 1795 ARMThumbImmediate newImm = imm; 1796 newImm.m_value.imm4 = imm4; 1797 1798 m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmFirst(op, newImm)); 1799 m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmSecond(rd, newImm)); 1728 1800 } 1729 1801 … … 1750 1822 AssemblerBuffer m_buffer; 1751 1823 } m_formatter; 1824 1825 Vector<LinkRecord> m_jumpsToLink; 1752 1826 }; 1753 1827 -
trunk/JavaScriptCore/assembler/MacroAssemblerARMv7.h
r48782 r50255 991 991 ARMv7Assembler::JmpSrc makeJump() 992 992 { 993 return m_assembler.b(); 993 moveFixedWidthEncoding(Imm32(0), dataTempRegister); 994 return m_assembler.bx(dataTempRegister); 994 995 } 995 996 996 997 ARMv7Assembler::JmpSrc makeBranch(ARMv7Assembler::Condition cond) 997 998 { 998 m_assembler.it(cond); 999 return m_assembler.b(); 999 m_assembler.it(cond, true, true); 1000 moveFixedWidthEncoding(Imm32(0), dataTempRegister); 1001 return m_assembler.bx(dataTempRegister); 1000 1002 } 1001 1003 ARMv7Assembler::JmpSrc makeBranch(Condition cond) { return makeBranch(armV7Condition(cond)); } -
trunk/JavaScriptCore/jit/JIT.h
r50254 r50255 587 587 // These architecture specific value are used to enable patching - see comment on op_put_by_id. 588 588 static const int patchOffsetPutByIdStructure = 10; 589 static const int patchOffsetPutByIdExternalLoad = 2 0;589 static const int patchOffsetPutByIdExternalLoad = 26; 590 590 static const int patchLengthPutByIdExternalLoad = 12; 591 static const int patchOffsetPutByIdPropertyMapOffset = 4 0;591 static const int patchOffsetPutByIdPropertyMapOffset = 46; 592 592 // These architecture specific value are used to enable patching - see comment on op_get_by_id. 593 593 static const int patchOffsetGetByIdStructure = 10; 594 static const int patchOffsetGetByIdBranchToSlowCase = 2 0;595 static const int patchOffsetGetByIdExternalLoad = 2 0;594 static const int patchOffsetGetByIdBranchToSlowCase = 26; 595 static const int patchOffsetGetByIdExternalLoad = 26; 596 596 static const int patchLengthGetByIdExternalLoad = 12; 597 static const int patchOffsetGetByIdPropertyMapOffset = 4 0;598 static const int patchOffsetGetByIdPutResult = 44;597 static const int patchOffsetGetByIdPropertyMapOffset = 46; 598 static const int patchOffsetGetByIdPutResult = 50; 599 599 #if ENABLE(OPCODE_SAMPLING) 600 600 static const int patchOffsetGetByIdSlowCaseCall = 0; // FIMXE … … 602 602 static const int patchOffsetGetByIdSlowCaseCall = 28; 603 603 #endif 604 static const int patchOffsetOpCallCompareToJump = 1 0;605 606 static const int patchOffsetMethodCheckProtoObj = 18;607 static const int patchOffsetMethodCheckProtoStruct = 28;608 static const int patchOffsetMethodCheckPutFunction = 46;604 static const int patchOffsetOpCallCompareToJump = 16; 605 606 static const int patchOffsetMethodCheckProtoObj = 24; 607 static const int patchOffsetMethodCheckProtoStruct = 34; 608 static const int patchOffsetMethodCheckPutFunction = 58; 609 609 #elif PLATFORM(ARM_TRADITIONAL) 610 610 // These architecture specific value are used to enable patching - see comment on op_put_by_id. -
trunk/JavaScriptCore/wtf/Platform.h
r50218 r50255 731 731 #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 1 732 732 #elif PLATFORM(ARM_THUMB2) && PLATFORM(IPHONE) 733 /* Under development, temporarily disabled until 16Mb link range limit in assembler is fixed. */ 734 #define ENABLE_JIT 0 733 #define ENABLE_JIT 1 735 734 #define ENABLE_JIT_OPTIMIZE_NATIVE_CALL 0 736 735 /* The JIT is tested & working on x86 Windows */ … … 798 797 #if (PLATFORM(X86) && PLATFORM(MAC)) \ 799 798 || (PLATFORM(X86_64) && PLATFORM(MAC)) \ 800 /* Under development, temporarily disabled until 16Mb link range limit in assembler is fixed. */ \ 801 || (PLATFORM(ARM_THUMB2) && PLATFORM(IPHONE) && 0) \ 799 || (PLATFORM(ARM_THUMB2) && PLATFORM(IPHONE)) \ 802 800 || (PLATFORM(X86) && PLATFORM(WIN)) 803 801 #define ENABLE_YARR 1
Note:
See TracChangeset
for help on using the changeset viewer.