Changeset 180360 in webkit
- Timestamp:
- Feb 19, 2015, 1:08:21 PM (10 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 2 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r180345 r180360 1 2015-02-19 Benjamin Poulain <bpoulain@apple.com> 2 3 Refine the FTL part of ArithPow 4 https://bugs.webkit.org/show_bug.cgi?id=141792 5 6 Reviewed by Filip Pizlo. 7 8 This patch refines the FTL lowering of ArithPow. This was left out 9 of the original patch to keep it simpler. 10 11 * ftl/FTLLowerDFGToLLVM.cpp: 12 (JSC::FTL::LowerDFGToLLVM::compileArithPow): 13 Two improvements here: 14 1) Do not generate the NaN check unless we know the exponent might be a NaN. 15 2) Use one BasicBlock per check with the appropriate weight. Now that we have 16 one branch per test, move the Infinity check before the check for 1 since 17 it is the less common case. 18 19 * tests/stress/math-pow-becomes-custom-function.js: Added. 20 Test for changing the Math.pow() function after it has been optimized. 21 22 * tests/stress/math-pow-nan-behaviors.js: 23 The previous tests were only going as far as the DFGAbstractInterpreter 24 were the operations were replaced by the equivalent constant. 25 26 I duplicated the test functions to also test the dynamic behavior of DFG 27 and FTL. 28 29 * tests/stress/math-pow-with-constants.js: 30 Add cases covering exponent constants. LLVM removes many value 31 checks for those. 32 33 * tests/stress/math-pow-with-never-NaN-exponent.js: Added. 34 Test for the new optimization removing the NaN check. 35 1 36 2015-02-19 Csaba Osztrogonác <ossy@webkit.org> 2 37 -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
r180317 r180360 1660 1660 LBasicBlock integerExponentIsSmallBlock = FTL_NEW_BLOCK(m_out, ("ArithPow test integer exponent is small.")); 1661 1661 LBasicBlock integerExponentPowBlock = FTL_NEW_BLOCK(m_out, ("ArithPow pow(double, (int)double).")); 1662 LBasicBlock doubleExponentPowBlock = FTL_NEW_BLOCK(m_out, ("ArithPow pow(double, double).")); 1662 LBasicBlock doubleExponentPowBlockEntry = FTL_NEW_BLOCK(m_out, ("ArithPow pow(double, double).")); 1663 LBasicBlock nanExceptionExponentIsInfinity = FTL_NEW_BLOCK(m_out, ("ArithPow NaN Exception, check exponent is infinity.")); 1664 LBasicBlock nanExceptionBaseIsOne = FTL_NEW_BLOCK(m_out, ("ArithPow NaN Exception, check base is one.")); 1663 1665 LBasicBlock powBlock = FTL_NEW_BLOCK(m_out, ("ArithPow regular pow")); 1664 LBasicBlock nanException = FTL_NEW_BLOCK(m_out, ("ArithPow NaN Exception"));1666 LBasicBlock nanExceptionResultIsNaN = FTL_NEW_BLOCK(m_out, ("ArithPow NaN Exception, result is NaN.")); 1665 1667 LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("ArithPow continuation")); 1666 1668 … … 1668 1670 LValue integerExponentConvertedToDouble = m_out.intToDouble(integerExponent); 1669 1671 LValue exponentIsInteger = m_out.doubleEqual(exponent, integerExponentConvertedToDouble); 1670 m_out.branch(exponentIsInteger, unsure(integerExponentIsSmallBlock), unsure(doubleExponentPowBlock ));1672 m_out.branch(exponentIsInteger, unsure(integerExponentIsSmallBlock), unsure(doubleExponentPowBlockEntry)); 1671 1673 1672 1674 LBasicBlock lastNext = m_out.appendTo(integerExponentIsSmallBlock, integerExponentPowBlock); 1673 1675 LValue integerExponentBelow1000 = m_out.below(integerExponent, m_out.constInt32(1000)); 1674 m_out.branch(integerExponentBelow1000, usually(integerExponentPowBlock), rarely(doubleExponentPowBlock ));1675 1676 m_out.appendTo(integerExponentPowBlock, doubleExponentPowBlock );1676 m_out.branch(integerExponentBelow1000, usually(integerExponentPowBlock), rarely(doubleExponentPowBlockEntry)); 1677 1678 m_out.appendTo(integerExponentPowBlock, doubleExponentPowBlockEntry); 1677 1679 ValueFromBlock powDoubleIntResult = m_out.anchor(m_out.doublePowi(base, integerExponent)); 1678 1680 m_out.jump(continuation); 1679 1681 1680 m_out.appendTo(doubleExponentPowBlock, powBlock);1681 1682 // If y is NaN, the result is NaN. 1682 // FIXME: shouldn't we only check that if the type of child2() might have NaN? 1683 LValue exponentIsNaN = m_out.doubleNotEqualOrUnordered(exponent, exponent); 1683 m_out.appendTo(doubleExponentPowBlockEntry, nanExceptionExponentIsInfinity); 1684 LValue exponentIsNaN; 1685 if (m_state.forNode(m_node->child2()).m_type & SpecDoubleNaN) 1686 exponentIsNaN = m_out.doubleNotEqualOrUnordered(exponent, exponent); 1687 else 1688 exponentIsNaN = m_out.booleanFalse; 1689 m_out.branch(exponentIsNaN, rarely(nanExceptionResultIsNaN), usually(nanExceptionExponentIsInfinity)); 1684 1690 1685 1691 // If abs(x) is 1 and y is +infinity, the result is NaN. 1686 1692 // If abs(x) is 1 and y is -infinity, the result is NaN. 1693 m_out.appendTo(nanExceptionExponentIsInfinity, nanExceptionBaseIsOne); 1687 1694 LValue absoluteExponent = m_out.doubleAbs(exponent); 1688 1695 LValue absoluteExponentIsInfinity = m_out.doubleEqual(absoluteExponent, m_out.constDouble(std::numeric_limits<double>::infinity())); 1696 m_out.branch(absoluteExponentIsInfinity, rarely(nanExceptionBaseIsOne), usually(powBlock)); 1697 1698 m_out.appendTo(nanExceptionBaseIsOne, powBlock); 1689 1699 LValue absoluteBase = m_out.doubleAbs(base); 1690 1700 LValue absoluteBaseIsOne = m_out.doubleEqual(absoluteBase, m_out.constDouble(1)); 1691 LValue oneBaseInfiniteExponent = m_out.bitAnd(absoluteExponentIsInfinity, absoluteBaseIsOne); 1692 1693 m_out.branch(m_out.bitOr(exponentIsNaN, oneBaseInfiniteExponent), rarely(nanException), usually(powBlock)); 1694 1695 m_out.appendTo(powBlock, nanException); 1701 m_out.branch(absoluteBaseIsOne, unsure(nanExceptionResultIsNaN), unsure(powBlock)); 1702 1703 m_out.appendTo(powBlock, nanExceptionResultIsNaN); 1696 1704 ValueFromBlock powResult = m_out.anchor(m_out.doublePow(base, exponent)); 1697 1705 m_out.jump(continuation); 1698 1706 1699 m_out.appendTo(nanException , continuation);1707 m_out.appendTo(nanExceptionResultIsNaN, continuation); 1700 1708 ValueFromBlock pureNan = m_out.anchor(m_out.constDouble(PNaN)); 1701 1709 m_out.jump(continuation); -
trunk/Source/JavaScriptCore/tests/stress/math-pow-nan-behaviors.js
r180098 r180360 1 1 // If y is NaN, the result is NaN. 2 function testIntegerBaseWithNaNExponent () {2 function testIntegerBaseWithNaNExponentStatic() { 3 3 for (var i = 0; i < 10000; ++i) { 4 4 var result = Math.pow(5, NaN); … … 12 12 } 13 13 } 14 noInline(testIntegerBaseWithNaNExponent); 15 testIntegerBaseWithNaNExponent(); 16 17 function testFloatingPointBaseWithNaNExponent() { 14 noInline(testIntegerBaseWithNaNExponentStatic); 15 testIntegerBaseWithNaNExponentStatic(); 16 17 function mathPowIntegerBaseWithNaNExponentDynamic(x, y) { 18 return Math.pow(x, y); 19 } 20 noInline(mathPowIntegerBaseWithNaNExponentDynamic); 21 function testIntegerBaseWithNaNExponentDynamic() { 22 // Warm up with 2 integers. 23 for (var i = 0; i < 10000; ++i) { 24 var result = mathPowIntegerBaseWithNaNExponentDynamic(2, 5); 25 if (result !== 32) 26 throw "Error: bad result, mathPowIntegerBaseWithNaNExponentDynamic(2, 5) = " + result + ", expected 32." 27 } 28 29 for (var i = 0; i < 10000; ++i) { 30 var result = mathPowIntegerBaseWithNaNExponentDynamic(i, NaN); 31 if (!isNaN(result)) 32 throw "Error: bad result, mathPowIntegerBaseWithNaNExponentDynamic(i, NaN) = " + result + " with i = " + i + ", expected NaN"; 33 } 34 } 35 noInline(testIntegerBaseWithNaNExponentDynamic); 36 testIntegerBaseWithNaNExponentDynamic(); 37 38 function testFloatingPointBaseWithNaNExponentStatic() { 18 39 for (var i = 0; i < 10000; ++i) { 19 40 var result = Math.pow(5.5, NaN); … … 22 43 } 23 44 for (var i = 0; i < 10000; ++i) { 24 var result = Math.pow(i + 1, NaN);45 var result = Math.pow(i + 0.5, NaN); 25 46 if (!isNaN(result)) 26 47 throw "Error: bad result, Math.pow(i + 0.5, NaN) = " + result + " with i = " + i; 27 48 } 28 49 } 29 noInline(testFloatingPointBaseWithNaNExponent); 30 testFloatingPointBaseWithNaNExponent(); 50 noInline(testFloatingPointBaseWithNaNExponentStatic); 51 testFloatingPointBaseWithNaNExponentStatic(); 52 53 function mathPowFloatingPointBaseWithNaNExponentDynamic(x, y) { 54 return Math.pow(x, y); 55 } 56 noInline(mathPowFloatingPointBaseWithNaNExponentDynamic); 57 function testFloatingPointBaseWithNaNExponentDynamic() { 58 // Warm up with 2 double. 59 for (var i = 0; i < 10000; ++i) { 60 var result = mathPowFloatingPointBaseWithNaNExponentDynamic(2.5, 5.1); 61 if (result !== 107.02717054543135) 62 throw "Error: bad result, mathPowFloatingPointBaseWithNaNExponentDynamic(2.5, 5.1) = " + result + ", expected 107.02717054543135." 63 } 64 65 for (var i = 0; i < 10000; ++i) { 66 var result = mathPowFloatingPointBaseWithNaNExponentDynamic(i + 0.5, NaN); 67 if (!isNaN(result)) 68 throw "Error: bad result, mathPowFloatingPointBaseWithNaNExponentDynamic(i + 0.5, NaN) = " + result + " with i = " + i + ", expected NaN"; 69 } 70 } 71 noInline(testFloatingPointBaseWithNaNExponentDynamic); 72 testFloatingPointBaseWithNaNExponentDynamic(); 31 73 32 74 // If y is +0, the result is 1, even if x is NaN. 33 75 // If y is −0, the result is 1, even if x is NaN. 34 76 // If x is NaN and y is nonzero, the result is NaN. 35 function testNaNBase () {77 function testNaNBaseStatic() { 36 78 for (var i = 0; i < 10000; ++i) { 37 79 var result = Math.pow(NaN, i + 1); … … 55 97 } 56 98 } 57 noInline(testNaNBase); 58 testNaNBase(); 99 noInline(testNaNBaseStatic); 100 testNaNBaseStatic(); 101 102 function mathPowNaNBaseDynamic1(x, y) { 103 return Math.pow(x, y); 104 } 105 function mathPowNaNBaseDynamic2(x, y) { 106 return Math.pow(x, y); 107 } 108 function mathPowNaNBaseDynamic3(x, y) { 109 return Math.pow(x, y); 110 } 111 function mathPowNaNBaseDynamic4(x, y) { 112 return Math.pow(x, y); 113 } 114 noInline(mathPowNaNBaseDynamic1); 115 noInline(mathPowNaNBaseDynamic2); 116 noInline(mathPowNaNBaseDynamic3); 117 noInline(mathPowNaNBaseDynamic4); 118 function testNaNBaseDynamic() { 119 for (var i = 0; i < 10000; ++i) { 120 var result = mathPowNaNBaseDynamic1(NaN, i + 1); 121 if (!isNaN(result)) 122 throw "Error: bad result, mathPowNaNBaseDynamic1(NaN, i + 1) = " + result + " with i = " + i; 123 } 124 for (var i = 0; i < 10000; ++i) { 125 var result = mathPowNaNBaseDynamic2(NaN, i + 1.5); 126 if (!isNaN(result)) 127 throw "Error: bad result, mathPowNaNBaseDynamic2(NaN, i + 1.5) = " + result + " with i = " + i; 128 } 129 for (var i = 0; i < 10000; ++i) { 130 var result = mathPowNaNBaseDynamic3(NaN, 0); 131 if (result !== 1) 132 throw "Error: bad result, mathPowNaNBaseDynamic3(NaN, 0) = " + result; 133 } 134 for (var i = 0; i < 10000; ++i) { 135 var result = mathPowNaNBaseDynamic4(NaN, -0); 136 if (result !== 1) 137 throw "Error: bad result, mathPowNaNBaseDynamic4(NaN, -0) = " + result; 138 } 139 } 140 noInline(testNaNBaseDynamic); 141 testNaNBaseDynamic(); 59 142 60 143 // If abs(x) is 1 and y is +∞, the result is NaN. 61 144 // If abs(x) is 1 and y is −∞, the result is NaN. 62 function infiniteExponents () {145 function infiniteExponentsStatic() { 63 146 for (var i = 0; i < 10000; ++i) { 64 147 var result = Math.pow(1, Number.POSITIVE_INFINITY); … … 82 165 } 83 166 } 84 noInline(infiniteExponents); 85 infiniteExponents(); 167 noInline(infiniteExponentsStatic); 168 infiniteExponentsStatic(); 169 170 function mathPowInfiniteExponentsDynamic1(x, y) { 171 return Math.pow(x, y); 172 } 173 function mathPowInfiniteExponentsDynamic2(x, y) { 174 return Math.pow(x, y); 175 } 176 function mathPowInfiniteExponentsDynamic3(x, y) { 177 return Math.pow(x, y); 178 } 179 function mathPowInfiniteExponentsDynamic4(x, y) { 180 return Math.pow(x, y); 181 } 182 noInline(mathPowInfiniteExponentsDynamic1); 183 noInline(mathPowInfiniteExponentsDynamic2); 184 noInline(mathPowInfiniteExponentsDynamic3); 185 noInline(mathPowInfiniteExponentsDynamic4); 186 function infiniteExponentsDynamic() { 187 for (var i = 0; i < 10000; ++i) { 188 var result = mathPowInfiniteExponentsDynamic1(1, Number.POSITIVE_INFINITY); 189 if (!isNaN(result)) 190 throw "Error: bad result, mathPowInfiniteExponentsDynamic1(1, Number.POSITIVE_INFINITY) = " + result; 191 } 192 for (var i = 0; i < 10000; ++i) { 193 var result = mathPowInfiniteExponentsDynamic2(-1, Number.POSITIVE_INFINITY); 194 if (!isNaN(result)) 195 throw "Error: bad result, mathPowInfiniteExponentsDynamic2(-1, Number.POSITIVE_INFINITY) = " + result; 196 } 197 for (var i = 0; i < 10000; ++i) { 198 var result = mathPowInfiniteExponentsDynamic3(1, Number.NEGATIVE_INFINITY); 199 if (!isNaN(result)) 200 throw "Error: bad result, mathPowInfiniteExponentsDynamic3(1, Number.NEGATIVE_INFINITY) = " + result; 201 } 202 for (var i = 0; i < 10000; ++i) { 203 var result = mathPowInfiniteExponentsDynamic4(-1, Number.NEGATIVE_INFINITY); 204 if (!isNaN(result)) 205 throw "Error: bad result, mathPowInfiniteExponentsDynamic4(-1, Number.NEGATIVE_INFINITY) = " + result; 206 } 207 } 208 noInline(infiniteExponentsDynamic); 209 infiniteExponentsDynamic(); -
trunk/Source/JavaScriptCore/tests/stress/math-pow-with-constants.js
r180098 r180360 114 114 } 115 115 testBaseAndExponentConstantLiterals(); 116 117 118 function exponentIsIntegerConstant(x) { 119 return Math.pow(x, 42); 120 } 121 noInline(exponentIsIntegerConstant); 122 123 function testExponentIsIntegerConstant() { 124 for (var i = 0; i < 1000; ++i) { 125 var result = exponentIsIntegerConstant(2); 126 if (result !== 4398046511104) 127 throw "Error: exponentIsIntegerConstant(2) should be 4398046511104, was = " + result; 128 } 129 for (var i = 0; i < 1000; ++i) { 130 var result = exponentIsIntegerConstant(5); 131 if (result !== 2.2737367544323207e+29) 132 throw "Error: exponentIsIntegerConstant(5) should be 2.2737367544323207e+29, was = " + result; 133 } 134 for (var i = 0; i < 1000; ++i) { 135 var result = exponentIsIntegerConstant(2.1); 136 if (result !== 34135823067412.42) 137 throw "Error: exponentIsIntegerConstant(2.1) should be 34135823067412.42, was = " + result; 138 } 139 } 140 testExponentIsIntegerConstant(); 141 142 143 function exponentIsDoubleConstant(x) { 144 return Math.pow(x, 42.5); 145 } 146 noInline(exponentIsDoubleConstant); 147 148 function testExponentIsDoubleConstant() { 149 for (var i = 0; i < 1000; ++i) { 150 var result = exponentIsDoubleConstant(2); 151 if (result !== 6219777023950.95) 152 throw "Error: exponentIsDoubleConstant(2) should be 6219777023950.95, was = " + result; 153 } 154 for (var i = 0; i < 1000; ++i) { 155 var result = exponentIsDoubleConstant(5); 156 if (result !== 5.084229945850415e+29) 157 throw "Error: exponentIsDoubleConstant(5) should be 5.084229945850415e+29, was = " + result; 158 } 159 for (var i = 0; i < 1000; ++i) { 160 var result = exponentIsDoubleConstant(2.1); 161 if (result !== 49467507261113.805) 162 throw "Error: exponentIsDoubleConstant(2.1) should be 49467507261113.805, was = " + result; 163 } 164 } 165 testExponentIsDoubleConstant(); 166 167 168 function exponentIsInfinityConstant(x) { 169 return Math.pow(x, Infinity); 170 } 171 noInline(exponentIsInfinityConstant); 172 173 function testExponentIsInfinityConstant() { 174 for (var i = 0; i < 1000; ++i) { 175 var result = exponentIsInfinityConstant(2); 176 if (result !== Infinity) 177 throw "Error: exponentIsInfinityConstant(2) should be Infinity, was = " + result; 178 } 179 for (var i = 0; i < 1000; ++i) { 180 var result = exponentIsInfinityConstant(5); 181 if (result !== Infinity) 182 throw "Error: exponentIsInfinityConstant(5) should be Infinity, was = " + result; 183 } 184 for (var i = 0; i < 1000; ++i) { 185 var result = exponentIsInfinityConstant(2.1); 186 if (result !== Infinity) 187 throw "Error: exponentIsInfinityConstant(2.1) should be Infinity, was = " + result; 188 } 189 } 190 testExponentIsInfinityConstant(); 191 192 193 function exponentIsNegativeInfinityConstant(x) { 194 return Math.pow(x, -Infinity); 195 } 196 noInline(exponentIsNegativeInfinityConstant); 197 198 function testExponentIsNegativeInfinityConstant() { 199 for (var i = 0; i < 1000; ++i) { 200 var result = exponentIsNegativeInfinityConstant(2); 201 if (result !== 0) 202 throw "Error: exponentIsNegativeInfinityConstant(2) should be zero, was = " + result; 203 } 204 for (var i = 0; i < 1000; ++i) { 205 var result = exponentIsNegativeInfinityConstant(5); 206 if (result !== 0) 207 throw "Error: exponentIsNegativeInfinityConstant(5) should be zero, was = " + result; 208 } 209 for (var i = 0; i < 1000; ++i) { 210 var result = exponentIsNegativeInfinityConstant(2.1); 211 if (result !== 0) 212 throw "Error: exponentIsNegativeInfinityConstant(2.1) should be zero, was = " + result; 213 } 214 } 215 testExponentIsNegativeInfinityConstant();
Note:
See TracChangeset
for help on using the changeset viewer.