Changeset 214774 in webkit
- Timestamp:
- Apr 3, 2017 5:33:21 AM (7 years ago)
- Location:
- releases/WebKitGTK/webkit-2.16
- Files:
-
- 3 added
- 25 edited
Legend:
- Unmodified
- Added
- Removed
-
releases/WebKitGTK/webkit-2.16/JSTests/ChangeLog
r214773 r214774 1 2017-03-21 Yusuke Suzuki <utatane.tea@gmail.com> 2 3 [JSC] Optimize Number.prototype.toString on Int32 / Int52 / Double 4 https://bugs.webkit.org/show_bug.cgi?id=167454 5 6 Reviewed by Saam Barati. 7 8 * stress/number-to-string-abstract-operation.js: Added. 9 (shouldBe): 10 (int32ToString): 11 (shouldBe.int32ToString.new.Number.int52ToString): 12 (shouldBe.int32ToString.new.Number): 13 (shouldBe.doubleToString): 14 * stress/number-to-string-radix.js: Added. 15 (shouldBe): 16 (int32ToString): 17 (shouldBe.int32ToString.new.Number.int52ToString): 18 (shouldBe.int32ToString.new.Number): 19 (shouldBe.doubleToString): 20 * stress/number-to-string.js: Added. 21 (shouldBe): 22 (int32ToString): 23 (shouldBe.int32ToString.new.Number.int52ToString): 24 (shouldBe.int32ToString.new.Number): 25 (shouldBe.doubleToString): 26 1 27 2017-02-23 Saam Barati <sbarati@apple.com> 2 28 -
releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/ChangeLog
r214773 r214774 1 2017-03-21 Yusuke Suzuki <utatane.tea@gmail.com> 2 3 [JSC] Optimize Number.prototype.toString on Int32 / Int52 / Double 4 https://bugs.webkit.org/show_bug.cgi?id=167454 5 6 Reviewed by Saam Barati. 7 8 This patch improves Number.toString(radix) performance 9 by introducing NumberToStringWithRadix DFG node. It directly 10 calls the operation and it always returns String. 11 12 baseline patched 13 14 stanford-crypto-sha256-iterative 45.130+-0.928 44.032+-1.184 might be 1.0250x faster 15 1 16 2017-02-24 Saam Barati <sbarati@apple.com> 2 17 … … 28 43 case. We also set up CSE rules for parseInt(someString, someIntRadix) 29 44 because it's a "pure" operation (modulo resolving a rope). 45 * dfg/DFGAbstractInterpreterInlines.h: 46 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 47 * dfg/DFGByteCodeParser.cpp: 48 (JSC::DFG::ByteCodeParser::handleIntrinsicCall): 49 * dfg/DFGClobberize.h: 50 (JSC::DFG::clobberize): 51 * dfg/DFGDoesGC.cpp: 52 (JSC::DFG::doesGC): 53 * dfg/DFGFixupPhase.cpp: 54 (JSC::DFG::FixupPhase::fixupNode): 55 (JSC::DFG::FixupPhase::fixupToStringOrCallStringConstructor): 56 * dfg/DFGNodeType.h: 57 * dfg/DFGOperations.cpp: 58 * dfg/DFGOperations.h: 59 * dfg/DFGPredictionPropagationPhase.cpp: 60 * dfg/DFGSafeToExecute.h: 61 (JSC::DFG::safeToExecute): 62 * dfg/DFGSpeculativeJIT.cpp: 63 (JSC::DFG::SpeculativeJIT::compileToStringOrCallStringConstructor): 64 (JSC::DFG::SpeculativeJIT::compileToStringOrCallStringConstructorOnNumber): 65 (JSC::DFG::SpeculativeJIT::compileNumberToStringWithRadix): 66 (JSC::DFG::SpeculativeJIT::compileToStringOrCallStringConstructorOnCell): Deleted. 67 * dfg/DFGSpeculativeJIT.h: 68 (JSC::DFG::SpeculativeJIT::callOperation): 69 * dfg/DFGSpeculativeJIT32_64.cpp: 70 (JSC::DFG::SpeculativeJIT::compile): 71 * dfg/DFGSpeculativeJIT64.cpp: 72 (JSC::DFG::SpeculativeJIT::compile): 73 * dfg/DFGStrengthReductionPhase.cpp: 74 (JSC::DFG::StrengthReductionPhase::handleNode): 75 * ftl/FTLCapabilities.cpp: 76 (JSC::FTL::canCompile): 77 * ftl/FTLLowerDFGToB3.cpp: 78 (JSC::FTL::DFG::LowerDFGToB3::compileNode): 79 (JSC::FTL::DFG::LowerDFGToB3::compileToStringOrCallStringConstructor): 80 (JSC::FTL::DFG::LowerDFGToB3::compileNumberToStringWithRadix): 81 * jit/CCallHelpers.h: 82 (JSC::CCallHelpers::setupArgumentsWithExecState): 83 * jit/JITOperations.h: 84 * runtime/Intrinsic.h: 85 * runtime/NumberPrototype.cpp: 86 (JSC::int52ToStringWithRadix): 87 (JSC::int32ToStringInternal): 88 (JSC::numberToStringInternal): 89 (JSC::int32ToString): 90 (JSC::int52ToString): 91 (JSC::numberToString): 92 (JSC::numberProtoFuncToString): 93 (JSC::integerValueToString): Deleted. 94 * runtime/NumberPrototype.h: 95 * runtime/StringPrototype.cpp: 96 (JSC::StringPrototype::finishCreation): 97 30 98 31 99 This looks to be a 4% Octane/Box2D progression. -
releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r214773 r214774 1859 1859 break; 1860 1860 case StringOrStringObjectUse: 1861 case Int32Use: 1862 case Int52RepUse: 1863 case DoubleRepUse: 1861 1864 case NotCellUse: 1862 1865 break; … … 1872 1875 break; 1873 1876 } 1877 1878 case NumberToStringWithRadix: 1879 clobberWorld(node->origin.semantic, clobberLimit); 1880 forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get()); 1881 break; 1874 1882 1875 1883 case NewStringObject: { -
releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r214773 r214774 2712 2712 } 2713 2713 2714 case ToLowerCaseIntrinsic: {2714 case StringPrototypeToLowerCaseIntrinsic: { 2715 2715 if (argumentCountIncludingThis != 1) 2716 2716 return false; … … 2723 2723 Node* result = addToGraph(ToLowerCase, thisString); 2724 2724 set(VirtualRegister(resultOperand), result); 2725 return true; 2726 } 2727 2728 case NumberPrototypeToStringIntrinsic: { 2729 if (argumentCountIncludingThis != 1 && argumentCountIncludingThis != 2) 2730 return false; 2731 2732 if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType)) 2733 return false; 2734 2735 insertChecks(); 2736 Node* thisNumber = get(virtualRegisterForArgument(0, registerOffset)); 2737 if (argumentCountIncludingThis == 1) { 2738 Node* result = addToGraph(ToString, thisNumber); 2739 set(VirtualRegister(resultOperand), result); 2740 } else { 2741 Node* radix = get(virtualRegisterForArgument(1, registerOffset)); 2742 Node* result = addToGraph(NumberToStringWithRadix, thisNumber, radix); 2743 set(VirtualRegister(resultOperand), result); 2744 } 2725 2745 return true; 2726 2746 } -
releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/dfg/DFGClobberize.h
r214773 r214774 1402 1402 return; 1403 1403 1404 case Int32Use: 1405 case Int52RepUse: 1406 case DoubleRepUse: 1404 1407 case NotCellUse: 1405 1408 def(PureValue(node)); … … 1449 1452 case ToLowerCase: 1450 1453 def(PureValue(node)); 1454 return; 1455 1456 case NumberToStringWithRadix: 1457 read(World); 1458 write(Heap); 1451 1459 return; 1452 1460 -
releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
r214773 r214774 179 179 case ToString: 180 180 case CallStringConstructor: 181 case NumberToStringWithRadix: 181 182 case In: 182 183 case HasOwnProperty: -
releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r214773 r214774 1751 1751 // are correct. 1752 1752 fixEdge<StringUse>(node->child1()); 1753 break; 1754 } 1755 1756 case NumberToStringWithRadix: { 1757 if (node->child1()->shouldSpeculateInt32()) 1758 fixEdge<Int32Use>(node->child1()); 1759 else if (enableInt52() && node->child1()->shouldSpeculateAnyInt()) 1760 fixEdge<Int52RepUse>(node->child1()); 1761 else 1762 fixEdge<DoubleRepUse>(node->child1()); 1763 fixEdge<Int32Use>(node->child2()); 1753 1764 break; 1754 1765 } … … 2230 2241 } 2231 2242 2243 if (node->child1()->shouldSpeculateInt32()) { 2244 fixEdge<Int32Use>(node->child1()); 2245 node->clearFlags(NodeMustGenerate); 2246 return; 2247 } 2248 2249 if (enableInt52() && node->child1()->shouldSpeculateAnyInt()) { 2250 fixEdge<Int52RepUse>(node->child1()); 2251 node->clearFlags(NodeMustGenerate); 2252 return; 2253 } 2254 2255 if (node->child1()->shouldSpeculateNumber()) { 2256 fixEdge<DoubleRepUse>(node->child1()); 2257 node->clearFlags(NodeMustGenerate); 2258 return; 2259 } 2260 2232 2261 // ToString(Symbol) throws an error. So if the child1 can include Symbols, 2233 2262 // we need to care about it in the clobberize. In the following case, -
releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/dfg/DFGNodeType.h
r214773 r214774 336 336 macro(CallObjectConstructor, NodeResultJS) \ 337 337 macro(CallStringConstructor, NodeResultJS | NodeMustGenerate) \ 338 macro(NumberToStringWithRadix, NodeResultJS | NodeMustGenerate) \ 338 339 macro(NewStringObject, NodeResultJS) \ 339 340 macro(MakeRope, NodeResultJS) \ -
releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/dfg/DFGOperations.cpp
r214773 r214774 1645 1645 } 1646 1646 1647 char* JIT_OPERATION operationInt32ToString(ExecState* exec, int32_t value, int32_t radix) 1648 { 1649 VM& vm = exec->vm(); 1650 NativeCallFrameTracer tracer(&vm, exec); 1651 1652 auto scope = DECLARE_THROW_SCOPE(vm); 1653 1654 if (radix < 2 || radix > 36) { 1655 throwVMError(exec, scope, createRangeError(exec, ASCIILiteral("toString() radix argument must be between 2 and 36"))); 1656 return nullptr; 1657 } 1658 1659 return reinterpret_cast<char*>(int32ToString(vm, value, radix)); 1660 } 1661 1662 char* JIT_OPERATION operationInt52ToString(ExecState* exec, int64_t value, int32_t radix) 1663 { 1664 VM& vm = exec->vm(); 1665 NativeCallFrameTracer tracer(&vm, exec); 1666 1667 auto scope = DECLARE_THROW_SCOPE(vm); 1668 1669 if (radix < 2 || radix > 36) { 1670 throwVMError(exec, scope, createRangeError(exec, ASCIILiteral("toString() radix argument must be between 2 and 36"))); 1671 return nullptr; 1672 } 1673 1674 return reinterpret_cast<char*>(int52ToString(vm, value, radix)); 1675 } 1676 1677 char* JIT_OPERATION operationDoubleToString(ExecState* exec, double value, int32_t radix) 1678 { 1679 VM& vm = exec->vm(); 1680 NativeCallFrameTracer tracer(&vm, exec); 1681 1682 auto scope = DECLARE_THROW_SCOPE(vm); 1683 1684 if (radix < 2 || radix > 36) { 1685 throwVMError(exec, scope, createRangeError(exec, ASCIILiteral("toString() radix argument must be between 2 and 36"))); 1686 return nullptr; 1687 } 1688 1689 return reinterpret_cast<char*>(numberToString(vm, value, radix)); 1690 } 1691 1692 char* JIT_OPERATION operationInt32ToStringWithValidRadix(ExecState* exec, int32_t value, int32_t radix) 1693 { 1694 VM& vm = exec->vm(); 1695 NativeCallFrameTracer tracer(&vm, exec); 1696 1697 return reinterpret_cast<char*>(int32ToString(vm, value, radix)); 1698 } 1699 1700 char* JIT_OPERATION operationInt52ToStringWithValidRadix(ExecState* exec, int64_t value, int32_t radix) 1701 { 1702 VM& vm = exec->vm(); 1703 NativeCallFrameTracer tracer(&vm, exec); 1704 1705 return reinterpret_cast<char*>(int52ToString(vm, value, radix)); 1706 } 1707 1708 char* JIT_OPERATION operationDoubleToStringWithValidRadix(ExecState* exec, double value, int32_t radix) 1709 { 1710 VM& vm = exec->vm(); 1711 NativeCallFrameTracer tracer(&vm, exec); 1712 1713 return reinterpret_cast<char*>(numberToString(vm, value, radix)); 1714 } 1715 1647 1716 JSString* JIT_OPERATION operationSingleCharacterString(ExecState* exec, int32_t character) 1648 1717 { -
releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/dfg/DFGOperations.h
r214773 r214774 160 160 JSString* JIT_OPERATION operationToLowerCase(ExecState*, JSString*, uint32_t); 161 161 162 char* JIT_OPERATION operationInt32ToString(ExecState*, int32_t, int32_t); 163 char* JIT_OPERATION operationInt52ToString(ExecState*, int64_t, int32_t); 164 char* JIT_OPERATION operationDoubleToString(ExecState*, double, int32_t); 165 char* JIT_OPERATION operationInt32ToStringWithValidRadix(ExecState*, int32_t, int32_t); 166 char* JIT_OPERATION operationInt52ToStringWithValidRadix(ExecState*, int64_t, int32_t); 167 char* JIT_OPERATION operationDoubleToStringWithValidRadix(ExecState*, double, int32_t); 168 162 169 int32_t JIT_OPERATION operationMapHash(ExecState*, EncodedJSValue input); 163 170 JSCell* JIT_OPERATION operationJSMapFindBucket(ExecState*, JSCell*, EncodedJSValue, int32_t); -
releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r214773 r214774 898 898 case CallStringConstructor: 899 899 case ToString: 900 case NumberToStringWithRadix: 900 901 case MakeRope: 901 902 case StrCat: { -
releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
r214773 r214774 289 289 case ToString: 290 290 case ToNumber: 291 case NumberToStringWithRadix: 291 292 case SetFunctionName: 292 293 case StrCat: -
releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r214773 r214774 7910 7910 } 7911 7911 7912 void SpeculativeJIT::compileToStringOrCallStringConstructorOnCell(Node* node) 7913 { 7914 if (node->child1().useKind() == NotCellUse) { 7912 void SpeculativeJIT::compileToStringOrCallStringConstructor(Node* node) 7913 { 7914 switch (node->child1().useKind()) { 7915 case NotCellUse: { 7915 7916 JSValueOperand op1(this, node->child1(), ManualOperandSpeculation); 7916 7917 JSValueRegs op1Regs = op1.jsValueRegs(); … … 7934 7935 } 7935 7936 7936 if (node->child1().useKind() == UntypedUse){7937 case UntypedUse: { 7937 7938 JSValueOperand op1(this, node->child1()); 7938 7939 JSValueRegs op1Regs = op1.jsValueRegs(); … … 7966 7967 } 7967 7968 7969 case Int32Use: 7970 case Int52RepUse: 7971 case DoubleRepUse: 7972 compileToStringOrCallStringConstructorOnNumber(node); 7973 return; 7974 7975 default: 7976 break; 7977 } 7968 7978 7969 7979 SpeculateCellOperand op1(this, node->child1()); … … 8036 8046 } 8037 8047 8048 default: 8049 RELEASE_ASSERT_NOT_REACHED(); 8050 } 8051 } 8052 8053 void SpeculativeJIT::compileToStringOrCallStringConstructorOnNumber(Node* node) 8054 { 8055 auto callToString = [&] (auto operation, GPRReg resultGPR, auto valueReg) { 8056 flushRegisters(); 8057 callOperation(operation, resultGPR, valueReg, CCallHelpers::TrustedImm32(10)); 8058 m_jit.exceptionCheck(); 8059 cellResult(resultGPR, node); 8060 }; 8061 8062 switch (node->child1().useKind()) { 8063 case Int32Use: { 8064 SpeculateStrictInt32Operand value(this, node->child1()); 8065 GPRFlushedCallResult result(this); 8066 callToString(operationInt32ToStringWithValidRadix, result.gpr(), value.gpr()); 8067 break; 8068 } 8069 8070 #if USE(JSVALUE64) 8071 case Int52RepUse: { 8072 SpeculateStrictInt52Operand value(this, node->child1()); 8073 GPRFlushedCallResult result(this); 8074 callToString(operationInt52ToStringWithValidRadix, result.gpr(), value.gpr()); 8075 break; 8076 } 8077 #endif 8078 8079 case DoubleRepUse: { 8080 SpeculateDoubleOperand value(this, node->child1()); 8081 GPRFlushedCallResult result(this); 8082 callToString(operationDoubleToStringWithValidRadix, result.gpr(), value.fpr()); 8083 break; 8084 } 8085 8086 default: 8087 RELEASE_ASSERT_NOT_REACHED(); 8088 } 8089 } 8090 8091 void SpeculativeJIT::compileNumberToStringWithRadix(Node* node) 8092 { 8093 bool validRadixIsGuaranteed = false; 8094 if (node->child2()->isInt32Constant()) { 8095 int32_t radix = node->child2()->asInt32(); 8096 if (radix >= 2 && radix <= 36) 8097 validRadixIsGuaranteed = true; 8098 } 8099 8100 auto callToString = [&] (auto operation, GPRReg resultGPR, auto valueReg, GPRReg radixGPR) { 8101 flushRegisters(); 8102 callOperation(operation, resultGPR, valueReg, radixGPR); 8103 m_jit.exceptionCheck(); 8104 cellResult(resultGPR, node); 8105 }; 8106 8107 switch (node->child1().useKind()) { 8108 case Int32Use: { 8109 SpeculateStrictInt32Operand value(this, node->child1()); 8110 SpeculateStrictInt32Operand radix(this, node->child2()); 8111 GPRFlushedCallResult result(this); 8112 callToString(validRadixIsGuaranteed ? operationInt32ToStringWithValidRadix : operationInt32ToString, result.gpr(), value.gpr(), radix.gpr()); 8113 break; 8114 } 8115 8116 #if USE(JSVALUE64) 8117 case Int52RepUse: { 8118 SpeculateStrictInt52Operand value(this, node->child1()); 8119 SpeculateStrictInt32Operand radix(this, node->child2()); 8120 GPRFlushedCallResult result(this); 8121 callToString(validRadixIsGuaranteed ? operationInt52ToStringWithValidRadix : operationInt52ToString, result.gpr(), value.gpr(), radix.gpr()); 8122 break; 8123 } 8124 #endif 8125 8126 case DoubleRepUse: { 8127 SpeculateDoubleOperand value(this, node->child1()); 8128 SpeculateStrictInt32Operand radix(this, node->child2()); 8129 GPRFlushedCallResult result(this); 8130 callToString(validRadixIsGuaranteed ? operationDoubleToStringWithValidRadix : operationDoubleToString, result.gpr(), value.fpr(), radix.gpr()); 8131 break; 8132 } 8133 8038 8134 default: 8039 8135 RELEASE_ASSERT_NOT_REACHED(); -
releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r214773 r214774 1378 1378 } 1379 1379 1380 JITCompiler::Call callOperation(P_JITOperation_EZZ operation, GPRReg result, GPRReg arg1, GPRReg arg2) 1381 { 1382 m_jit.setupArgumentsWithExecState(arg1, arg2); 1383 return appendCallSetResult(operation, result); 1384 } 1385 1386 JITCompiler::Call callOperation(P_JITOperation_EZZ operation, GPRReg result, GPRReg arg1, TrustedImm32 arg2) 1387 { 1388 m_jit.setupArgumentsWithExecState(arg1, arg2); 1389 return appendCallSetResult(operation, result); 1390 } 1391 1392 JITCompiler::Call callOperation(P_JITOperation_EDZ operation, GPRReg result, FPRReg arg1, GPRReg arg2) 1393 { 1394 m_jit.setupArgumentsWithExecState(arg1, arg2); 1395 return appendCallSetResult(operation, result); 1396 } 1397 1398 JITCompiler::Call callOperation(P_JITOperation_EDZ operation, GPRReg result, FPRReg arg1, TrustedImm32 arg2) 1399 { 1400 m_jit.setupArgumentsWithExecState(arg1, arg2); 1401 return appendCallSetResult(operation, result); 1402 } 1380 1403 1381 1404 #if USE(JSVALUE64) … … 1602 1625 return appendCallSetResult(operation, result); 1603 1626 } 1627 JITCompiler::Call callOperation(P_JITOperation_EQZ operation, GPRReg result, GPRReg arg1, GPRReg arg2) 1628 { 1629 m_jit.setupArgumentsWithExecState(arg1, arg2); 1630 return appendCallSetResult(operation, result); 1631 } 1632 JITCompiler::Call callOperation(P_JITOperation_EQZ operation, GPRReg result, GPRReg arg1, TrustedImm32 arg2) 1633 { 1634 m_jit.setupArgumentsWithExecState(arg1, arg2); 1635 return appendCallSetResult(operation, result); 1636 } 1637 1604 1638 JITCompiler::Call callOperation(J_JITOperation_EZIcfZ operation, GPRReg result, int32_t arg1, InlineCallFrame* inlineCallFrame, GPRReg arg2) 1605 1639 { … … 2658 2692 void emitSwitch(Node*); 2659 2693 2660 void compileToStringOrCallStringConstructorOnCell(Node*); 2694 void compileToStringOrCallStringConstructor(Node*); 2695 void compileToStringOrCallStringConstructorOnNumber(Node*); 2696 void compileNumberToStringWithRadix(Node*); 2661 2697 void compileNewStringObject(Node*); 2662 2698 -
releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r214773 r214774 2797 2797 } 2798 2798 2799 case NumberToStringWithRadix: { 2800 compileNumberToStringWithRadix(node); 2801 break; 2802 } 2803 2799 2804 case GetByValWithThis: { 2800 2805 JSValueOperand base(this, node->child1()); … … 3731 3736 case ToString: 3732 3737 case CallStringConstructor: { 3733 compileToStringOrCallStringConstructor OnCell(node);3738 compileToStringOrCallStringConstructor(node); 3734 3739 break; 3735 3740 } -
releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r214773 r214774 3712 3712 case ToString: 3713 3713 case CallStringConstructor: { 3714 compileToStringOrCallStringConstructor OnCell(node);3714 compileToStringOrCallStringConstructor(node); 3715 3715 break; 3716 3716 } … … 5008 5008 } 5009 5009 5010 case NumberToStringWithRadix: { 5011 compileNumberToStringWithRadix(node); 5012 break; 5013 } 5014 5010 5015 case IsObject: { 5011 5016 JSValueOperand value(this, node->child1()); -
releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp
r211247 r214774 391 391 } 392 392 393 case ToString: 394 case CallStringConstructor: { 395 Edge& child1 = m_node->child1(); 396 switch (child1.useKind()) { 397 case Int32Use: 398 case Int52RepUse: 399 case DoubleRepUse: { 400 if (child1->hasConstant()) { 401 JSValue value = child1->constant()->value(); 402 if (value) { 403 String result; 404 if (value.isInt32()) 405 result = String::number(value.asInt32()); 406 else if (value.isNumber()) 407 result = String::numberToStringECMAScript(value.asNumber()); 408 409 if (!result.isNull()) { 410 m_node->convertToLazyJSConstant(m_graph, LazyJSValue::newString(m_graph, result)); 411 m_changed = true; 412 } 413 } 414 } 415 break; 416 } 417 418 default: 419 break; 420 } 421 break; 422 } 423 393 424 case GetArrayLength: { 394 425 if (m_node->arrayMode().type() == Array::Generic -
releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
r214773 r214774 280 280 case DefineAccessorProperty: 281 281 case ToLowerCase: 282 case NumberToStringWithRadix: 282 283 case CheckDOM: 283 284 case CallDOM: -
releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
r214773 r214774 1077 1077 compileToLowerCase(); 1078 1078 break; 1079 case NumberToStringWithRadix: 1080 compileNumberToStringWithRadix(); 1081 break; 1079 1082 case CheckDOM: 1080 1083 compileCheckDOM(); … … 4950 4953 return; 4951 4954 } 4955 4956 case Int32Use: 4957 setJSValue(vmCall(Int64, m_out.operation(operationInt32ToStringWithValidRadix), m_callFrame, lowInt32(m_node->child1()), m_out.constInt32(10))); 4958 return; 4959 4960 case Int52RepUse: 4961 setJSValue(vmCall(Int64, m_out.operation(operationInt52ToStringWithValidRadix), m_callFrame, lowStrictInt52(m_node->child1()), m_out.constInt32(10))); 4962 return; 4963 4964 case DoubleRepUse: 4965 setJSValue(vmCall(Int64, m_out.operation(operationDoubleToStringWithValidRadix), m_callFrame, lowDouble(m_node->child1()), m_out.constInt32(10))); 4966 return; 4952 4967 4953 4968 default: … … 9881 9896 m_out.appendTo(continuation, lastNext); 9882 9897 setJSValue(m_out.phi(pointerType(), fastResult, slowResult)); 9898 } 9899 9900 void compileNumberToStringWithRadix() 9901 { 9902 bool validRadixIsGuaranteed = false; 9903 if (m_node->child2()->isInt32Constant()) { 9904 int32_t radix = m_node->child2()->asInt32(); 9905 if (radix >= 2 && radix <= 36) 9906 validRadixIsGuaranteed = true; 9907 } 9908 9909 switch (m_node->child1().useKind()) { 9910 case Int32Use: 9911 setJSValue(vmCall(pointerType(), m_out.operation(validRadixIsGuaranteed ? operationInt32ToStringWithValidRadix : operationInt32ToString), m_callFrame, lowInt32(m_node->child1()), lowInt32(m_node->child2()))); 9912 break; 9913 case Int52RepUse: 9914 setJSValue(vmCall(pointerType(), m_out.operation(validRadixIsGuaranteed ? operationInt52ToStringWithValidRadix : operationInt52ToString), m_callFrame, lowStrictInt52(m_node->child1()), lowInt32(m_node->child2()))); 9915 break; 9916 case DoubleRepUse: 9917 setJSValue(vmCall(pointerType(), m_out.operation(validRadixIsGuaranteed ? operationDoubleToStringWithValidRadix : operationDoubleToString), m_callFrame, lowDouble(m_node->child1()), lowInt32(m_node->child2()))); 9918 break; 9919 default: 9920 RELEASE_ASSERT_NOT_REACHED(); 9921 } 9883 9922 } 9884 9923 -
releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/jit/CCallHelpers.h
r210232 r214774 862 862 863 863 ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, GPRReg arg2) 864 { 865 resetCallArguments(); 866 addCallArgument(GPRInfo::callFrameRegister); 867 addCallArgument(arg1); 868 addCallArgument(arg2); 869 } 870 871 ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, TrustedImm32 arg2) 864 872 { 865 873 resetCallArguments(); … … 1070 1078 } 1071 1079 1080 ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, TrustedImm32 arg2) 1081 { 1082 #if OS(WINDOWS) && CPU(X86_64) 1083 // On Windows, arguments map to designated registers based on the argument positions, even when there are interlaced scalar and floating point arguments. 1084 // See http://msdn.microsoft.com/en-us/library/zthk2dkh.aspx 1085 moveDouble(arg1, FPRInfo::argumentFPR1); 1086 move(arg2, GPRInfo::argumentGPR2); 1087 #else 1088 moveDouble(arg1, FPRInfo::argumentFPR0); 1089 move(arg2, GPRInfo::argumentGPR1); 1090 #endif 1091 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); 1092 } 1093 1072 1094 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, FPRReg arg3) 1073 1095 { … … 1112 1134 } 1113 1135 1136 ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, TrustedImm32 arg2) 1137 { 1138 moveDouble(arg1, FPRInfo::argumentFPR0); 1139 move(arg2, GPRInfo::argumentGPR1); 1140 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); 1141 } 1142 1114 1143 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, FPRReg arg3) 1115 1144 { … … 1146 1175 1147 1176 ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, GPRReg arg2) 1177 { 1178 move(arg2, GPRInfo::argumentGPR3); 1179 assembler().vmov(GPRInfo::argumentGPR1, GPRInfo::argumentGPR2, arg1); 1180 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); 1181 } 1182 1183 ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, TrustedImm32 arg2) 1148 1184 { 1149 1185 move(arg2, GPRInfo::argumentGPR3); … … 1199 1235 1200 1236 ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, GPRReg arg2) 1237 { 1238 assembler().vmov(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3, arg1); 1239 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); 1240 poke(arg2, 4); 1241 } 1242 1243 ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, TrustedImm32 arg2) 1201 1244 { 1202 1245 assembler().vmov(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3, arg1); -
releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/jit/JITOperations.h
r214773 r214774 312 312 typedef char* (JIT_OPERATION *P_JITOperation_EStZP)(ExecState*, Structure*, int32_t, char*); 313 313 typedef char* (JIT_OPERATION *P_JITOperation_EZZ)(ExecState*, int32_t, int32_t); 314 typedef char* (JIT_OPERATION *P_JITOperation_EQZ)(ExecState*, int64_t, int32_t); 315 typedef char* (JIT_OPERATION *P_JITOperation_EDZ)(ExecState*, double, int32_t); 314 316 typedef SlowPathReturnType (JIT_OPERATION *Sprt_JITOperation_ECli)(ExecState*, CallLinkInfo*); 315 317 typedef StringImpl* (JIT_OPERATION *T_JITOperation_EJss)(ExecState*, JSString*); -
releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/runtime/Intrinsic.h
r214773 r214774 57 57 StringPrototypeReplaceIntrinsic, 58 58 StringPrototypeReplaceRegExpIntrinsic, 59 StringPrototypeToLowerCaseIntrinsic, 60 NumberPrototypeToStringIntrinsic, 59 61 IMulIntrinsic, 60 62 RandomIntrinsic, … … 79 81 AtomicsWakeIntrinsic, 80 82 AtomicsXorIntrinsic, 81 ToLowerCaseIntrinsic,82 83 ParseIntIntrinsic, 83 84 -
releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/runtime/NumberPrototype.cpp
r211247 r214774 59 59 /* Source for NumberPrototype.lut.h 60 60 @begin numberPrototypeTable 61 toString numberProtoFuncToString DontEnum|Function 1 61 toString numberProtoFuncToString DontEnum|Function 1 NumberPrototypeToStringIntrinsic 62 62 toLocaleString numberProtoFuncToLocaleString DontEnum|Function 0 63 63 valueOf numberProtoFuncValueOf DontEnum|Function 0 … … 145 145 static const char radixDigits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; 146 146 147 static char* int52ToStringWithRadix(char* startOfResultString, int64_t int52Value, unsigned radix)147 static inline char* int52ToStringWithRadix(char* startOfResultString, int64_t int52Value, unsigned radix) 148 148 { 149 149 bool negative = false; … … 500 500 } 501 501 502 static inline EncodedJSValue integerValueToString(ExecState* exec, int32_t radix, int32_t value) 503 { 502 static inline JSString* int32ToStringInternal(VM& vm, int32_t value, int32_t radix) 503 { 504 ASSERT(!(radix < 2 || radix > 36)); 504 505 // A negative value casted to unsigned would be bigger than 36 (the max radix). 505 506 if (static_cast<unsigned>(value) < static_cast<unsigned>(radix)) { 506 507 ASSERT(value <= 36); 507 508 ASSERT(value >= 0); 508 VM* vm = &exec->vm(); 509 return JSValue::encode(vm->smallStrings.singleCharacterString(radixDigits[value])); 509 return vm.smallStrings.singleCharacterString(radixDigits[value]); 510 510 } 511 511 512 512 if (radix == 10) { 513 VM* vm = &exec->vm(); 514 return JSValue::encode(jsString(vm, vm->numericStrings.add(value))); 515 } 516 517 return JSValue::encode(jsString(exec, toStringWithRadix(value, radix))); 518 513 return jsString(&vm, vm.numericStrings.add(value)); 514 } 515 516 return jsString(&vm, toStringWithRadix(value, radix)); 517 518 } 519 520 static ALWAYS_INLINE JSString* numberToStringInternal(VM& vm, double doubleValue, int32_t radix) 521 { 522 ASSERT(!(radix < 2 || radix > 36)); 523 524 int32_t integerValue = static_cast<int32_t>(doubleValue); 525 if (integerValue == doubleValue) 526 return int32ToStringInternal(vm, integerValue, radix); 527 528 if (radix == 10) 529 return jsString(&vm, vm.numericStrings.add(doubleValue)); 530 531 if (!std::isfinite(doubleValue)) 532 return jsNontrivialString(&vm, String::numberToStringECMAScript(doubleValue)); 533 534 RadixBuffer buffer; 535 return jsString(&vm, toStringWithRadix(buffer, doubleValue, radix)); 536 } 537 538 JSString* int32ToString(VM& vm, int32_t value, int32_t radix) 539 { 540 return int32ToStringInternal(vm, value, radix); 541 } 542 543 JSString* int52ToString(VM& vm, int64_t value, int32_t radix) 544 { 545 ASSERT(!(radix < 2 || radix > 36)); 546 if (radix == 10) 547 return jsString(&vm, vm.numericStrings.add(static_cast<double>(value))); 548 549 // Position the decimal point at the center of the string, set 550 // the startOfResultString pointer to point at the decimal point. 551 RadixBuffer buffer; 552 char* decimalPoint = buffer + sizeof(buffer) / 2; 553 char* startOfResultString = decimalPoint; 554 *decimalPoint = '\0'; 555 556 return jsString(&vm, int52ToStringWithRadix(startOfResultString, value, radix)); 557 } 558 559 JSString* numberToString(VM& vm, double doubleValue, int32_t radix) 560 { 561 return numberToStringInternal(vm, doubleValue, radix); 519 562 } 520 563 … … 532 575 return throwVMError(exec, scope, createRangeError(exec, ASCIILiteral("toString() radix argument must be between 2 and 36"))); 533 576 534 int32_t integerValue = static_cast<int32_t>(doubleValue); 535 if (integerValue == doubleValue) 536 return integerValueToString(exec, radix, integerValue); 537 538 if (radix == 10) 539 return JSValue::encode(jsString(&vm, vm.numericStrings.add(doubleValue))); 540 541 if (!std::isfinite(doubleValue)) 542 return JSValue::encode(jsNontrivialString(exec, String::numberToStringECMAScript(doubleValue))); 543 544 RadixBuffer s; 545 return JSValue::encode(jsString(exec, toStringWithRadix(s, doubleValue, radix))); 577 return JSValue::encode(numberToStringInternal(vm, doubleValue, radix)); 546 578 } 547 579 -
releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/runtime/NumberPrototype.h
r206525 r214774 52 52 53 53 EncodedJSValue JSC_HOST_CALL numberProtoFuncValueOf(ExecState*); 54 JSString* int32ToString(VM&, int32_t value, int32_t radix); 55 JSString* int52ToString(VM&, int64_t value, int32_t radix); 56 JSString* numberToString(VM&, double value, int32_t radix); 54 57 55 58 } // namespace JSC -
releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/runtime/StringPrototype.cpp
r214773 r214774 143 143 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("substr", stringProtoFuncSubstr, DontEnum, 2); 144 144 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("substring", stringProtoFuncSubstring, DontEnum, 2); 145 JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION("toLowerCase", stringProtoFuncToLowerCase, DontEnum, 0, ToLowerCaseIntrinsic);145 JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION("toLowerCase", stringProtoFuncToLowerCase, DontEnum, 0, StringPrototypeToLowerCaseIntrinsic); 146 146 JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("toUpperCase", stringProtoFuncToUpperCase, DontEnum, 0); 147 147 #if ENABLE(INTL)
Note: See TracChangeset
for help on using the changeset viewer.