Changeset 214219 in webkit
- Timestamp:
- Mar 21, 2017 4:31:43 AM (7 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 25 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r214145 r214219 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-03-19 Chris Dumez <cdumez@apple.com> 2 28 -
trunk/Source/JavaScriptCore/ChangeLog
r214218 r214219 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-03-21 Yusuke Suzuki <utatane.tea@gmail.com> 2 17 … … 27 42 * assembler/MacroAssemblerMIPS.h: 28 43 (JSC::MacroAssemblerMIPS::branchPtr): Added. 44 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): 29 97 30 98 2017-03-20 Filip Pizlo <fpizlo@apple.com> -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r214028 r214219 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: { -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r214029 r214219 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 } -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.h
r214028 r214219 1410 1410 return; 1411 1411 1412 case Int32Use: 1413 case Int52RepUse: 1414 case DoubleRepUse: 1412 1415 case NotCellUse: 1413 1416 def(PureValue(node)); … … 1456 1459 case ToLowerCase: 1457 1460 def(PureValue(node)); 1461 return; 1462 1463 case NumberToStringWithRadix: 1464 read(World); 1465 write(Heap); 1458 1466 return; 1459 1467 -
trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
r213107 r214219 179 179 case ToString: 180 180 case CallStringConstructor: 181 case NumberToStringWithRadix: 181 182 case In: 182 183 case HasOwnProperty: -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r214028 r214219 1759 1759 // are correct. 1760 1760 fixEdge<StringUse>(node->child1()); 1761 break; 1762 } 1763 1764 case NumberToStringWithRadix: { 1765 if (node->child1()->shouldSpeculateInt32()) 1766 fixEdge<Int32Use>(node->child1()); 1767 else if (enableInt52() && node->child1()->shouldSpeculateAnyInt()) 1768 fixEdge<Int52RepUse>(node->child1()); 1769 else 1770 fixEdge<DoubleRepUse>(node->child1()); 1771 fixEdge<Int32Use>(node->child2()); 1761 1772 break; 1762 1773 } … … 2237 2248 } 2238 2249 2250 if (node->child1()->shouldSpeculateInt32()) { 2251 fixEdge<Int32Use>(node->child1()); 2252 node->clearFlags(NodeMustGenerate); 2253 return; 2254 } 2255 2256 if (enableInt52() && node->child1()->shouldSpeculateAnyInt()) { 2257 fixEdge<Int52RepUse>(node->child1()); 2258 node->clearFlags(NodeMustGenerate); 2259 return; 2260 } 2261 2262 if (node->child1()->shouldSpeculateNumber()) { 2263 fixEdge<DoubleRepUse>(node->child1()); 2264 node->clearFlags(NodeMustGenerate); 2265 return; 2266 } 2267 2239 2268 // ToString(Symbol) throws an error. So if the child1 can include Symbols, 2240 2269 // we need to care about it in the clobberize. In the following case, -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r213652 r214219 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) \ -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r214071 r214219 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 { -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r212939 r214219 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); -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r213107 r214219 898 898 case CallStringConstructor: 899 899 case ToString: 900 case NumberToStringWithRadix: 900 901 case MakeRope: 901 902 case StrCat: { -
trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
r213107 r214219 289 289 case ToString: 290 290 case ToNumber: 291 case NumberToStringWithRadix: 291 292 case SetFunctionName: 292 293 case StrCat: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r214071 r214219 7924 7924 } 7925 7925 7926 void SpeculativeJIT::compileToStringOrCallStringConstructorOnCell(Node* node) 7927 { 7928 if (node->child1().useKind() == NotCellUse) { 7926 void SpeculativeJIT::compileToStringOrCallStringConstructor(Node* node) 7927 { 7928 switch (node->child1().useKind()) { 7929 case NotCellUse: { 7929 7930 JSValueOperand op1(this, node->child1(), ManualOperandSpeculation); 7930 7931 JSValueRegs op1Regs = op1.jsValueRegs(); … … 7948 7949 } 7949 7950 7950 if (node->child1().useKind() == UntypedUse){7951 case UntypedUse: { 7951 7952 JSValueOperand op1(this, node->child1()); 7952 7953 JSValueRegs op1Regs = op1.jsValueRegs(); … … 7980 7981 } 7981 7982 7983 case Int32Use: 7984 case Int52RepUse: 7985 case DoubleRepUse: 7986 compileToStringOrCallStringConstructorOnNumber(node); 7987 return; 7988 7989 default: 7990 break; 7991 } 7982 7992 7983 7993 SpeculateCellOperand op1(this, node->child1()); … … 8050 8060 } 8051 8061 8062 default: 8063 RELEASE_ASSERT_NOT_REACHED(); 8064 } 8065 } 8066 8067 void SpeculativeJIT::compileToStringOrCallStringConstructorOnNumber(Node* node) 8068 { 8069 auto callToString = [&] (auto operation, GPRReg resultGPR, auto valueReg) { 8070 flushRegisters(); 8071 callOperation(operation, resultGPR, valueReg, CCallHelpers::TrustedImm32(10)); 8072 m_jit.exceptionCheck(); 8073 cellResult(resultGPR, node); 8074 }; 8075 8076 switch (node->child1().useKind()) { 8077 case Int32Use: { 8078 SpeculateStrictInt32Operand value(this, node->child1()); 8079 GPRFlushedCallResult result(this); 8080 callToString(operationInt32ToStringWithValidRadix, result.gpr(), value.gpr()); 8081 break; 8082 } 8083 8084 #if USE(JSVALUE64) 8085 case Int52RepUse: { 8086 SpeculateStrictInt52Operand value(this, node->child1()); 8087 GPRFlushedCallResult result(this); 8088 callToString(operationInt52ToStringWithValidRadix, result.gpr(), value.gpr()); 8089 break; 8090 } 8091 #endif 8092 8093 case DoubleRepUse: { 8094 SpeculateDoubleOperand value(this, node->child1()); 8095 GPRFlushedCallResult result(this); 8096 callToString(operationDoubleToStringWithValidRadix, result.gpr(), value.fpr()); 8097 break; 8098 } 8099 8100 default: 8101 RELEASE_ASSERT_NOT_REACHED(); 8102 } 8103 } 8104 8105 void SpeculativeJIT::compileNumberToStringWithRadix(Node* node) 8106 { 8107 bool validRadixIsGuaranteed = false; 8108 if (node->child2()->isInt32Constant()) { 8109 int32_t radix = node->child2()->asInt32(); 8110 if (radix >= 2 && radix <= 36) 8111 validRadixIsGuaranteed = true; 8112 } 8113 8114 auto callToString = [&] (auto operation, GPRReg resultGPR, auto valueReg, GPRReg radixGPR) { 8115 flushRegisters(); 8116 callOperation(operation, resultGPR, valueReg, radixGPR); 8117 m_jit.exceptionCheck(); 8118 cellResult(resultGPR, node); 8119 }; 8120 8121 switch (node->child1().useKind()) { 8122 case Int32Use: { 8123 SpeculateStrictInt32Operand value(this, node->child1()); 8124 SpeculateStrictInt32Operand radix(this, node->child2()); 8125 GPRFlushedCallResult result(this); 8126 callToString(validRadixIsGuaranteed ? operationInt32ToStringWithValidRadix : operationInt32ToString, result.gpr(), value.gpr(), radix.gpr()); 8127 break; 8128 } 8129 8130 #if USE(JSVALUE64) 8131 case Int52RepUse: { 8132 SpeculateStrictInt52Operand value(this, node->child1()); 8133 SpeculateStrictInt32Operand radix(this, node->child2()); 8134 GPRFlushedCallResult result(this); 8135 callToString(validRadixIsGuaranteed ? operationInt52ToStringWithValidRadix : operationInt52ToString, result.gpr(), value.gpr(), radix.gpr()); 8136 break; 8137 } 8138 #endif 8139 8140 case DoubleRepUse: { 8141 SpeculateDoubleOperand value(this, node->child1()); 8142 SpeculateStrictInt32Operand radix(this, node->child2()); 8143 GPRFlushedCallResult result(this); 8144 callToString(validRadixIsGuaranteed ? operationDoubleToStringWithValidRadix : operationDoubleToString, result.gpr(), value.fpr(), radix.gpr()); 8145 break; 8146 } 8147 8052 8148 default: 8053 8149 RELEASE_ASSERT_NOT_REACHED(); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r214028 r214219 1382 1382 } 1383 1383 1384 JITCompiler::Call callOperation(P_JITOperation_EZZ operation, GPRReg result, GPRReg arg1, GPRReg arg2) 1385 { 1386 m_jit.setupArgumentsWithExecState(arg1, arg2); 1387 return appendCallSetResult(operation, result); 1388 } 1389 1390 JITCompiler::Call callOperation(P_JITOperation_EZZ operation, GPRReg result, GPRReg arg1, TrustedImm32 arg2) 1391 { 1392 m_jit.setupArgumentsWithExecState(arg1, arg2); 1393 return appendCallSetResult(operation, result); 1394 } 1395 1396 JITCompiler::Call callOperation(P_JITOperation_EDZ operation, GPRReg result, FPRReg arg1, GPRReg arg2) 1397 { 1398 m_jit.setupArgumentsWithExecState(arg1, arg2); 1399 return appendCallSetResult(operation, result); 1400 } 1401 1402 JITCompiler::Call callOperation(P_JITOperation_EDZ operation, GPRReg result, FPRReg arg1, TrustedImm32 arg2) 1403 { 1404 m_jit.setupArgumentsWithExecState(arg1, arg2); 1405 return appendCallSetResult(operation, result); 1406 } 1384 1407 1385 1408 #if USE(JSVALUE64) … … 1611 1634 return appendCallSetResult(operation, result); 1612 1635 } 1636 JITCompiler::Call callOperation(P_JITOperation_EQZ operation, GPRReg result, GPRReg arg1, GPRReg arg2) 1637 { 1638 m_jit.setupArgumentsWithExecState(arg1, arg2); 1639 return appendCallSetResult(operation, result); 1640 } 1641 JITCompiler::Call callOperation(P_JITOperation_EQZ operation, GPRReg result, GPRReg arg1, TrustedImm32 arg2) 1642 { 1643 m_jit.setupArgumentsWithExecState(arg1, arg2); 1644 return appendCallSetResult(operation, result); 1645 } 1646 1613 1647 JITCompiler::Call callOperation(J_JITOperation_EZIcfZ operation, GPRReg result, int32_t arg1, InlineCallFrame* inlineCallFrame, GPRReg arg2) 1614 1648 { … … 2682 2716 void emitSwitch(Node*); 2683 2717 2684 void compileToStringOrCallStringConstructorOnCell(Node*); 2718 void compileToStringOrCallStringConstructor(Node*); 2719 void compileToStringOrCallStringConstructorOnNumber(Node*); 2720 void compileNumberToStringWithRadix(Node*); 2685 2721 void compileNewStringObject(Node*); 2686 2722 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r214028 r214219 2836 2836 } 2837 2837 2838 case NumberToStringWithRadix: { 2839 compileNumberToStringWithRadix(node); 2840 break; 2841 } 2842 2838 2843 case GetByValWithThis: { 2839 2844 JSValueOperand base(this, node->child1()); … … 3770 3775 case ToString: 3771 3776 case CallStringConstructor: { 3772 compileToStringOrCallStringConstructor OnCell(node);3777 compileToStringOrCallStringConstructor(node); 3773 3778 break; 3774 3779 } -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r214028 r214219 3740 3740 case ToString: 3741 3741 case CallStringConstructor: { 3742 compileToStringOrCallStringConstructor OnCell(node);3742 compileToStringOrCallStringConstructor(node); 3743 3743 break; 3744 3744 } … … 5058 5058 } 5059 5059 5060 case NumberToStringWithRadix: { 5061 compileNumberToStringWithRadix(node); 5062 break; 5063 } 5064 5060 5065 case IsObject: { 5061 5066 JSValueOperand value(this, node->child1()); -
trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp
r211247 r214219 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 -
trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
r214069 r214219 280 280 case DefineAccessorProperty: 281 281 case ToLowerCase: 282 case NumberToStringWithRadix: 282 283 case CheckDOM: 283 284 case CallDOM: -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
r214071 r214219 1079 1079 compileToLowerCase(); 1080 1080 break; 1081 case NumberToStringWithRadix: 1082 compileNumberToStringWithRadix(); 1083 break; 1081 1084 case CheckDOM: 1082 1085 compileCheckDOM(); … … 4982 4985 return; 4983 4986 } 4987 4988 case Int32Use: 4989 setJSValue(vmCall(Int64, m_out.operation(operationInt32ToStringWithValidRadix), m_callFrame, lowInt32(m_node->child1()), m_out.constInt32(10))); 4990 return; 4991 4992 case Int52RepUse: 4993 setJSValue(vmCall(Int64, m_out.operation(operationInt52ToStringWithValidRadix), m_callFrame, lowStrictInt52(m_node->child1()), m_out.constInt32(10))); 4994 return; 4995 4996 case DoubleRepUse: 4997 setJSValue(vmCall(Int64, m_out.operation(operationDoubleToStringWithValidRadix), m_callFrame, lowDouble(m_node->child1()), m_out.constInt32(10))); 4998 return; 4984 4999 4985 5000 default: … … 9983 9998 m_out.appendTo(continuation, lastNext); 9984 9999 setJSValue(m_out.phi(pointerType(), fastResult, slowResult)); 10000 } 10001 10002 void compileNumberToStringWithRadix() 10003 { 10004 bool validRadixIsGuaranteed = false; 10005 if (m_node->child2()->isInt32Constant()) { 10006 int32_t radix = m_node->child2()->asInt32(); 10007 if (radix >= 2 && radix <= 36) 10008 validRadixIsGuaranteed = true; 10009 } 10010 10011 switch (m_node->child1().useKind()) { 10012 case Int32Use: 10013 setJSValue(vmCall(pointerType(), m_out.operation(validRadixIsGuaranteed ? operationInt32ToStringWithValidRadix : operationInt32ToString), m_callFrame, lowInt32(m_node->child1()), lowInt32(m_node->child2()))); 10014 break; 10015 case Int52RepUse: 10016 setJSValue(vmCall(pointerType(), m_out.operation(validRadixIsGuaranteed ? operationInt52ToStringWithValidRadix : operationInt52ToString), m_callFrame, lowStrictInt52(m_node->child1()), lowInt32(m_node->child2()))); 10017 break; 10018 case DoubleRepUse: 10019 setJSValue(vmCall(pointerType(), m_out.operation(validRadixIsGuaranteed ? operationDoubleToStringWithValidRadix : operationDoubleToString), m_callFrame, lowDouble(m_node->child1()), lowInt32(m_node->child2()))); 10020 break; 10021 default: 10022 RELEASE_ASSERT_NOT_REACHED(); 10023 } 9985 10024 } 9986 10025 -
trunk/Source/JavaScriptCore/jit/CCallHelpers.h
r213467 r214219 886 886 887 887 ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, GPRReg arg2) 888 { 889 resetCallArguments(); 890 addCallArgument(GPRInfo::callFrameRegister); 891 addCallArgument(arg1); 892 addCallArgument(arg2); 893 } 894 895 ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, TrustedImm32 arg2) 888 896 { 889 897 resetCallArguments(); … … 1094 1102 } 1095 1103 1104 ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, TrustedImm32 arg2) 1105 { 1106 #if OS(WINDOWS) && CPU(X86_64) 1107 // On Windows, arguments map to designated registers based on the argument positions, even when there are interlaced scalar and floating point arguments. 1108 // See http://msdn.microsoft.com/en-us/library/zthk2dkh.aspx 1109 moveDouble(arg1, FPRInfo::argumentFPR1); 1110 move(arg2, GPRInfo::argumentGPR2); 1111 #else 1112 moveDouble(arg1, FPRInfo::argumentFPR0); 1113 move(arg2, GPRInfo::argumentGPR1); 1114 #endif 1115 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); 1116 } 1117 1096 1118 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, FPRReg arg3) 1097 1119 { … … 1136 1158 } 1137 1159 1160 ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, TrustedImm32 arg2) 1161 { 1162 moveDouble(arg1, FPRInfo::argumentFPR0); 1163 move(arg2, GPRInfo::argumentGPR1); 1164 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); 1165 } 1166 1138 1167 ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, FPRReg arg3) 1139 1168 { … … 1170 1199 1171 1200 ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, GPRReg arg2) 1201 { 1202 move(arg2, GPRInfo::argumentGPR3); 1203 assembler().vmov(GPRInfo::argumentGPR1, GPRInfo::argumentGPR2, arg1); 1204 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); 1205 } 1206 1207 ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, TrustedImm32 arg2) 1172 1208 { 1173 1209 move(arg2, GPRInfo::argumentGPR3); … … 1223 1259 1224 1260 ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, GPRReg arg2) 1261 { 1262 assembler().vmov(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3, arg1); 1263 move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); 1264 poke(arg2, 4); 1265 } 1266 1267 ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, TrustedImm32 arg2) 1225 1268 { 1226 1269 assembler().vmov(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3, arg1); -
trunk/Source/JavaScriptCore/jit/JITOperations.h
r213467 r214219 313 313 typedef char* (JIT_OPERATION *P_JITOperation_EStZP)(ExecState*, Structure*, int32_t, char*); 314 314 typedef char* (JIT_OPERATION *P_JITOperation_EZZ)(ExecState*, int32_t, int32_t); 315 typedef char* (JIT_OPERATION *P_JITOperation_EQZ)(ExecState*, int64_t, int32_t); 316 typedef char* (JIT_OPERATION *P_JITOperation_EDZ)(ExecState*, double, int32_t); 315 317 typedef SlowPathReturnType (JIT_OPERATION *Sprt_JITOperation_ECli)(ExecState*, CallLinkInfo*); 316 318 typedef StringImpl* (JIT_OPERATION *T_JITOperation_EJss)(ExecState*, JSString*); -
trunk/Source/JavaScriptCore/runtime/Intrinsic.h
r212939 r214219 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 -
trunk/Source/JavaScriptCore/runtime/NumberPrototype.cpp
r211247 r214219 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 -
trunk/Source/JavaScriptCore/runtime/NumberPrototype.h
r206525 r214219 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 -
trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp
r212939 r214219 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.