Changeset 183963 in webkit
- Timestamp:
- May 7, 2015, 5:23:32 PM (11 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 1 added
- 28 edited
-
ChangeLog (modified) (1 diff)
-
assembler/MacroAssemblerX86Common.h (modified) (1 diff)
-
assembler/X86Assembler.h (modified) (2 diffs)
-
bytecode/SpeculatedType.cpp (modified) (1 diff)
-
bytecode/SpeculatedType.h (modified) (1 diff)
-
dfg/DFGAbstractInterpreterInlines.h (modified) (2 diffs)
-
dfg/DFGArithMode.h (modified) (2 diffs)
-
dfg/DFGByteCodeParser.cpp (modified) (1 diff)
-
dfg/DFGClobberize.h (modified) (1 diff)
-
dfg/DFGDoesGC.cpp (modified) (1 diff)
-
dfg/DFGFixupPhase.cpp (modified) (1 diff)
-
dfg/DFGGraph.h (modified) (1 diff)
-
dfg/DFGNode.h (modified) (3 diffs)
-
dfg/DFGNodeType.h (modified) (1 diff)
-
dfg/DFGPredictionPropagationPhase.cpp (modified) (1 diff)
-
dfg/DFGSafeToExecute.h (modified) (1 diff)
-
dfg/DFGSpeculativeJIT.cpp (modified) (1 diff)
-
dfg/DFGSpeculativeJIT.h (modified) (1 diff)
-
dfg/DFGSpeculativeJIT32_64.cpp (modified) (1 diff)
-
dfg/DFGSpeculativeJIT64.cpp (modified) (1 diff)
-
ftl/FTLCapabilities.cpp (modified) (2 diffs)
-
ftl/FTLIntrinsicRepository.h (modified) (1 diff)
-
ftl/FTLLowerDFGToLLVM.cpp (modified) (5 diffs)
-
ftl/FTLOutput.h (modified) (1 diff)
-
jit/ThunkGenerators.cpp (modified) (2 diffs)
-
runtime/MathCommon.cpp (modified) (1 diff)
-
runtime/MathCommon.h (modified) (1 diff)
-
runtime/MathObject.cpp (modified) (1 diff)
-
tests/stress/math-round-basics.js (added)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r183962 r183963 1 2015-05-07 Benjamin Poulain <bpoulain@apple.com> 2 3 [JSC] Add basic DFG/FTL support for Math.round 4 https://bugs.webkit.org/show_bug.cgi?id=144725 5 6 Reviewed by Filip Pizlo. 7 8 This patch adds two optimizations targeting Math.round(): 9 -Add a DFGNode ArithRound corresponding to the intrinsic RoundIntrinsic. 10 -Change the MacroAssembler to be stricter on how we fail to convert a double 11 to ingeter. Previously, any number valued zero would fail, now we only 12 fail for -0. 13 14 Since ArithRound speculate it produces int32, the MacroAssembler assembler 15 part became necessary because zero is a pretty common output of Math.round() 16 and we would OSR exit a lot (and eventually recompile for doubles). 17 18 The implementation itself of the inline Math.round() is exactly the same 19 as the C function that exists for Math.round(). We can very likely do better 20 but it is a good start known to be valid and inlining alone alread provides 21 significant speedups. 22 23 * assembler/X86Assembler.h: 24 (JSC::X86Assembler::movmskpd_rr): 25 * assembler/MacroAssemblerX86Common.h: 26 (JSC::MacroAssemblerX86Common::branchConvertDoubleToInt32): 27 When we have a zero, get the sign bit out of the double and check if is one. 28 29 I'll look into doing the same improvement for ARM. 30 31 * bytecode/SpeculatedType.cpp: 32 (JSC::typeOfDoubleRounding): 33 (JSC::typeOfDoubleFRound): Deleted. 34 * bytecode/SpeculatedType.h: 35 * dfg/DFGAbstractInterpreterInlines.h: 36 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 37 * dfg/DFGByteCodeParser.cpp: 38 (JSC::DFG::ByteCodeParser::handleIntrinsic): 39 * dfg/DFGClobberize.h: 40 (JSC::DFG::clobberize): 41 * dfg/DFGDoesGC.cpp: 42 (JSC::DFG::doesGC): 43 * dfg/DFGFixupPhase.cpp: 44 (JSC::DFG::FixupPhase::fixupNode): 45 * dfg/DFGGraph.h: 46 (JSC::DFG::Graph::roundShouldSpeculateInt32): 47 (JSC::DFG::Graph::negateShouldSpeculateMachineInt): Deleted. 48 * dfg/DFGNode.h: 49 (JSC::DFG::Node::arithNodeFlags): 50 (JSC::DFG::Node::hasHeapPrediction): 51 (JSC::DFG::Node::hasArithMode): 52 * dfg/DFGNodeType.h: 53 * dfg/DFGPredictionPropagationPhase.cpp: 54 (JSC::DFG::PredictionPropagationPhase::propagate): 55 * dfg/DFGSafeToExecute.h: 56 (JSC::DFG::safeToExecute): 57 * dfg/DFGSpeculativeJIT.cpp: 58 (JSC::DFG::SpeculativeJIT::compileArithRound): 59 * dfg/DFGSpeculativeJIT.h: 60 * dfg/DFGSpeculativeJIT32_64.cpp: 61 (JSC::DFG::SpeculativeJIT::compile): 62 * dfg/DFGSpeculativeJIT64.cpp: 63 (JSC::DFG::SpeculativeJIT::compile): 64 * ftl/FTLCapabilities.cpp: 65 (JSC::FTL::canCompile): 66 * ftl/FTLIntrinsicRepository.h: 67 * ftl/FTLLowerDFGToLLVM.cpp: 68 (JSC::FTL::LowerDFGToLLVM::compileNode): 69 (JSC::FTL::LowerDFGToLLVM::convertDoubleToInt32): 70 (JSC::FTL::LowerDFGToLLVM::compileDoubleAsInt32): 71 (JSC::FTL::LowerDFGToLLVM::compileArithRound): 72 * ftl/FTLOutput.h: 73 (JSC::FTL::Output::ceil64): 74 * jit/ThunkGenerators.cpp: 75 * runtime/MathCommon.cpp: 76 * runtime/MathCommon.h: 77 * runtime/MathObject.cpp: 78 (JSC::mathProtoFuncRound): 79 * tests/stress/math-round-basics.js: Added. 80 (mathRoundOnIntegers): 81 (mathRoundOnDoubles): 82 (mathRoundOnBooleans): 83 (uselessMathRound): 84 (mathRoundWithOverflow): 85 (mathRoundConsumedAsDouble): 86 (mathRoundDoesNotCareAboutMinusZero): 87 (mathRoundNoArguments): 88 (mathRoundTooManyArguments): 89 (testMathRoundOnConstants): 90 (mathRoundStructTransition): 91 (Math.round): 92 1 93 2015-05-07 Saam Barati <saambarati1@gmail.com> 2 94 -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h
r183358 r183963 922 922 923 923 // If the result is zero, it might have been -0.0, and the double comparison won't catch this! 924 #if CPU(X86_64) 925 if (negZeroCheck) { 926 Jump valueIsNonZero = branchTest32(NonZero, dest); 927 m_assembler.movmskpd_rr(src, scratchRegister); 928 failureCases.append(branchTest32(NonZero, scratchRegister, TrustedImm32(1))); 929 valueIsNonZero.link(this); 930 } 931 #else 924 932 if (negZeroCheck) 925 933 failureCases.append(branchTest32(Zero, dest)); 934 #endif 926 935 927 936 // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump. -
trunk/Source/JavaScriptCore/assembler/X86Assembler.h
r183358 r183963 254 254 OP2_SUBSD_VsdWsd = 0x5C, 255 255 OP2_DIVSD_VsdWsd = 0x5E, 256 OP2_MOVMSKPD_VdEd = 0x50, 256 257 OP2_SQRTSD_VsdWsd = 0x51, 257 258 OP2_ANDNPD_VpdWpd = 0x55, … … 1803 1804 m_formatter.prefix(PRE_SSE_66); 1804 1805 m_formatter.twoByteOp(OP2_MOVD_VdEd, (RegisterID)dst, src); 1806 } 1807 1808 void movmskpd_rr(XMMRegisterID src, RegisterID dst) 1809 { 1810 m_formatter.prefix(PRE_SSE_66); 1811 m_formatter.twoByteOp64(OP2_MOVMSKPD_VdEd, dst, (RegisterID)src); 1805 1812 } 1806 1813 -
trunk/Source/JavaScriptCore/bytecode/SpeculatedType.cpp
r182971 r183963 508 508 } 509 509 510 SpeculatedType typeOfDouble FRound(SpeculatedType value)510 SpeculatedType typeOfDoubleRounding(SpeculatedType value) 511 511 { 512 512 // We might lose bits, which leads to a NaN being purified. -
trunk/Source/JavaScriptCore/bytecode/SpeculatedType.h
r181993 r183963 423 423 SpeculatedType typeOfDoubleNegation(SpeculatedType); 424 424 SpeculatedType typeOfDoubleAbs(SpeculatedType); 425 SpeculatedType typeOfDouble FRound(SpeculatedType);425 SpeculatedType typeOfDoubleRounding(SpeculatedType); 426 426 SpeculatedType typeOfDoublePow(SpeculatedType, SpeculatedType); 427 427 -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r183812 r183963 762 762 break; 763 763 } 764 765 case ArithRound: { 766 JSValue operand = forNode(node->child1()).value(); 767 if (operand && operand.isNumber()) { 768 double roundedValue = jsRound(operand.asNumber()); 769 770 if (producesInteger(node->arithRoundingMode())) { 771 int32_t roundedValueAsInt32 = static_cast<int32_t>(roundedValue); 772 if (roundedValueAsInt32 == roundedValue) { 773 if (shouldCheckNegativeZero(node->arithRoundingMode())) { 774 if (roundedValueAsInt32 || !std::signbit(roundedValue)) { 775 setConstant(node, jsNumber(roundedValueAsInt32)); 776 break; 777 } 778 } else { 779 setConstant(node, jsNumber(roundedValueAsInt32)); 780 break; 781 } 782 } 783 } else { 784 setConstant(node, jsDoubleNumber(roundedValue)); 785 break; 786 } 787 } 788 if (producesInteger(node->arithRoundingMode())) 789 forNode(node).setType(SpecInt32); 790 else 791 forNode(node).setType(typeOfDoubleRounding(forNode(node->child1()).m_type)); 792 break; 793 } 764 794 765 795 case ArithSqrt: { … … 779 809 break; 780 810 } 781 forNode(node).setType(typeOfDouble FRound(forNode(node->child1()).m_type));811 forNode(node).setType(typeOfDoubleRounding(forNode(node->child1()).m_type)); 782 812 break; 783 813 } -
trunk/Source/JavaScriptCore/dfg/DFGArithMode.h
r164059 r183963 41 41 DoOverflow // Up-convert to the smallest type that soundly represents all possible results after input type speculation. 42 42 }; 43 44 // Define the type of operation the rounding operation will perform. 45 enum class RoundingMode { 46 Int32, // The round operation produces a integer and -0 is considered as 0. 47 Int32WithNegativeZeroCheck, // The round operation produces a integer and checks for -0. 48 Double // The round operation produce a double. The result can be -0, NaN or (+/-)Infinity. 49 }; 50 43 51 } // namespace Arith 44 52 … … 123 131 } 124 132 133 inline bool producesInteger(Arith::RoundingMode mode) 134 { 135 return mode == Arith::RoundingMode::Int32WithNegativeZeroCheck || mode == Arith::RoundingMode::Int32; 136 } 137 138 inline bool shouldCheckNegativeZero(Arith::RoundingMode mode) 139 { 140 return mode == Arith::RoundingMode::Int32WithNegativeZeroCheck; 141 } 142 125 143 } } // namespace JSC::DFG 126 144 -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r183373 r183963 2045 2045 return true; 2046 2046 } 2047 2047 case RoundIntrinsic: { 2048 if (argumentCountIncludingThis == 1) { 2049 insertChecks(); 2050 set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantNaN))); 2051 return true; 2052 } 2053 if (argumentCountIncludingThis == 2) { 2054 insertChecks(); 2055 Node* operand = get(virtualRegisterForArgument(1, registerOffset)); 2056 Node* roundNode = addToGraph(ArithRound, OpInfo(0), OpInfo(prediction), operand); 2057 set(VirtualRegister(resultOperand), roundNode); 2058 return true; 2059 } 2060 return false; 2061 } 2048 2062 case IMulIntrinsic: { 2049 2063 if (argumentCountIncludingThis != 3) -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.h
r183812 r183963 135 135 case ArithSqrt: 136 136 case ArithFRound: 137 case ArithRound: 137 138 case ArithSin: 138 139 case ArithCos: -
trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
r183812 r183963 84 84 case ArithPow: 85 85 case ArithSqrt: 86 case ArithRound: 86 87 case ArithFRound: 87 88 case ArithSin: -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r183897 r183963 321 321 fixDoubleOrBooleanEdge(node->child1()); 322 322 fixDoubleOrBooleanEdge(node->child2()); 323 break; 324 } 325 326 case ArithRound: { 327 if (node->child1()->shouldSpeculateInt32OrBooleanForArithmetic() && node->canSpeculateInt32(FixupPass)) { 328 fixIntOrBooleanEdge(node->child1()); 329 insertCheck<Int32Use>(m_indexInBlock, node->child1().node()); 330 node->convertToIdentity(); 331 break; 332 } 333 fixDoubleOrBooleanEdge(node->child1()); 334 335 if (isInt32OrBooleanSpeculation(node->getHeapPrediction()) && m_graph.roundShouldSpeculateInt32(node, FixupPass)) { 336 node->setResult(NodeResultInt32); 337 if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags())) 338 node->setArithRoundingMode(Arith::RoundingMode::Int32); 339 else 340 node->setArithRoundingMode(Arith::RoundingMode::Int32WithNegativeZeroCheck); 341 } else { 342 node->setResult(NodeResultDouble); 343 node->setArithRoundingMode(Arith::RoundingMode::Double); 344 } 323 345 break; 324 346 } -
trunk/Source/JavaScriptCore/dfg/DFGGraph.h
r183650 r183963 315 315 && negate->canSpeculateInt52(pass); 316 316 } 317 318 bool roundShouldSpeculateInt32(Node* arithRound, PredictionPass pass) 319 { 320 ASSERT(arithRound->op() == ArithRound); 321 return arithRound->canSpeculateInt32(pass) && !hasExitSite(arithRound->origin.semantic, Overflow) && !hasExitSite(arithRound->origin.semantic, NegativeZero); 322 } 317 323 318 324 static const char *opName(NodeType); -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r183819 r183963 873 873 { 874 874 NodeFlags result = m_flags & NodeArithFlagsMask; 875 if (op() == ArithMul || op() == ArithDiv || op() == ArithMod || op() == ArithNegate || op() == ArithPow || op() == DoubleAsInt32)875 if (op() == ArithMul || op() == ArithDiv || op() == ArithMod || op() == ArithNegate || op() == ArithPow || op() == ArithRound || op() == DoubleAsInt32) 876 876 return result; 877 877 return result & ~NodeBytecodeNeedsNegZero; … … 1243 1243 { 1244 1244 switch (op()) { 1245 case ArithRound: 1245 1246 case GetDirectPname: 1246 1247 case GetById: … … 1564 1565 m_opInfo = mode; 1565 1566 } 1567 1568 bool hasArithRoundingMode() 1569 { 1570 return op() == ArithRound; 1571 } 1572 1573 Arith::RoundingMode arithRoundingMode() 1574 { 1575 ASSERT(hasArithRoundingMode()); 1576 return static_cast<Arith::RoundingMode>(m_opInfo); 1577 } 1578 1579 void setArithRoundingMode(Arith::RoundingMode mode) 1580 { 1581 ASSERT(hasArithRoundingMode()); 1582 m_opInfo = static_cast<uintptr_t>(mode); 1583 } 1566 1584 1567 1585 bool hasVirtualRegister() -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r183812 r183963 151 151 macro(ArithFRound, NodeResultNumber) \ 152 152 macro(ArithPow, NodeResultNumber) \ 153 macro(ArithRound, NodeResultNumber) \ 153 154 macro(ArithSqrt, NodeResultNumber) \ 154 155 macro(ArithSin, NodeResultNumber) \ -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r183812 r183963 348 348 break; 349 349 } 350 350 351 case ArithRound: { 352 if (isInt32OrBooleanSpeculation(node->getHeapPrediction()) && m_graph.roundShouldSpeculateInt32(node, m_pass)) 353 changed |= setPrediction(SpecInt32); 354 else 355 changed |= setPrediction(SpecBytecodeDouble); 356 break; 357 } 358 351 359 case ArithAbs: { 352 360 SpeculatedType child = node->child1()->prediction(); -
trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
r183812 r183963 155 155 case ArithSqrt: 156 156 case ArithFRound: 157 case ArithRound: 157 158 case ArithSin: 158 159 case ArithCos: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r183897 r183963 3545 3545 } 3546 3546 3547 void SpeculativeJIT::compileArithRound(Node* node) 3548 { 3549 ASSERT(node->child1().useKind() == DoubleRepUse); 3550 3551 SpeculateDoubleOperand value(this, node->child1()); 3552 FPRReg valueFPR = value.fpr(); 3553 flushRegisters(); 3554 FPRResult roundedResultAsDouble(this); 3555 FPRReg resultFPR = roundedResultAsDouble.fpr(); 3556 callOperation(jsRound, resultFPR, valueFPR); 3557 3558 if (producesInteger(node->arithRoundingMode())) { 3559 GPRTemporary roundedResultAsInt32(this); 3560 FPRTemporary scratch(this); 3561 FPRReg scratchFPR = scratch.fpr(); 3562 GPRReg resultGPR = roundedResultAsInt32.gpr(); 3563 JITCompiler::JumpList failureCases; 3564 m_jit.branchConvertDoubleToInt32(resultFPR, resultGPR, failureCases, scratchFPR, shouldCheckNegativeZero(node->arithRoundingMode())); 3565 speculationCheck(Overflow, JSValueRegs(), node, failureCases); 3566 3567 int32Result(resultGPR, node); 3568 } else 3569 doubleResult(resultFPR, node); 3570 } 3571 3547 3572 void SpeculativeJIT::compileArithSqrt(Node* node) 3548 3573 { -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r183724 r183963 2200 2200 void compileArithMod(Node*); 2201 2201 void compileArithPow(Node*); 2202 void compileArithRound(Node*); 2202 2203 void compileArithSqrt(Node*); 2203 2204 void compileArithLog(Node*); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r183812 r183963 2170 2170 break; 2171 2171 } 2172 2173 case ArithRound: 2174 compileArithRound(node); 2175 break; 2172 2176 2173 2177 case ArithSin: { -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r183812 r183963 2313 2313 break; 2314 2314 } 2315 2316 case ArithRound: 2317 compileArithRound(node); 2318 break; 2315 2319 2316 2320 case ArithSin: { -
trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
r183812 r183963 64 64 case BitURShift: 65 65 case CheckStructure: 66 case DoubleAsInt32: 66 67 case ArrayifyToStructure: 67 68 case PutStructure: … … 90 91 case ArithCos: 91 92 case ArithPow: 93 case ArithRound: 92 94 case ArithSqrt: 93 95 case ArithLog: -
trunk/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h
r183724 r183963 36 36 37 37 #define FOR_EACH_FTL_INTRINSIC(macro) \ 38 macro(ceil64, "llvm.ceil.f64", functionType(doubleType, doubleType)) \ 38 39 macro(ctlz32, "llvm.ctlz.i32", functionType(int32, int32, boolean)) \ 39 40 macro(addWithOverflow32, "llvm.sadd.with.overflow.i32", functionType(structType(m_context, int32, boolean), int32, int32)) \ -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
r183944 r183963 444 444 compileDoubleRep(); 445 445 break; 446 case DoubleAsInt32: 447 compileDoubleAsInt32(); 448 break; 446 449 case ValueRep: 447 450 compileValueRep(); … … 505 508 case ArithPow: 506 509 compileArithPow(); 510 break; 511 case ArithRound: 512 compileArithRound(); 507 513 break; 508 514 case ArithSqrt: … … 971 977 } 972 978 } 973 979 980 void compileDoubleAsInt32() 981 { 982 LValue integerValue = convertDoubleToInt32(lowDouble(m_node->child1()), shouldCheckNegativeZero(m_node->arithMode())); 983 setInt32(integerValue); 984 } 985 974 986 void compileValueRep() 975 987 { … … 1760 1772 setDouble(m_out.phi(m_out.doubleType, powDoubleIntResult, powResult, pureNan)); 1761 1773 } 1774 } 1775 1776 void compileArithRound() 1777 { 1778 LBasicBlock realPartIsMoreThanHalf = FTL_NEW_BLOCK(m_out, ("ArithRound should round down")); 1779 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithRound continuation")); 1780 1781 LValue value = lowDouble(m_node->child1()); 1782 LValue integerValue = m_out.ceil64(value); 1783 ValueFromBlock integerValueResult = m_out.anchor(integerValue); 1784 1785 LValue realPart = m_out.doubleSub(integerValue, value); 1786 1787 m_out.branch(m_out.doubleGreaterThanOrUnordered(realPart, m_out.constDouble(0.5)), unsure(realPartIsMoreThanHalf), unsure(continuation)); 1788 1789 LBasicBlock lastNext = m_out.appendTo(realPartIsMoreThanHalf, continuation); 1790 LValue integerValueRoundedDown = m_out.doubleSub(integerValue, m_out.constDouble(1)); 1791 ValueFromBlock integerValueRoundedDownResult = m_out.anchor(integerValueRoundedDown); 1792 m_out.jump(continuation); 1793 m_out.appendTo(continuation, lastNext); 1794 1795 LValue result = m_out.phi(m_out.doubleType, integerValueResult, integerValueRoundedDownResult); 1796 1797 if (producesInteger(m_node->arithRoundingMode())) { 1798 LValue integerValue = convertDoubleToInt32(result, shouldCheckNegativeZero(m_node->arithRoundingMode())); 1799 setInt32(integerValue); 1800 } else 1801 setDouble(result); 1762 1802 } 1763 1803 … … 7236 7276 return possibleResult; 7237 7277 } 7238 7278 7279 LValue convertDoubleToInt32(LValue value, bool shouldCheckNegativeZero) 7280 { 7281 LValue integerValue = m_out.fpToInt32(value); 7282 LValue integerValueConvertedToDouble = m_out.intToDouble(integerValue); 7283 LValue valueNotConvertibleToInteger = m_out.doubleNotEqualOrUnordered(value, integerValueConvertedToDouble); 7284 speculate(Overflow, FormattedValue(ValueFormatDouble, value), m_node, valueNotConvertibleToInteger); 7285 7286 if (shouldCheckNegativeZero) { 7287 LBasicBlock valueIsZero = FTL_NEW_BLOCK(m_out, ("ConvertDoubleToInt32 on zero")); 7288 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ConvertDoubleToInt32 continuation")); 7289 m_out.branch(m_out.isZero32(integerValue), unsure(valueIsZero), unsure(continuation)); 7290 7291 LBasicBlock lastNext = m_out.appendTo(valueIsZero, continuation); 7292 7293 LValue doubleBitcastToInt64 = m_out.bitCast(value, m_out.int64); 7294 LValue signBitSet = m_out.lessThan(doubleBitcastToInt64, m_out.constInt64(0)); 7295 7296 speculate(NegativeZero, FormattedValue(ValueFormatDouble, value), m_node, signBitSet); 7297 m_out.jump(continuation); 7298 m_out.appendTo(continuation, lastNext); 7299 } 7300 return integerValue; 7301 } 7302 7239 7303 LValue isNumber(LValue jsValue, SpeculatedType type = SpecFullTop) 7240 7304 { -
trunk/Source/JavaScriptCore/ftl/FTLOutput.h
r183525 r183963 140 140 LValue insertElement(LValue vector, LValue element, LValue index) { return buildInsertElement(m_builder, vector, element, index); } 141 141 142 LValue ceil64(LValue operand) 143 { 144 return call(ceil64Intrinsic(), operand); 145 } 142 146 LValue ctlz32(LValue xOperand, LValue yOperand) 143 147 { -
trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp
r183358 r183963 33 33 #include "JSArrayIterator.h" 34 34 #include "JSStack.h" 35 #include "MathCommon.h" 35 36 #include "MaxFrameExtentForSlowPathCall.h" 36 37 #include "JSCInlines.h" … … 684 685 enum MathThunkCallingConvention { }; 685 686 typedef MathThunkCallingConvention(*MathThunk)(MathThunkCallingConvention); 686 extern "C" {687 688 double jsRound(double) REFERENCED_FROM_ASM;689 double jsRound(double d)690 {691 double integer = ceil(d);692 return integer - (integer - d > 0.5);693 }694 695 }696 687 697 688 #if CPU(X86_64) && COMPILER(GCC) && (OS(DARWIN) || OS(LINUX)) -
trunk/Source/JavaScriptCore/runtime/MathCommon.cpp
r180262 r183963 421 421 } 422 422 423 extern "C" { 424 double jsRound(double value) 425 { 426 double integer = ceil(value); 427 return integer - (integer - value > 0.5); 428 } 429 } 430 423 431 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/MathCommon.h
r183358 r183963 55 55 } 56 56 57 extern "C" { 58 double JIT_OPERATION jsRound(double value) REFERENCED_FROM_ASM WTF_INTERNAL; 59 } 60 57 61 } 58 62 -
trunk/Source/JavaScriptCore/runtime/MathObject.cpp
r183785 r183963 269 269 EncodedJSValue JSC_HOST_CALL mathProtoFuncRound(ExecState* exec) 270 270 { 271 double arg = exec->argument(0).toNumber(exec); 272 double integer = ceil(arg); 273 return JSValue::encode(jsNumber(integer - (integer - arg > 0.5))); 271 return JSValue::encode(jsNumber(jsRound(exec->argument(0).toNumber(exec)))); 274 272 } 275 273
Note:
See TracChangeset
for help on using the changeset viewer.