Changeset 192836 in webkit
- Timestamp:
- Nov 30, 2015 3:13:41 PM (8 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 3 added
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/CMakeLists.txt
r192816 r192836 456 456 jit/JITCode.cpp 457 457 jit/JITDisassembler.cpp 458 jit/JITDivGenerator.cpp 458 459 jit/JITExceptions.cpp 459 460 jit/JITInlineCacheGenerator.cpp -
trunk/Source/JavaScriptCore/ChangeLog
r192831 r192836 1 2015-11-30 Mark Lam <mark.lam@apple.com> 2 3 Snippefy op_div for the baseline JIT. 4 https://bugs.webkit.org/show_bug.cgi?id=151607 5 6 Reviewed by Geoffrey Garen. 7 8 * CMakeLists.txt: 9 * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj: 10 * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters: 11 * JavaScriptCore.xcodeproj/project.pbxproj: 12 13 * jit/JIT.h: 14 * jit/JITArithmetic.cpp: 15 (JSC::JIT::emit_op_div): 16 (JSC::JIT::emitSlow_op_div): 17 (JSC::JIT::compileBinaryArithOpSlowCase): Deleted. 18 19 * jit/JITArithmetic32_64.cpp: 20 (JSC::JIT::emitBinaryDoubleOp): 21 (JSC::JIT::emit_op_div): Deleted. 22 (JSC::JIT::emitSlow_op_div): Deleted. 23 - Removed the 32-bit specific op_div implementation. The 64-bit version with the 24 op_div snippet can now service both 32-bit and 64-bit. 25 26 * jit/JITDivGenerator.cpp: Added. 27 (JSC::JITDivGenerator::loadOperand): 28 (JSC::JITDivGenerator::generateFastPath): 29 * jit/JITDivGenerator.h: Added. 30 (JSC::JITDivGenerator::JITDivGenerator): 31 (JSC::JITDivGenerator::didEmitFastPath): 32 (JSC::JITDivGenerator::endJumpList): 33 (JSC::JITDivGenerator::slowPathJumpList): 34 35 * jit/JITInlines.h: 36 (JSC::JIT::getOperandConstantDouble): Added. 37 38 * jit/SnippetOperand.h: Added. 39 (JSC::SnippetOperand::SnippetOperand): 40 (JSC::SnippetOperand::mightBeNumber): 41 (JSC::SnippetOperand::definitelyIsNumber): 42 (JSC::SnippetOperand::isConst): 43 (JSC::SnippetOperand::isConstInt32): 44 (JSC::SnippetOperand::isConstDouble): 45 (JSC::SnippetOperand::asRawBits): 46 (JSC::SnippetOperand::asConstInt32): 47 (JSC::SnippetOperand::asConstDouble): 48 (JSC::SnippetOperand::setConstInt32): 49 (JSC::SnippetOperand::setConstDouble): 50 - The SnippetOperand encapsulates operand constness, const type, and profiling 51 information. As a result: 52 1. The argument list to the JITDivGenerator constructor is now more concise. 53 2. The logic of the JITDivGenerator is now less verbose and easier to express. 54 55 * parser/ResultType.h: 56 (JSC::ResultType::isInt32): 57 (JSC::ResultType::definitelyIsNumber): 58 (JSC::ResultType::definitelyIsString): 59 (JSC::ResultType::definitelyIsBoolean): 60 (JSC::ResultType::mightBeNumber): 61 (JSC::ResultType::isNotNumber): 62 - Made these functions const because they were always meant to be const. 63 This also allows me to enforce constness in the SnippetOperand. 64 1 65 2015-11-30 Sukolsak Sakshuwong <sukolsak@gmail.com> 2 66 -
trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
r192600 r192836 648 648 <ClCompile Include="..\jit\JITCode.cpp" /> 649 649 <ClCompile Include="..\jit\JITDisassembler.cpp" /> 650 <ClCompile Include="..\jit\JITDivGenerator.cpp" /> 650 651 <ClCompile Include="..\jit\JITExceptions.cpp" /> 651 652 <ClCompile Include="..\jit\JITInlineCacheGenerator.cpp" /> … … 1466 1467 <ClInclude Include="..\jit\JITCompilationEffort.h" /> 1467 1468 <ClInclude Include="..\jit\JITDisassembler.h" /> 1469 <ClInclude Include="..\jit\JITDivGenerator.h" /> 1468 1470 <ClInclude Include="..\jit\JITExceptions.h" /> 1469 1471 <ClInclude Include="..\jit\JITInlineCacheGenerator.h" /> … … 1486 1488 <ClInclude Include="..\jit\Repatch.h" /> 1487 1489 <ClInclude Include="..\jit\ScratchRegisterAllocator.h" /> 1490 <ClInclude Include="..\jit\SnippetOperand.h" /> 1488 1491 <ClInclude Include="..\jit\SpecializedThunkJIT.h" /> 1489 1492 <ClInclude Include="..\jit\TempRegisterSet.h" /> -
trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters
r192600 r192836 442 442 <Filter>jit</Filter> 443 443 </ClCompile> 444 <ClCompile Include="..\jit\JITDivGenerator.cpp"> 445 <Filter>jit</Filter> 446 </ClCompile> 444 447 <ClCompile Include="..\jit\JITExceptions.cpp"> 445 448 <Filter>jit</Filter> … … 2517 2520 <Filter>jit</Filter> 2518 2521 </ClInclude> 2522 <ClInclude Include="..\jit\JITDivGenerator.h"> 2523 <Filter>jit</Filter> 2524 </ClInclude> 2519 2525 <ClInclude Include="..\jit\JITExceptions.h"> 2520 2526 <Filter>jit</Filter> … … 2542 2548 </ClInclude> 2543 2549 <ClInclude Include="..\jit\SpecializedThunkJIT.h"> 2550 <Filter>jit</Filter> 2551 </ClInclude> 2552 <ClInclude Include="..\jit\SnippetOperand.h"> 2544 2553 <Filter>jit</Filter> 2545 2554 </ClInclude> -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r192816 r192836 1973 1973 FE187A011BFBE55E0038BBCA /* JITMulGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE1879FF1BFBC73C0038BBCA /* JITMulGenerator.cpp */; }; 1974 1974 FE187A021BFBE5610038BBCA /* JITMulGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = FE187A001BFBC73C0038BBCA /* JITMulGenerator.h */; }; 1975 FE187A0D1C030D5C0038BBCA /* JITDivGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = FE187A0B1C0229230038BBCA /* JITDivGenerator.h */; settings = {ASSET_TAGS = (); }; }; 1976 FE187A0E1C030D640038BBCA /* JITDivGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE187A0A1C0229230038BBCA /* JITDivGenerator.cpp */; settings = {ASSET_TAGS = (); }; }; 1977 FE187A0F1C030D6C0038BBCA /* SnippetOperand.h in Headers */ = {isa = PBXBuildFile; fileRef = FE187A0C1C02EBA70038BBCA /* SnippetOperand.h */; settings = {ASSET_TAGS = (); }; }; 1975 1978 FE1C0FFD1B193E9800B53FCA /* Exception.h in Headers */ = {isa = PBXBuildFile; fileRef = FE1C0FFC1B193E9800B53FCA /* Exception.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1976 1979 FE1C0FFF1B194FD100B53FCA /* Exception.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE1C0FFE1B194FD100B53FCA /* Exception.cpp */; }; … … 4113 4116 FE1879FF1BFBC73C0038BBCA /* JITMulGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITMulGenerator.cpp; sourceTree = "<group>"; }; 4114 4117 FE187A001BFBC73C0038BBCA /* JITMulGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITMulGenerator.h; sourceTree = "<group>"; }; 4118 FE187A0A1C0229230038BBCA /* JITDivGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITDivGenerator.cpp; sourceTree = "<group>"; }; 4119 FE187A0B1C0229230038BBCA /* JITDivGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITDivGenerator.h; sourceTree = "<group>"; }; 4120 FE187A0C1C02EBA70038BBCA /* SnippetOperand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SnippetOperand.h; sourceTree = "<group>"; }; 4115 4121 FE1C0FFC1B193E9800B53FCA /* Exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Exception.h; sourceTree = "<group>"; }; 4116 4122 FE1C0FFE1B194FD100B53FCA /* Exception.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Exception.cpp; sourceTree = "<group>"; }; … … 4792 4798 0FAF7EFA165BA919000C8455 /* JITDisassembler.cpp */, 4793 4799 0FAF7EFB165BA919000C8455 /* JITDisassembler.h */, 4800 FE187A0A1C0229230038BBCA /* JITDivGenerator.cpp */, 4801 FE187A0B1C0229230038BBCA /* JITDivGenerator.h */, 4794 4802 0F46807F14BA572700BFE272 /* JITExceptions.cpp */, 4795 4803 0F46808014BA572700BFE272 /* JITExceptions.h */, … … 4833 4841 0FEE98401A8865B600754E93 /* SetupVarargsFrame.h */, 4834 4842 A709F2EF17A0AC0400512E98 /* SlowPathCall.h */, 4843 FE187A0C1C02EBA70038BBCA /* SnippetOperand.h */, 4835 4844 A7386551118697B400540279 /* SpecializedThunkJIT.h */, 4836 4845 A7FF647A18C52E8500B55307 /* SpillRegistersMode.h */, … … 7198 7207 0F32BD111BB34F190093A57F /* HeapHelperPool.h in Headers */, 7199 7208 C2DA778318E259990066FCB6 /* HeapInlines.h in Headers */, 7209 FE187A0D1C030D5C0038BBCA /* JITDivGenerator.h in Headers */, 7200 7210 2AD8932B17E3868F00668276 /* HeapIterationScope.h in Headers */, 7201 7211 A5339EC91BB4B4600054F005 /* HeapObserver.h in Headers */, … … 7261 7271 A18193E41B4E0CDB00FC1029 /* IntlCollatorPrototype.lut.h in Headers */, 7262 7272 A1587D6E1B4DC14100D69849 /* IntlDateTimeFormat.h in Headers */, 7273 FE187A0F1C030D6C0038BBCA /* SnippetOperand.h in Headers */, 7263 7274 A1587D701B4DC14100D69849 /* IntlDateTimeFormatConstructor.h in Headers */, 7264 7275 A1587D751B4DC1C600D69849 /* IntlDateTimeFormatConstructor.lut.h in Headers */, … … 8599 8610 0FD120331A8C85BD000F5280 /* FTLJSCallVarargs.cpp in Sources */, 8600 8611 62774DAA1B8D4B190006F05A /* FTLJSTailCall.cpp in Sources */, 8612 FE187A0E1C030D640038BBCA /* JITDivGenerator.cpp in Sources */, 8601 8613 0FB4FB731BC843140025CA5A /* FTLLazySlowPath.cpp in Sources */, 8602 8614 0F8F2B95172E04A0007DBDA5 /* FTLLink.cpp in Sources */, -
trunk/Source/JavaScriptCore/jit/JIT.h
r192814 r192836 405 405 406 406 int32_t getOperandConstantInt(int src); 407 double getOperandConstantDouble(int src); 407 408 408 409 #if USE(JSVALUE32_64) … … 463 464 464 465 void emitTagBool(RegisterID); 465 void compileBinaryArithOpSlowCase(Instruction*, OpcodeID, Vector<SlowCaseEntry>::iterator&, int dst, int src1, int src2, OperandTypes, bool op1HasImmediateIntFastCase, bool op2HasImmediateIntFastCase);466 466 467 467 void compileGetByIdHotPath(int baseVReg, const Identifier*); -
trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp
r192600 r192836 31 31 #include "CodeBlock.h" 32 32 #include "JITAddGenerator.h" 33 #include "JITDivGenerator.h" 33 34 #include "JITInlines.h" 34 35 #include "JITMulGenerator.h" … … 662 663 /* ------------------------------ END: OP_MOD ------------------------------ */ 663 664 664 /* ------------------------------ BEGIN: USE(JSVALUE64) (OP_ADD, OP_SUB, OP_MUL) ------------------------------ */665 666 void JIT::compileBinaryArithOpSlowCase(Instruction* currentInstruction, OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, int result, int op1, int op2, OperandTypes types, bool op1HasImmediateIntFastCase, bool op2HasImmediateIntFastCase)667 {668 // We assume that subtracting TagTypeNumber is equivalent to adding DoubleEncodeOffset.669 COMPILE_ASSERT(((TagTypeNumber + DoubleEncodeOffset) == 0), TagTypeNumber_PLUS_DoubleEncodeOffset_EQUALS_0);670 671 Jump notImm1;672 Jump notImm2;673 if (op1HasImmediateIntFastCase) {674 notImm2 = getSlowCase(iter);675 } else if (op2HasImmediateIntFastCase) {676 notImm1 = getSlowCase(iter);677 } else {678 notImm1 = getSlowCase(iter);679 notImm2 = getSlowCase(iter);680 }681 682 linkSlowCase(iter); // Integer overflow case - we could handle this in JIT code, but this is likely rare.683 684 Label stubFunctionCall(this);685 686 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_mul);687 slowPathCall.call();688 Jump end = jump();689 690 if (op1HasImmediateIntFastCase) {691 notImm2.link(this);692 if (!types.second().definitelyIsNumber())693 emitJumpIfNotNumber(regT0).linkTo(stubFunctionCall, this);694 emitGetVirtualRegister(op1, regT1);695 convertInt32ToDouble(regT1, fpRegT1);696 add64(tagTypeNumberRegister, regT0);697 move64ToDouble(regT0, fpRegT2);698 } else if (op2HasImmediateIntFastCase) {699 notImm1.link(this);700 if (!types.first().definitelyIsNumber())701 emitJumpIfNotNumber(regT0).linkTo(stubFunctionCall, this);702 emitGetVirtualRegister(op2, regT1);703 convertInt32ToDouble(regT1, fpRegT1);704 add64(tagTypeNumberRegister, regT0);705 move64ToDouble(regT0, fpRegT2);706 } else {707 // if we get here, eax is not an int32, edx not yet checked.708 notImm1.link(this);709 if (!types.first().definitelyIsNumber())710 emitJumpIfNotNumber(regT0).linkTo(stubFunctionCall, this);711 if (!types.second().definitelyIsNumber())712 emitJumpIfNotNumber(regT1).linkTo(stubFunctionCall, this);713 add64(tagTypeNumberRegister, regT0);714 move64ToDouble(regT0, fpRegT1);715 Jump op2isDouble = emitJumpIfNotInt(regT1);716 convertInt32ToDouble(regT1, fpRegT2);717 Jump op2wasInteger = jump();718 719 // if we get here, eax IS an int32, edx is not.720 notImm2.link(this);721 if (!types.second().definitelyIsNumber())722 emitJumpIfNotNumber(regT1).linkTo(stubFunctionCall, this);723 convertInt32ToDouble(regT0, fpRegT1);724 op2isDouble.link(this);725 add64(tagTypeNumberRegister, regT1);726 move64ToDouble(regT1, fpRegT2);727 op2wasInteger.link(this);728 }729 730 ASSERT_UNUSED(opcodeID, opcodeID == op_div);731 divDouble(fpRegT2, fpRegT1);732 733 moveDoubleTo64(fpRegT1, regT0);734 sub64(tagTypeNumberRegister, regT0);735 emitPutVirtualRegister(result, regT0);736 737 end.link(this);738 }739 740 void JIT::emit_op_div(Instruction* currentInstruction)741 {742 int dst = currentInstruction[1].u.operand;743 int op1 = currentInstruction[2].u.operand;744 int op2 = currentInstruction[3].u.operand;745 OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);746 747 if (isOperandConstantDouble(op1)) {748 emitGetVirtualRegister(op1, regT0);749 add64(tagTypeNumberRegister, regT0);750 move64ToDouble(regT0, fpRegT0);751 } else if (isOperandConstantInt(op1)) {752 emitLoadInt32ToDouble(op1, fpRegT0);753 } else {754 emitGetVirtualRegister(op1, regT0);755 if (!types.first().definitelyIsNumber())756 emitJumpSlowCaseIfNotNumber(regT0);757 Jump notInt = emitJumpIfNotInt(regT0);758 convertInt32ToDouble(regT0, fpRegT0);759 Jump skipDoubleLoad = jump();760 notInt.link(this);761 add64(tagTypeNumberRegister, regT0);762 move64ToDouble(regT0, fpRegT0);763 skipDoubleLoad.link(this);764 }765 766 if (isOperandConstantDouble(op2)) {767 emitGetVirtualRegister(op2, regT1);768 add64(tagTypeNumberRegister, regT1);769 move64ToDouble(regT1, fpRegT1);770 } else if (isOperandConstantInt(op2)) {771 emitLoadInt32ToDouble(op2, fpRegT1);772 } else {773 emitGetVirtualRegister(op2, regT1);774 if (!types.second().definitelyIsNumber())775 emitJumpSlowCaseIfNotNumber(regT1);776 Jump notInt = emitJumpIfNotInt(regT1);777 convertInt32ToDouble(regT1, fpRegT1);778 Jump skipDoubleLoad = jump();779 notInt.link(this);780 add64(tagTypeNumberRegister, regT1);781 move64ToDouble(regT1, fpRegT1);782 skipDoubleLoad.link(this);783 }784 divDouble(fpRegT1, fpRegT0);785 786 // Is the result actually an integer? The DFG JIT would really like to know. If it's787 // not an integer, we increment a count. If this together with the slow case counter788 // are below threshold then the DFG JIT will compile this division with a specualtion789 // that the remainder is zero.790 791 // As well, there are cases where a double result here would cause an important field792 // in the heap to sometimes have doubles in it, resulting in double predictions getting793 // propagated to a use site where it might cause damage (such as the index to an array794 // access). So if we are DFG compiling anything in the program, we want this code to795 // ensure that it produces integers whenever possible.796 797 JumpList notInteger;798 branchConvertDoubleToInt32(fpRegT0, regT0, notInteger, fpRegT1);799 // If we've got an integer, we might as well make that the result of the division.800 emitTagInt(regT0, regT0);801 Jump isInteger = jump();802 notInteger.link(this);803 moveDoubleTo64(fpRegT0, regT0);804 Jump doubleZero = branchTest64(Zero, regT0);805 add32(TrustedImm32(1), AbsoluteAddress(&m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset)->m_counter));806 sub64(tagTypeNumberRegister, regT0);807 Jump trueDouble = jump();808 doubleZero.link(this);809 move(tagTypeNumberRegister, regT0);810 trueDouble.link(this);811 isInteger.link(this);812 813 emitPutVirtualRegister(dst, regT0);814 }815 816 void JIT::emitSlow_op_div(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)817 {818 int op1 = currentInstruction[2].u.operand;819 int op2 = currentInstruction[3].u.operand;820 OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);821 if (types.first().definitelyIsNumber() && types.second().definitelyIsNumber()) {822 if (!ASSERT_DISABLED)823 abortWithReason(JITDivOperandsAreNotNumbers);824 return;825 }826 if (!isOperandConstantDouble(op1) && !isOperandConstantInt(op1)) {827 if (!types.first().definitelyIsNumber())828 linkSlowCase(iter);829 }830 if (!isOperandConstantDouble(op2) && !isOperandConstantInt(op2)) {831 if (!types.second().definitelyIsNumber())832 linkSlowCase(iter);833 }834 // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0.835 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_div);836 slowPathCall.call();837 }838 839 665 #endif // USE(JSVALUE64) 840 666 … … 907 733 } 908 734 909 void JIT::emit_op_ mul(Instruction* currentInstruction)735 void JIT::emit_op_div(Instruction* currentInstruction) 910 736 { 911 737 int result = currentInstruction[1].u.operand; … … 928 754 #endif 929 755 930 bool leftIsConstInt32 = isOperandConstantInt(op1); 931 bool rightIsConstInt32 = isOperandConstantInt(op2); 932 ResultType leftType = types.first(); 933 ResultType rightType = types.second(); 934 int32_t leftConstInt32 = 0; 935 int32_t rightConstInt32 = 0; 936 937 uint32_t* profilingCounter = nullptr; 938 if (shouldEmitProfiling()) 939 profilingCounter = &m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset)->m_counter; 940 941 ASSERT(!leftIsConstInt32 || !rightIsConstInt32); 942 943 if (leftIsConstInt32) 944 leftConstInt32 = getOperandConstantInt(op1); 945 if (rightIsConstInt32) 946 rightConstInt32 = getOperandConstantInt(op2); 947 948 bool leftIsPositiveConstInt32 = leftIsConstInt32 && (leftConstInt32 > 0); 949 bool rightIsPositiveConstInt32 = rightIsConstInt32 && (rightConstInt32 > 0); 950 951 if (leftIsPositiveConstInt32) 756 uint32_t* profilingCounter = &m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset)->m_counter; 757 758 SnippetOperand leftOperand(types.first()); 759 SnippetOperand rightOperand(types.second()); 760 761 if (isOperandConstantInt(op1)) 762 leftOperand.setConstInt32(getOperandConstantInt(op1)); 763 #if USE(JSVALUE64) 764 else if (isOperandConstantDouble(op1)) 765 leftOperand.setConstDouble(getOperandConstantDouble(op1)); 766 #endif 767 768 if (isOperandConstantInt(op2)) 769 rightOperand.setConstInt32(getOperandConstantInt(op2)); 770 #if USE(JSVALUE64) 771 else if (isOperandConstantDouble(op2)) 772 rightOperand.setConstDouble(getOperandConstantDouble(op2)); 773 #endif 774 775 ASSERT(!leftOperand.isConst() || !rightOperand.isConst()); 776 777 if (!leftOperand.isConst()) 778 emitGetVirtualRegister(op1, leftRegs); 779 if (!rightOperand.isConst()) 952 780 emitGetVirtualRegister(op2, rightRegs); 953 else if (rightIsPositiveConstInt32) 954 emitGetVirtualRegister(op1, leftRegs); 955 else { 956 emitGetVirtualRegister(op1, leftRegs); 957 emitGetVirtualRegister(op2, rightRegs); 958 } 959 960 JITMulGenerator gen(resultRegs, leftRegs, rightRegs, leftType, rightType, 961 leftIsPositiveConstInt32, rightIsPositiveConstInt32, leftConstInt32, rightConstInt32, 781 782 JITDivGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs, 962 783 fpRegT0, fpRegT1, scratchGPR, scratchFPR, profilingCounter); 963 784 … … 972 793 ASSERT(gen.endJumpList().empty()); 973 794 ASSERT(gen.slowPathJumpList().empty()); 974 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_ mul);795 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_div); 975 796 slowPathCall.call(); 976 797 } 977 798 } 978 799 979 void JIT::emitSlow_op_ mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)800 void JIT::emitSlow_op_div(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 980 801 { 981 802 linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset); 982 983 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_ mul);984 slowPathCall.call(); 985 } 986 987 void JIT::emit_op_ sub(Instruction* currentInstruction)803 804 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_div); 805 slowPathCall.call(); 806 } 807 808 void JIT::emit_op_mul(Instruction* currentInstruction) 988 809 { 989 810 int result = currentInstruction[1].u.operand; … … 1006 827 #endif 1007 828 829 bool leftIsConstInt32 = isOperandConstantInt(op1); 830 bool rightIsConstInt32 = isOperandConstantInt(op2); 831 ResultType leftType = types.first(); 832 ResultType rightType = types.second(); 833 int32_t leftConstInt32 = 0; 834 int32_t rightConstInt32 = 0; 835 836 uint32_t* profilingCounter = nullptr; 837 if (shouldEmitProfiling()) 838 profilingCounter = &m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset)->m_counter; 839 840 ASSERT(!leftIsConstInt32 || !rightIsConstInt32); 841 842 if (leftIsConstInt32) 843 leftConstInt32 = getOperandConstantInt(op1); 844 if (rightIsConstInt32) 845 rightConstInt32 = getOperandConstantInt(op2); 846 847 bool leftIsPositiveConstInt32 = leftIsConstInt32 && (leftConstInt32 > 0); 848 bool rightIsPositiveConstInt32 = rightIsConstInt32 && (rightConstInt32 > 0); 849 850 if (leftIsPositiveConstInt32) 851 emitGetVirtualRegister(op2, rightRegs); 852 else if (rightIsPositiveConstInt32) 853 emitGetVirtualRegister(op1, leftRegs); 854 else { 855 emitGetVirtualRegister(op1, leftRegs); 856 emitGetVirtualRegister(op2, rightRegs); 857 } 858 859 JITMulGenerator gen(resultRegs, leftRegs, rightRegs, leftType, rightType, 860 leftIsPositiveConstInt32, rightIsPositiveConstInt32, leftConstInt32, rightConstInt32, 861 fpRegT0, fpRegT1, scratchGPR, scratchFPR, profilingCounter); 862 863 gen.generateFastPath(*this); 864 865 if (gen.didEmitFastPath()) { 866 gen.endJumpList().link(this); 867 emitPutVirtualRegister(result, resultRegs); 868 869 addSlowCase(gen.slowPathJumpList()); 870 } else { 871 ASSERT(gen.endJumpList().empty()); 872 ASSERT(gen.slowPathJumpList().empty()); 873 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_mul); 874 slowPathCall.call(); 875 } 876 } 877 878 void JIT::emitSlow_op_mul(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) 879 { 880 linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset); 881 882 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_mul); 883 slowPathCall.call(); 884 } 885 886 void JIT::emit_op_sub(Instruction* currentInstruction) 887 { 888 int result = currentInstruction[1].u.operand; 889 int op1 = currentInstruction[2].u.operand; 890 int op2 = currentInstruction[3].u.operand; 891 OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand); 892 893 #if USE(JSVALUE64) 894 JSValueRegs leftRegs = JSValueRegs(regT0); 895 JSValueRegs rightRegs = JSValueRegs(regT1); 896 JSValueRegs resultRegs = leftRegs; 897 GPRReg scratchGPR = regT2; 898 FPRReg scratchFPR = InvalidFPRReg; 899 #else 900 JSValueRegs leftRegs = JSValueRegs(regT1, regT0); 901 JSValueRegs rightRegs = JSValueRegs(regT3, regT2); 902 JSValueRegs resultRegs = leftRegs; 903 GPRReg scratchGPR = regT4; 904 FPRReg scratchFPR = fpRegT2; 905 #endif 906 1008 907 emitGetVirtualRegister(op1, leftRegs); 1009 908 emitGetVirtualRegister(op2, rightRegs); -
trunk/Source/JavaScriptCore/jit/JITArithmetic32_64.cpp
r192600 r192836 479 479 } 480 480 481 // Addition (+)482 483 481 void JIT::emitBinaryDoubleOp(OpcodeID opcodeID, int dst, int op1, int op2, OperandTypes types, JumpList& notInt32Op1, JumpList& notInt32Op2, bool op1IsInRegisters, bool op2IsInRegisters) 484 482 { … … 513 511 doTheMath.link(this); 514 512 switch (opcodeID) { 515 case op_div: {516 emitLoadDouble(op1, fpRegT1);517 divDouble(fpRegT0, fpRegT1);518 519 // Is the result actually an integer? The DFG JIT would really like to know. If it's520 // not an integer, we increment a count. If this together with the slow case counter521 // are below threshold then the DFG JIT will compile this division with a specualtion522 // that the remainder is zero.523 524 // As well, there are cases where a double result here would cause an important field525 // in the heap to sometimes have doubles in it, resulting in double predictions getting526 // propagated to a use site where it might cause damage (such as the index to an array527 // access). So if we are DFG compiling anything in the program, we want this code to528 // ensure that it produces integers whenever possible.529 530 // FIXME: This will fail to convert to integer if the result is zero. We should531 // distinguish between positive zero and negative zero here.532 533 JumpList notInteger;534 branchConvertDoubleToInt32(fpRegT1, regT2, notInteger, fpRegT0);535 // If we've got an integer, we might as well make that the result of the division.536 emitStoreInt32(dst, regT2);537 Jump isInteger = jump();538 notInteger.link(this);539 add32(TrustedImm32(1), AbsoluteAddress(&m_codeBlock->specialFastCaseProfileForBytecodeOffset(m_bytecodeOffset)->m_counter));540 emitStoreDouble(dst, fpRegT1);541 isInteger.link(this);542 break;543 }544 513 case op_jless: 545 514 emitLoadDouble(op1, fpRegT2); … … 599 568 // Do the math. 600 569 switch (opcodeID) { 601 case op_div: {602 emitLoadDouble(op2, fpRegT2);603 divDouble(fpRegT2, fpRegT0);604 // Is the result actually an integer? The DFG JIT would really like to know. If it's605 // not an integer, we increment a count. If this together with the slow case counter606 // are below threshold then the DFG JIT will compile this division with a specualtion607 // that the remainder is zero.608 609 // As well, there are cases where a double result here would cause an important field610 // in the heap to sometimes have doubles in it, resulting in double predictions getting611 // propagated to a use site where it might cause damage (such as the index to an array612 // access). So if we are DFG compiling anything in the program, we want this code to613 // ensure that it produces integers whenever possible.614 615 // FIXME: This will fail to convert to integer if the result is zero. We should616 // distinguish between positive zero and negative zero here.617 618 JumpList notInteger;619 branchConvertDoubleToInt32(fpRegT0, regT2, notInteger, fpRegT1);620 // If we've got an integer, we might as well make that the result of the division.621 emitStoreInt32(dst, regT2);622 Jump isInteger = jump();623 notInteger.link(this);624 add32(TrustedImm32(1), AbsoluteAddress(&m_codeBlock->specialFastCaseProfileForBytecodeOffset(m_bytecodeOffset)->m_counter));625 emitStoreDouble(dst, fpRegT0);626 isInteger.link(this);627 break;628 }629 570 case op_jless: 630 571 emitLoadDouble(op2, fpRegT1); … … 665 606 666 607 end.link(this); 667 }668 669 // Division (/)670 671 void JIT::emit_op_div(Instruction* currentInstruction)672 {673 int dst = currentInstruction[1].u.operand;674 int op1 = currentInstruction[2].u.operand;675 int op2 = currentInstruction[3].u.operand;676 OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);677 678 m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset);679 680 if (!supportsFloatingPoint()) {681 addSlowCase(jump());682 return;683 }684 685 // Int32 divide.686 JumpList notInt32Op1;687 JumpList notInt32Op2;688 689 JumpList end;690 691 emitLoad2(op1, regT1, regT0, op2, regT3, regT2);692 693 notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));694 notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));695 696 convertInt32ToDouble(regT0, fpRegT0);697 convertInt32ToDouble(regT2, fpRegT1);698 divDouble(fpRegT1, fpRegT0);699 // Is the result actually an integer? The DFG JIT would really like to know. If it's700 // not an integer, we increment a count. If this together with the slow case counter701 // are below threshold then the DFG JIT will compile this division with a specualtion702 // that the remainder is zero.703 704 // As well, there are cases where a double result here would cause an important field705 // in the heap to sometimes have doubles in it, resulting in double predictions getting706 // propagated to a use site where it might cause damage (such as the index to an array707 // access). So if we are DFG compiling anything in the program, we want this code to708 // ensure that it produces integers whenever possible.709 710 // FIXME: This will fail to convert to integer if the result is zero. We should711 // distinguish between positive zero and negative zero here.712 713 JumpList notInteger;714 branchConvertDoubleToInt32(fpRegT0, regT2, notInteger, fpRegT1);715 // If we've got an integer, we might as well make that the result of the division.716 emitStoreInt32(dst, regT2);717 end.append(jump());718 notInteger.link(this);719 add32(TrustedImm32(1), AbsoluteAddress(&m_codeBlock->specialFastCaseProfileForBytecodeOffset(m_bytecodeOffset)->m_counter));720 emitStoreDouble(dst, fpRegT0);721 end.append(jump());722 723 // Double divide.724 emitBinaryDoubleOp(op_div, dst, op1, op2, types, notInt32Op1, notInt32Op2);725 end.link(this);726 }727 728 void JIT::emitSlow_op_div(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)729 {730 OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);731 732 if (!supportsFloatingPoint())733 linkSlowCase(iter);734 else {735 if (!types.first().definitelyIsNumber())736 linkSlowCase(iter); // double check737 738 if (!types.second().definitelyIsNumber()) {739 linkSlowCase(iter); // int32 check740 linkSlowCase(iter); // double check741 }742 }743 744 JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_div);745 slowPathCall.call();746 608 } 747 609 -
trunk/Source/JavaScriptCore/jit/JITInlines.h
r191905 r192836 981 981 } 982 982 983 ALWAYS_INLINE double JIT::getOperandConstantDouble(int src) 984 { 985 return getConstantOperand(src).asDouble(); 986 } 987 983 988 #if USE(JSVALUE32_64) 984 989 -
trunk/Source/JavaScriptCore/parser/ResultType.h
r191224 r192836 50 50 51 51 public: 52 bool isInt32() 52 bool isInt32() const 53 53 { 54 54 return m_type & TypeInt32; 55 55 } 56 56 57 bool definitelyIsNumber() 57 bool definitelyIsNumber() const 58 58 { 59 59 return (m_type & TypeBits) == TypeMaybeNumber; 60 60 } 61 61 62 bool definitelyIsString() 62 bool definitelyIsString() const 63 63 { 64 64 return (m_type & TypeBits) == TypeMaybeString; 65 65 } 66 66 67 bool definitelyIsBoolean() 67 bool definitelyIsBoolean() const 68 68 { 69 69 return (m_type & TypeBits) == TypeMaybeBool; 70 70 } 71 71 72 bool mightBeNumber() 72 bool mightBeNumber() const 73 73 { 74 74 return m_type & TypeMaybeNumber; 75 75 } 76 76 77 bool isNotNumber() 77 bool isNotNumber() const 78 78 { 79 79 return !mightBeNumber();
Note: See TracChangeset
for help on using the changeset viewer.