Changeset 214774 in webkit


Ignore:
Timestamp:
Apr 3, 2017 5:33:21 AM (7 years ago)
Author:
Carlos Garcia Campos
Message:

Merge r214219 - [JSC] Optimize Number.prototype.toString on Int32 / Int52 / Double
https://bugs.webkit.org/show_bug.cgi?id=167454

Reviewed by Saam Barati.

JSTests:

  • stress/number-to-string-abstract-operation.js: Added.

(shouldBe):
(int32ToString):
(shouldBe.int32ToString.new.Number.int52ToString):
(shouldBe.int32ToString.new.Number):
(shouldBe.doubleToString):

  • stress/number-to-string-radix.js: Added.

(shouldBe):
(int32ToString):
(shouldBe.int32ToString.new.Number.int52ToString):
(shouldBe.int32ToString.new.Number):
(shouldBe.doubleToString):

  • stress/number-to-string.js: Added.

(shouldBe):
(int32ToString):
(shouldBe.int32ToString.new.Number.int52ToString):
(shouldBe.int32ToString.new.Number):
(shouldBe.doubleToString):

Source/JavaScriptCore:

This patch improves Number.toString(radix) performance
by introducing NumberToStringWithRadix DFG node. It directly
calls the operation and it always returns String.

baseline patched

stanford-crypto-sha256-iterative 45.130+-0.928 44.032+-1.184 might be 1.0250x faster

Location:
releases/WebKitGTK/webkit-2.16
Files:
3 added
25 edited

Legend:

Unmodified
Added
Removed
  • releases/WebKitGTK/webkit-2.16/JSTests/ChangeLog

    r214773 r214774  
     12017-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
    1272017-02-23  Saam Barati  <sbarati@apple.com>
    228
  • releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/ChangeLog

    r214773 r214774  
     12017-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
    1162017-02-24  Saam Barati  <sbarati@apple.com>
    217
     
    2843        case. We also set up CSE rules for parseInt(someString, someIntRadix)
    2944        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
    3098
    3199        This looks to be a 4% Octane/Box2D progression.
  • releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r214773 r214774  
    18591859            break;
    18601860        case StringOrStringObjectUse:
     1861        case Int32Use:
     1862        case Int52RepUse:
     1863        case DoubleRepUse:
    18611864        case NotCellUse:
    18621865            break;
     
    18721875        break;
    18731876    }
     1877
     1878    case NumberToStringWithRadix:
     1879        clobberWorld(node->origin.semantic, clobberLimit);
     1880        forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
     1881        break;
    18741882       
    18751883    case NewStringObject: {
  • releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r214773 r214774  
    27122712    }
    27132713
    2714     case ToLowerCaseIntrinsic: {
     2714    case StringPrototypeToLowerCaseIntrinsic: {
    27152715        if (argumentCountIncludingThis != 1)
    27162716            return false;
     
    27232723        Node* result = addToGraph(ToLowerCase, thisString);
    27242724        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        }
    27252745        return true;
    27262746    }
  • releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/dfg/DFGClobberize.h

    r214773 r214774  
    14021402            return;
    14031403
     1404        case Int32Use:
     1405        case Int52RepUse:
     1406        case DoubleRepUse:
    14041407        case NotCellUse:
    14051408            def(PureValue(node));
     
    14491452    case ToLowerCase:
    14501453        def(PureValue(node));
     1454        return;
     1455
     1456    case NumberToStringWithRadix:
     1457        read(World);
     1458        write(Heap);
    14511459        return;
    14521460       
  • releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/dfg/DFGDoesGC.cpp

    r214773 r214774  
    179179    case ToString:
    180180    case CallStringConstructor:
     181    case NumberToStringWithRadix:
    181182    case In:
    182183    case HasOwnProperty:
  • releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r214773 r214774  
    17511751            // are correct.
    17521752            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());
    17531764            break;
    17541765        }
     
    22302241        }
    22312242
     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
    22322261        // ToString(Symbol) throws an error. So if the child1 can include Symbols,
    22332262        // 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  
    336336    macro(CallObjectConstructor, NodeResultJS) \
    337337    macro(CallStringConstructor, NodeResultJS | NodeMustGenerate) \
     338    macro(NumberToStringWithRadix, NodeResultJS | NodeMustGenerate) \
    338339    macro(NewStringObject, NodeResultJS) \
    339340    macro(MakeRope, NodeResultJS) \
  • releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r214773 r214774  
    16451645}
    16461646
     1647char* 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
     1662char* 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
     1677char* 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
     1692char* 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
     1700char* 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
     1708char* 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
    16471716JSString* JIT_OPERATION operationSingleCharacterString(ExecState* exec, int32_t character)
    16481717{
  • releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/dfg/DFGOperations.h

    r214773 r214774  
    160160JSString* JIT_OPERATION operationToLowerCase(ExecState*, JSString*, uint32_t);
    161161
     162char* JIT_OPERATION operationInt32ToString(ExecState*, int32_t, int32_t);
     163char* JIT_OPERATION operationInt52ToString(ExecState*, int64_t, int32_t);
     164char* JIT_OPERATION operationDoubleToString(ExecState*, double, int32_t);
     165char* JIT_OPERATION operationInt32ToStringWithValidRadix(ExecState*, int32_t, int32_t);
     166char* JIT_OPERATION operationInt52ToStringWithValidRadix(ExecState*, int64_t, int32_t);
     167char* JIT_OPERATION operationDoubleToStringWithValidRadix(ExecState*, double, int32_t);
     168
    162169int32_t JIT_OPERATION operationMapHash(ExecState*, EncodedJSValue input);
    163170JSCell* JIT_OPERATION operationJSMapFindBucket(ExecState*, JSCell*, EncodedJSValue, int32_t);
  • releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r214773 r214774  
    898898        case CallStringConstructor:
    899899        case ToString:
     900        case NumberToStringWithRadix:
    900901        case MakeRope:
    901902        case StrCat: {
  • releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/dfg/DFGSafeToExecute.h

    r214773 r214774  
    289289    case ToString:
    290290    case ToNumber:
     291    case NumberToStringWithRadix:
    291292    case SetFunctionName:
    292293    case StrCat:
  • releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r214773 r214774  
    79107910}
    79117911
    7912 void SpeculativeJIT::compileToStringOrCallStringConstructorOnCell(Node* node)
    7913 {
    7914     if (node->child1().useKind() == NotCellUse) {
     7912void SpeculativeJIT::compileToStringOrCallStringConstructor(Node* node)
     7913{
     7914    switch (node->child1().useKind()) {
     7915    case NotCellUse: {
    79157916        JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
    79167917        JSValueRegs op1Regs = op1.jsValueRegs();
     
    79347935    }
    79357936
    7936     if (node->child1().useKind() == UntypedUse) {
     7937    case UntypedUse: {
    79377938        JSValueOperand op1(this, node->child1());
    79387939        JSValueRegs op1Regs = op1.jsValueRegs();
     
    79667967    }
    79677968
     7969    case Int32Use:
     7970    case Int52RepUse:
     7971    case DoubleRepUse:
     7972        compileToStringOrCallStringConstructorOnNumber(node);
     7973        return;
     7974
     7975    default:
     7976        break;
     7977    }
    79687978
    79697979    SpeculateCellOperand op1(this, node->child1());
     
    80368046    }
    80378047       
     8048    default:
     8049        RELEASE_ASSERT_NOT_REACHED();
     8050    }
     8051}
     8052
     8053void 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
     8091void 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
    80388134    default:
    80398135        RELEASE_ASSERT_NOT_REACHED();
  • releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r214773 r214774  
    13781378    }
    13791379
     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    }
    13801403
    13811404#if USE(JSVALUE64)
     
    16021625        return appendCallSetResult(operation, result);
    16031626    }
     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
    16041638    JITCompiler::Call callOperation(J_JITOperation_EZIcfZ operation, GPRReg result, int32_t arg1, InlineCallFrame* inlineCallFrame, GPRReg arg2)
    16051639    {
     
    26582692    void emitSwitch(Node*);
    26592693   
    2660     void compileToStringOrCallStringConstructorOnCell(Node*);
     2694    void compileToStringOrCallStringConstructor(Node*);
     2695    void compileToStringOrCallStringConstructorOnNumber(Node*);
     2696    void compileNumberToStringWithRadix(Node*);
    26612697    void compileNewStringObject(Node*);
    26622698   
  • releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r214773 r214774  
    27972797    }
    27982798
     2799    case NumberToStringWithRadix: {
     2800        compileNumberToStringWithRadix(node);
     2801        break;
     2802    }
     2803
    27992804    case GetByValWithThis: {
    28002805        JSValueOperand base(this, node->child1());
     
    37313736    case ToString:
    37323737    case CallStringConstructor: {
    3733         compileToStringOrCallStringConstructorOnCell(node);
     3738        compileToStringOrCallStringConstructor(node);
    37343739        break;
    37353740    }
  • releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r214773 r214774  
    37123712    case ToString:
    37133713    case CallStringConstructor: {
    3714         compileToStringOrCallStringConstructorOnCell(node);
     3714        compileToStringOrCallStringConstructor(node);
    37153715        break;
    37163716    }
     
    50085008    }
    50095009
     5010    case NumberToStringWithRadix: {
     5011        compileNumberToStringWithRadix(node);
     5012        break;
     5013    }
     5014
    50105015    case IsObject: {
    50115016        JSValueOperand value(this, node->child1());
  • releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp

    r211247 r214774  
    391391        }
    392392
     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
    393424        case GetArrayLength: {
    394425            if (m_node->arrayMode().type() == Array::Generic
  • releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/ftl/FTLCapabilities.cpp

    r214773 r214774  
    280280    case DefineAccessorProperty:
    281281    case ToLowerCase:
     282    case NumberToStringWithRadix:
    282283    case CheckDOM:
    283284    case CallDOM:
  • releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r214773 r214774  
    10771077            compileToLowerCase();
    10781078            break;
     1079        case NumberToStringWithRadix:
     1080            compileNumberToStringWithRadix();
     1081            break;
    10791082        case CheckDOM:
    10801083            compileCheckDOM();
     
    49504953            return;
    49514954        }
     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;
    49524967           
    49534968        default:
     
    98819896        m_out.appendTo(continuation, lastNext);
    98829897        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        }
    98839922    }
    98849923
  • releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/jit/CCallHelpers.h

    r210232 r214774  
    862862
    863863    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)
    864872    {
    865873        resetCallArguments();
     
    10701078    }
    10711079
     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
    10721094    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, FPRReg arg3)
    10731095    {
     
    11121134    }
    11131135
     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
    11141143    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, FPRReg arg3)
    11151144    {
     
    11461175
    11471176    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)
    11481184    {
    11491185        move(arg2, GPRInfo::argumentGPR3);
     
    11991235
    12001236    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)
    12011244    {
    12021245        assembler().vmov(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3, arg1);
  • releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/jit/JITOperations.h

    r214773 r214774  
    312312typedef char* (JIT_OPERATION *P_JITOperation_EStZP)(ExecState*, Structure*, int32_t, char*);
    313313typedef char* (JIT_OPERATION *P_JITOperation_EZZ)(ExecState*, int32_t, int32_t);
     314typedef char* (JIT_OPERATION *P_JITOperation_EQZ)(ExecState*, int64_t, int32_t);
     315typedef char* (JIT_OPERATION *P_JITOperation_EDZ)(ExecState*, double, int32_t);
    314316typedef SlowPathReturnType (JIT_OPERATION *Sprt_JITOperation_ECli)(ExecState*, CallLinkInfo*);
    315317typedef StringImpl* (JIT_OPERATION *T_JITOperation_EJss)(ExecState*, JSString*);
  • releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/runtime/Intrinsic.h

    r214773 r214774  
    5757    StringPrototypeReplaceIntrinsic,
    5858    StringPrototypeReplaceRegExpIntrinsic,
     59    StringPrototypeToLowerCaseIntrinsic,
     60    NumberPrototypeToStringIntrinsic,
    5961    IMulIntrinsic,
    6062    RandomIntrinsic,
     
    7981    AtomicsWakeIntrinsic,
    8082    AtomicsXorIntrinsic,
    81     ToLowerCaseIntrinsic,
    8283    ParseIntIntrinsic,
    8384
  • releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/runtime/NumberPrototype.cpp

    r211247 r214774  
    5959/* Source for NumberPrototype.lut.h
    6060@begin numberPrototypeTable
    61   toString          numberProtoFuncToString         DontEnum|Function 1
     61  toString          numberProtoFuncToString         DontEnum|Function 1 NumberPrototypeToStringIntrinsic
    6262  toLocaleString    numberProtoFuncToLocaleString   DontEnum|Function 0
    6363  valueOf           numberProtoFuncValueOf          DontEnum|Function 0
     
    145145static const char radixDigits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
    146146
    147 static char* int52ToStringWithRadix(char* startOfResultString, int64_t int52Value, unsigned radix)
     147static inline char* int52ToStringWithRadix(char* startOfResultString, int64_t int52Value, unsigned radix)
    148148{
    149149    bool negative = false;
     
    500500}
    501501
    502 static inline EncodedJSValue integerValueToString(ExecState* exec, int32_t radix, int32_t value)
    503 {
     502static inline JSString* int32ToStringInternal(VM& vm, int32_t value, int32_t radix)
     503{
     504    ASSERT(!(radix < 2 || radix > 36));
    504505    // A negative value casted to unsigned would be bigger than 36 (the max radix).
    505506    if (static_cast<unsigned>(value) < static_cast<unsigned>(radix)) {
    506507        ASSERT(value <= 36);
    507508        ASSERT(value >= 0);
    508         VM* vm = &exec->vm();
    509         return JSValue::encode(vm->smallStrings.singleCharacterString(radixDigits[value]));
     509        return vm.smallStrings.singleCharacterString(radixDigits[value]);
    510510    }
    511511
    512512    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
     520static 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
     538JSString* int32ToString(VM& vm, int32_t value, int32_t radix)
     539{
     540    return int32ToStringInternal(vm, value, radix);
     541}
     542
     543JSString* 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
     559JSString* numberToString(VM& vm, double doubleValue, int32_t radix)
     560{
     561    return numberToStringInternal(vm, doubleValue, radix);
    519562}
    520563
     
    532575        return throwVMError(exec, scope, createRangeError(exec, ASCIILiteral("toString() radix argument must be between 2 and 36")));
    533576
    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));
    546578}
    547579
  • releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/runtime/NumberPrototype.h

    r206525 r214774  
    5252
    5353EncodedJSValue JSC_HOST_CALL numberProtoFuncValueOf(ExecState*);
     54JSString* int32ToString(VM&, int32_t value, int32_t radix);
     55JSString* int52ToString(VM&, int64_t value, int32_t radix);
     56JSString* numberToString(VM&, double value, int32_t radix);
    5457
    5558} // namespace JSC
  • releases/WebKitGTK/webkit-2.16/Source/JavaScriptCore/runtime/StringPrototype.cpp

    r214773 r214774  
    143143    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("substr", stringProtoFuncSubstr, DontEnum, 2);
    144144    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);
    146146    JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("toUpperCase", stringProtoFuncToUpperCase, DontEnum, 0);
    147147#if ENABLE(INTL)
Note: See TracChangeset for help on using the changeset viewer.