Title: [214774] releases/WebKitGTK/webkit-2.16
Revision
214774
Author
carlo...@webkit.org
Date
2017-04-03 05:33:21 -0700 (Mon, 03 Apr 2017)

Log 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/_javascript_Core:

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

Modified Paths

Added Paths

Diff

Modified: releases/WebKitGTK/webkit-2.16/JSTests/ChangeLog (214773 => 214774)


--- releases/WebKitGTK/webkit-2.16/JSTests/ChangeLog	2017-04-03 12:32:51 UTC (rev 214773)
+++ releases/WebKitGTK/webkit-2.16/JSTests/ChangeLog	2017-04-03 12:33:21 UTC (rev 214774)
@@ -1,3 +1,29 @@
+2017-03-21  Yusuke Suzuki  <utatane....@gmail.com>
+
+        [JSC] Optimize Number.prototype.toString on Int32 / Int52 / Double
+        https://bugs.webkit.org/show_bug.cgi?id=167454
+
+        Reviewed by Saam Barati.
+
+        * 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):
+
 2017-02-23  Saam Barati  <sbar...@apple.com>
 
         Intrinsicify parseInt

Added: releases/WebKitGTK/webkit-2.16/JSTests/stress/number-to-string-abstract-operation.js (0 => 214774)


--- releases/WebKitGTK/webkit-2.16/JSTests/stress/number-to-string-abstract-operation.js	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.16/JSTests/stress/number-to-string-abstract-operation.js	2017-04-03 12:33:21 UTC (rev 214774)
@@ -0,0 +1,80 @@
+function shouldBe(actual, expected)
+{
+    if (actual !== expected)
+        throw new Error(`bad value: expected:(${expected}),actual:(${actual})`);
+}
+
+function expected(num, radix)
+{
+    let characters = "0123456789abcdefghijklmnopqrstuvwxyz";
+    let result = "";
+    let negative = false;
+    if (num < 0) {
+        negative = true;
+        num = -num;
+    }
+
+    do {
+        const index = num % radix;
+        result = characters[index] + result;
+        num = (num - index) / radix;
+    } while (num);
+
+    if (negative)
+        return '-' + result;
+    return result;
+}
+
+{
+    function int32ToString(num)
+    {
+        return `${num}`;
+    }
+    noInline(int32ToString);
+
+    for (var i = 0; i < 1e3; ++i) {
+        shouldBe(int32ToString(i), expected(i, 10));
+        shouldBe(int32ToString(-i), expected(-i, 10));
+    }
+
+    shouldBe(int32ToString(0xffffffffff), expected(0xffffffffff, 10));
+    shouldBe(int32ToString(0.1), `0.1`);
+    shouldBe(int32ToString(-0.1), `-0.1`);
+    shouldBe(int32ToString(new Number(0xff)), `255`);
+}
+
+{
+    function int52ToString(num)
+    {
+        return `${fiatInt52(num)}`;
+    }
+    noInline(int52ToString);
+
+    for (var i = 0; i < 1e3; ++i) {
+        shouldBe(int52ToString(0xffffffff + i), expected(0xffffffff + i, 10));
+        shouldBe(int52ToString(-(0xffffffff + i)), expected(-(0xffffffff + i), 10));
+    }
+
+    shouldBe(int52ToString(0xff), `255`);
+    shouldBe(int52ToString(0.1), `0.1`);
+    shouldBe(int52ToString(-0.1), `-0.1`);
+    shouldBe(int52ToString(new Number(0xff)), `255`);
+}
+
+{
+    function doubleToString(num)
+    {
+        return `${num}`;
+    }
+    noInline(doubleToString);
+
+    for (var i = 0; i < 1e3; ++i) {
+        shouldBe(doubleToString(1.01), `1.01`);
+        shouldBe(doubleToString(-1.01), `-1.01`);
+    }
+
+    shouldBe(doubleToString(0xff), `255`);
+    shouldBe(doubleToString(0.1), `0.1`);
+    shouldBe(doubleToString(-0.1), `-0.1`);
+    shouldBe(doubleToString(new Number(0xff)), `255`);
+}

Added: releases/WebKitGTK/webkit-2.16/JSTests/stress/number-to-string-radix.js (0 => 214774)


--- releases/WebKitGTK/webkit-2.16/JSTests/stress/number-to-string-radix.js	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.16/JSTests/stress/number-to-string-radix.js	2017-04-03 12:33:21 UTC (rev 214774)
@@ -0,0 +1,80 @@
+function shouldBe(actual, expected)
+{
+    if (actual !== expected)
+        throw new Error(`bad value: expected:(${expected}),actual:(${actual})`);
+}
+
+function expected(num, radix)
+{
+    let characters = "0123456789abcdefghijklmnopqrstuvwxyz";
+    let result = "";
+    let negative = false;
+    if (num < 0) {
+        negative = true;
+        num = -num;
+    }
+
+    do {
+        const index = num % radix;
+        result = characters[index] + result;
+        num = (num - index) / radix;
+    } while (num);
+
+    if (negative)
+        return '-' + result;
+    return result;
+}
+
+{
+    function int32ToString(num, radix)
+    {
+        return num.toString(radix);
+    }
+    noInline(int32ToString);
+
+    for (var i = 0; i < 1e3; ++i) {
+        shouldBe(int32ToString(i, 16), expected(i, 16));
+        shouldBe(int32ToString(-i, 16), expected(-i, 16));
+    }
+
+    shouldBe(int32ToString(0xffffffffff, 16), expected(0xffffffffff, 16));
+    shouldBe(int32ToString(0.1, 16), `0.1999999999999a`);
+    shouldBe(int32ToString(-0.1, 16), `-0.1999999999999a`);
+    shouldBe(int32ToString(new Number(0xff), 16), `ff`);
+}
+
+{
+    function int52ToString(num, radix)
+    {
+        return fiatInt52(num).toString(radix);
+    }
+    noInline(int52ToString);
+
+    for (var i = 0; i < 1e3; ++i) {
+        shouldBe(int52ToString(0xffffffff + i, 16), expected(0xffffffff + i, 16));
+        shouldBe(int52ToString(-(0xffffffff + i), 16), expected(-(0xffffffff + i), 16));
+    }
+
+    shouldBe(int52ToString(0xff, 16), `ff`);
+    shouldBe(int52ToString(0.1, 16), `0.1999999999999a`);
+    shouldBe(int52ToString(-0.1, 16), `-0.1999999999999a`);
+    shouldBe(int52ToString(new Number(0xff), 16), `ff`);
+}
+
+{
+    function doubleToString(num, radix)
+    {
+        return num.toString(radix);
+    }
+    noInline(doubleToString);
+
+    for (var i = 0; i < 1e3; ++i) {
+        shouldBe(doubleToString(1.01, 16), `1.028f5c28f5c29`);
+        shouldBe(doubleToString(-1.01, 16), `-1.028f5c28f5c29`);
+    }
+
+    shouldBe(doubleToString(0xff, 16), `ff`);
+    shouldBe(doubleToString(0.1, 16), `0.1999999999999a`);
+    shouldBe(doubleToString(-0.1, 16), `-0.1999999999999a`);
+    shouldBe(doubleToString(new Number(0xff), 16), `ff`);
+}

Added: releases/WebKitGTK/webkit-2.16/JSTests/stress/number-to-string.js (0 => 214774)


--- releases/WebKitGTK/webkit-2.16/JSTests/stress/number-to-string.js	                        (rev 0)
+++ releases/WebKitGTK/webkit-2.16/JSTests/stress/number-to-string.js	2017-04-03 12:33:21 UTC (rev 214774)
@@ -0,0 +1,80 @@
+function shouldBe(actual, expected)
+{
+    if (actual !== expected)
+        throw new Error(`bad value: expected:(${expected}),actual:(${actual})`);
+}
+
+function expected(num, radix)
+{
+    let characters = "0123456789abcdefghijklmnopqrstuvwxyz";
+    let result = "";
+    let negative = false;
+    if (num < 0) {
+        negative = true;
+        num = -num;
+    }
+
+    do {
+        const index = num % radix;
+        result = characters[index] + result;
+        num = (num - index) / radix;
+    } while (num);
+
+    if (negative)
+        return '-' + result;
+    return result;
+}
+
+{
+    function int32ToString(num)
+    {
+        return num.toString(16);
+    }
+    noInline(int32ToString);
+
+    for (var i = 0; i < 1e3; ++i) {
+        shouldBe(int32ToString(i), expected(i, 16));
+        shouldBe(int32ToString(-i), expected(-i, 16));
+    }
+
+    shouldBe(int32ToString(0xffffffffff), expected(0xffffffffff, 16));
+    shouldBe(int32ToString(0.1), `0.1999999999999a`);
+    shouldBe(int32ToString(-0.1), `-0.1999999999999a`);
+    shouldBe(int32ToString(new Number(0xff)), `ff`);
+}
+
+{
+    function int52ToString(num)
+    {
+        return fiatInt52(num).toString(16);
+    }
+    noInline(int52ToString);
+
+    for (var i = 0; i < 1e3; ++i) {
+        shouldBe(int52ToString(0xffffffff + i), expected(0xffffffff + i, 16));
+        shouldBe(int52ToString(-(0xffffffff + i)), expected(-(0xffffffff + i), 16));
+    }
+
+    shouldBe(int52ToString(0xff), `ff`);
+    shouldBe(int52ToString(0.1), `0.1999999999999a`);
+    shouldBe(int52ToString(-0.1), `-0.1999999999999a`);
+    shouldBe(int52ToString(new Number(0xff)), `ff`);
+}
+
+{
+    function doubleToString(num)
+    {
+        return num.toString(16);
+    }
+    noInline(doubleToString);
+
+    for (var i = 0; i < 1e3; ++i) {
+        shouldBe(doubleToString(1.01), `1.028f5c28f5c29`);
+        shouldBe(doubleToString(-1.01), `-1.028f5c28f5c29`);
+    }
+
+    shouldBe(doubleToString(0xff), `ff`);
+    shouldBe(doubleToString(0.1), `0.1999999999999a`);
+    shouldBe(doubleToString(-0.1), `-0.1999999999999a`);
+    shouldBe(doubleToString(new Number(0xff)), `ff`);
+}

Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/ChangeLog (214773 => 214774)


--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/ChangeLog	2017-04-03 12:32:51 UTC (rev 214773)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/ChangeLog	2017-04-03 12:33:21 UTC (rev 214774)
@@ -1,3 +1,18 @@
+2017-03-21  Yusuke Suzuki  <utatane....@gmail.com>
+
+        [JSC] Optimize Number.prototype.toString on Int32 / Int52 / Double
+        https://bugs.webkit.org/show_bug.cgi?id=167454
+
+        Reviewed by Saam Barati.
+
+        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
+
 2017-02-24  Saam Barati  <sbar...@apple.com>
 
         Unreviewed. Remove inaccurate copy-paste comment from r212939.
@@ -27,7 +42,60 @@
         is a proven string. The DFG might be able to remove type checks in this
         case. We also set up CSE rules for parseInt(someString, someIntRadix)
         because it's a "pure" operation (modulo resolving a rope).
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::handleIntrinsicCall):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGDoesGC.cpp:
+        (JSC::DFG::doesGC):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        (JSC::DFG::FixupPhase::fixupToStringOrCallStringConstructor):
+        * dfg/DFGNodeType.h:
+        * dfg/DFGOperations.cpp:
+        * dfg/DFGOperations.h:
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileToStringOrCallStringConstructor):
+        (JSC::DFG::SpeculativeJIT::compileToStringOrCallStringConstructorOnNumber):
+        (JSC::DFG::SpeculativeJIT::compileNumberToStringWithRadix):
+        (JSC::DFG::SpeculativeJIT::compileToStringOrCallStringConstructorOnCell): Deleted.
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::callOperation):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGStrengthReductionPhase.cpp:
+        (JSC::DFG::StrengthReductionPhase::handleNode):
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+        (JSC::FTL::DFG::LowerDFGToB3::compileToStringOrCallStringConstructor):
+        (JSC::FTL::DFG::LowerDFGToB3::compileNumberToStringWithRadix):
+        * jit/CCallHelpers.h:
+        (JSC::CCallHelpers::setupArgumentsWithExecState):
+        * jit/JITOperations.h:
+        * runtime/Intrinsic.h:
+        * runtime/NumberPrototype.cpp:
+        (JSC::int52ToStringWithRadix):
+        (JSC::int32ToStringInternal):
+        (JSC::numberToStringInternal):
+        (JSC::int32ToString):
+        (JSC::int52ToString):
+        (JSC::numberToString):
+        (JSC::numberProtoFuncToString):
+        (JSC::integerValueToString): Deleted.
+        * runtime/NumberPrototype.h:
+        * runtime/StringPrototype.cpp:
+        (JSC::StringPrototype::finishCreation):
 
+
         This looks to be a 4% Octane/Box2D progression.
 
         * dfg/DFGAbstractInterpreterInlines.h:

Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (214773 => 214774)


--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2017-04-03 12:32:51 UTC (rev 214773)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2017-04-03 12:33:21 UTC (rev 214774)
@@ -1858,6 +1858,9 @@
                 m_graph.registerStructure(m_graph.globalObjectFor(node->origin.semantic)->stringObjectStructure()));
             break;
         case StringOrStringObjectUse:
+        case Int32Use:
+        case Int52RepUse:
+        case DoubleRepUse:
         case NotCellUse:
             break;
         case CellUse:
@@ -1871,6 +1874,11 @@
         forNode(node).set(m_graph, m_vm.stringStructure.get());
         break;
     }
+
+    case NumberToStringWithRadix:
+        clobberWorld(node->origin.semantic, clobberLimit);
+        forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
+        break;
         
     case NewStringObject: {
         ASSERT(node->structure()->classInfo() == StringObject::info());

Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (214773 => 214774)


--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2017-04-03 12:32:51 UTC (rev 214773)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2017-04-03 12:33:21 UTC (rev 214774)
@@ -2711,7 +2711,7 @@
         return true;
     }
 
-    case ToLowerCaseIntrinsic: {
+    case StringPrototypeToLowerCaseIntrinsic: {
         if (argumentCountIncludingThis != 1)
             return false;
 
@@ -2725,6 +2725,26 @@
         return true;
     }
 
+    case NumberPrototypeToStringIntrinsic: {
+        if (argumentCountIncludingThis != 1 && argumentCountIncludingThis != 2)
+            return false;
+
+        if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadType))
+            return false;
+
+        insertChecks();
+        Node* thisNumber = get(virtualRegisterForArgument(0, registerOffset));
+        if (argumentCountIncludingThis == 1) {
+            Node* result = addToGraph(ToString, thisNumber);
+            set(VirtualRegister(resultOperand), result);
+        } else {
+            Node* radix = get(virtualRegisterForArgument(1, registerOffset));
+            Node* result = addToGraph(NumberToStringWithRadix, thisNumber, radix);
+            set(VirtualRegister(resultOperand), result);
+        }
+        return true;
+    }
+
     default:
         return false;
     }

Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGClobberize.h (214773 => 214774)


--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGClobberize.h	2017-04-03 12:32:51 UTC (rev 214773)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGClobberize.h	2017-04-03 12:33:21 UTC (rev 214774)
@@ -1401,6 +1401,9 @@
             write(Heap);
             return;
 
+        case Int32Use:
+        case Int52RepUse:
+        case DoubleRepUse:
         case NotCellUse:
             def(PureValue(node));
             return;
@@ -1449,6 +1452,11 @@
     case ToLowerCase:
         def(PureValue(node));
         return;
+
+    case NumberToStringWithRadix:
+        read(World);
+        write(Heap);
+        return;
         
     case LastNodeType:
         RELEASE_ASSERT_NOT_REACHED();

Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGDoesGC.cpp (214773 => 214774)


--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGDoesGC.cpp	2017-04-03 12:32:51 UTC (rev 214773)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGDoesGC.cpp	2017-04-03 12:33:21 UTC (rev 214774)
@@ -178,6 +178,7 @@
     case ToNumber:
     case ToString:
     case CallStringConstructor:
+    case NumberToStringWithRadix:
     case In:
     case HasOwnProperty:
     case Jump:

Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (214773 => 214774)


--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2017-04-03 12:32:51 UTC (rev 214773)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2017-04-03 12:33:21 UTC (rev 214774)
@@ -1753,6 +1753,17 @@
             break;
         }
 
+        case NumberToStringWithRadix: {
+            if (node->child1()->shouldSpeculateInt32())
+                fixEdge<Int32Use>(node->child1());
+            else if (enableInt52() && node->child1()->shouldSpeculateAnyInt())
+                fixEdge<Int52RepUse>(node->child1());
+            else
+                fixEdge<DoubleRepUse>(node->child1());
+            fixEdge<Int32Use>(node->child2());
+            break;
+        }
+
         case DefineAccessorProperty: {
             fixEdge<CellUse>(m_graph.varArgChild(node, 0));
             Edge& propertyEdge = m_graph.varArgChild(node, 1);
@@ -2229,6 +2240,24 @@
             return;
         }
 
+        if (node->child1()->shouldSpeculateInt32()) {
+            fixEdge<Int32Use>(node->child1());
+            node->clearFlags(NodeMustGenerate);
+            return;
+        }
+
+        if (enableInt52() && node->child1()->shouldSpeculateAnyInt()) {
+            fixEdge<Int52RepUse>(node->child1());
+            node->clearFlags(NodeMustGenerate);
+            return;
+        }
+
+        if (node->child1()->shouldSpeculateNumber()) {
+            fixEdge<DoubleRepUse>(node->child1());
+            node->clearFlags(NodeMustGenerate);
+            return;
+        }
+
         // ToString(Symbol) throws an error. So if the child1 can include Symbols,
         // we need to care about it in the clobberize. In the following case,
         // since NotCellUse edge filter is used and this edge filters Symbols,

Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGNodeType.h (214773 => 214774)


--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGNodeType.h	2017-04-03 12:32:51 UTC (rev 214773)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGNodeType.h	2017-04-03 12:33:21 UTC (rev 214774)
@@ -335,6 +335,7 @@
     macro(ToNumber, NodeResultJS | NodeMustGenerate) \
     macro(CallObjectConstructor, NodeResultJS) \
     macro(CallStringConstructor, NodeResultJS | NodeMustGenerate) \
+    macro(NumberToStringWithRadix, NodeResultJS | NodeMustGenerate) \
     macro(NewStringObject, NodeResultJS) \
     macro(MakeRope, NodeResultJS) \
     macro(In, NodeResultBoolean | NodeMustGenerate) \

Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGOperations.cpp (214773 => 214774)


--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGOperations.cpp	2017-04-03 12:32:51 UTC (rev 214773)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGOperations.cpp	2017-04-03 12:33:21 UTC (rev 214774)
@@ -1644,6 +1644,75 @@
     return jsString(exec, lowercasedString);
 }
 
+char* JIT_OPERATION operationInt32ToString(ExecState* exec, int32_t value, int32_t radix)
+{
+    VM& vm = exec->vm();
+    NativeCallFrameTracer tracer(&vm, exec);
+
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    if (radix < 2 || radix > 36) {
+        throwVMError(exec, scope, createRangeError(exec, ASCIILiteral("toString() radix argument must be between 2 and 36")));
+        return nullptr;
+    }
+
+    return reinterpret_cast<char*>(int32ToString(vm, value, radix));
+}
+
+char* JIT_OPERATION operationInt52ToString(ExecState* exec, int64_t value, int32_t radix)
+{
+    VM& vm = exec->vm();
+    NativeCallFrameTracer tracer(&vm, exec);
+
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    if (radix < 2 || radix > 36) {
+        throwVMError(exec, scope, createRangeError(exec, ASCIILiteral("toString() radix argument must be between 2 and 36")));
+        return nullptr;
+    }
+
+    return reinterpret_cast<char*>(int52ToString(vm, value, radix));
+}
+
+char* JIT_OPERATION operationDoubleToString(ExecState* exec, double value, int32_t radix)
+{
+    VM& vm = exec->vm();
+    NativeCallFrameTracer tracer(&vm, exec);
+
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    if (radix < 2 || radix > 36) {
+        throwVMError(exec, scope, createRangeError(exec, ASCIILiteral("toString() radix argument must be between 2 and 36")));
+        return nullptr;
+    }
+
+    return reinterpret_cast<char*>(numberToString(vm, value, radix));
+}
+
+char* JIT_OPERATION operationInt32ToStringWithValidRadix(ExecState* exec, int32_t value, int32_t radix)
+{
+    VM& vm = exec->vm();
+    NativeCallFrameTracer tracer(&vm, exec);
+
+    return reinterpret_cast<char*>(int32ToString(vm, value, radix));
+}
+
+char* JIT_OPERATION operationInt52ToStringWithValidRadix(ExecState* exec, int64_t value, int32_t radix)
+{
+    VM& vm = exec->vm();
+    NativeCallFrameTracer tracer(&vm, exec);
+
+    return reinterpret_cast<char*>(int52ToString(vm, value, radix));
+}
+
+char* JIT_OPERATION operationDoubleToStringWithValidRadix(ExecState* exec, double value, int32_t radix)
+{
+    VM& vm = exec->vm();
+    NativeCallFrameTracer tracer(&vm, exec);
+
+    return reinterpret_cast<char*>(numberToString(vm, value, radix));
+}
+
 JSString* JIT_OPERATION operationSingleCharacterString(ExecState* exec, int32_t character)
 {
     VM& vm = exec->vm();

Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGOperations.h (214773 => 214774)


--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGOperations.h	2017-04-03 12:32:51 UTC (rev 214773)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGOperations.h	2017-04-03 12:33:21 UTC (rev 214774)
@@ -159,6 +159,13 @@
 
 JSString* JIT_OPERATION operationToLowerCase(ExecState*, JSString*, uint32_t);
 
+char* JIT_OPERATION operationInt32ToString(ExecState*, int32_t, int32_t);
+char* JIT_OPERATION operationInt52ToString(ExecState*, int64_t, int32_t);
+char* JIT_OPERATION operationDoubleToString(ExecState*, double, int32_t);
+char* JIT_OPERATION operationInt32ToStringWithValidRadix(ExecState*, int32_t, int32_t);
+char* JIT_OPERATION operationInt52ToStringWithValidRadix(ExecState*, int64_t, int32_t);
+char* JIT_OPERATION operationDoubleToStringWithValidRadix(ExecState*, double, int32_t);
+
 int32_t JIT_OPERATION operationMapHash(ExecState*, EncodedJSValue input);
 JSCell* JIT_OPERATION operationJSMapFindBucket(ExecState*, JSCell*, EncodedJSValue, int32_t);
 JSCell* JIT_OPERATION operationJSSetFindBucket(ExecState*, JSCell*, EncodedJSValue, int32_t);

Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (214773 => 214774)


--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2017-04-03 12:32:51 UTC (rev 214773)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2017-04-03 12:33:21 UTC (rev 214774)
@@ -897,6 +897,7 @@
         case StringCharAt:
         case CallStringConstructor:
         case ToString:
+        case NumberToStringWithRadix:
         case MakeRope:
         case StrCat: {
             setPrediction(SpecString);

Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGSafeToExecute.h (214773 => 214774)


--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGSafeToExecute.h	2017-04-03 12:32:51 UTC (rev 214773)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGSafeToExecute.h	2017-04-03 12:33:21 UTC (rev 214774)
@@ -288,6 +288,7 @@
     case ToPrimitive:
     case ToString:
     case ToNumber:
+    case NumberToStringWithRadix:
     case SetFunctionName:
     case StrCat:
     case CallStringConstructor:

Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (214773 => 214774)


--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2017-04-03 12:32:51 UTC (rev 214773)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp	2017-04-03 12:33:21 UTC (rev 214774)
@@ -7909,9 +7909,10 @@
     return temporary.gpr();
 }
 
-void SpeculativeJIT::compileToStringOrCallStringConstructorOnCell(Node* node)
+void SpeculativeJIT::compileToStringOrCallStringConstructor(Node* node)
 {
-    if (node->child1().useKind() == NotCellUse) {
+    switch (node->child1().useKind()) {
+    case NotCellUse: {
         JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
         JSValueRegs op1Regs = op1.jsValueRegs();
 
@@ -7933,7 +7934,7 @@
         return;
     }
 
-    if (node->child1().useKind() == UntypedUse) {
+    case UntypedUse: {
         JSValueOperand op1(this, node->child1());
         JSValueRegs op1Regs = op1.jsValueRegs();
         GPRReg op1PayloadGPR = op1Regs.payloadGPR();
@@ -7965,7 +7966,16 @@
         return;
     }
 
+    case Int32Use:
+    case Int52RepUse:
+    case DoubleRepUse:
+        compileToStringOrCallStringConstructorOnNumber(node);
+        return;
 
+    default:
+        break;
+    }
+
     SpeculateCellOperand op1(this, node->child1());
     GPRReg op1GPR = op1.gpr();
     
@@ -8040,6 +8050,92 @@
     }
 }
 
+void SpeculativeJIT::compileToStringOrCallStringConstructorOnNumber(Node* node)
+{
+    auto callToString = [&] (auto operation, GPRReg resultGPR, auto valueReg) {
+        flushRegisters();
+        callOperation(operation, resultGPR, valueReg, CCallHelpers::TrustedImm32(10));
+        m_jit.exceptionCheck();
+        cellResult(resultGPR, node);
+    };
+
+    switch (node->child1().useKind()) {
+    case Int32Use: {
+        SpeculateStrictInt32Operand value(this, node->child1());
+        GPRFlushedCallResult result(this);
+        callToString(operationInt32ToStringWithValidRadix, result.gpr(), value.gpr());
+        break;
+    }
+
+#if USE(JSVALUE64)
+    case Int52RepUse: {
+        SpeculateStrictInt52Operand value(this, node->child1());
+        GPRFlushedCallResult result(this);
+        callToString(operationInt52ToStringWithValidRadix, result.gpr(), value.gpr());
+        break;
+    }
+#endif
+
+    case DoubleRepUse: {
+        SpeculateDoubleOperand value(this, node->child1());
+        GPRFlushedCallResult result(this);
+        callToString(operationDoubleToStringWithValidRadix, result.gpr(), value.fpr());
+        break;
+    }
+
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+    }
+}
+
+void SpeculativeJIT::compileNumberToStringWithRadix(Node* node)
+{
+    bool validRadixIsGuaranteed = false;
+    if (node->child2()->isInt32Constant()) {
+        int32_t radix = node->child2()->asInt32();
+        if (radix >= 2 && radix <= 36)
+            validRadixIsGuaranteed = true;
+    }
+
+    auto callToString = [&] (auto operation, GPRReg resultGPR, auto valueReg, GPRReg radixGPR) {
+        flushRegisters();
+        callOperation(operation, resultGPR, valueReg, radixGPR);
+        m_jit.exceptionCheck();
+        cellResult(resultGPR, node);
+    };
+
+    switch (node->child1().useKind()) {
+    case Int32Use: {
+        SpeculateStrictInt32Operand value(this, node->child1());
+        SpeculateStrictInt32Operand radix(this, node->child2());
+        GPRFlushedCallResult result(this);
+        callToString(validRadixIsGuaranteed ? operationInt32ToStringWithValidRadix : operationInt32ToString, result.gpr(), value.gpr(), radix.gpr());
+        break;
+    }
+
+#if USE(JSVALUE64)
+    case Int52RepUse: {
+        SpeculateStrictInt52Operand value(this, node->child1());
+        SpeculateStrictInt32Operand radix(this, node->child2());
+        GPRFlushedCallResult result(this);
+        callToString(validRadixIsGuaranteed ? operationInt52ToStringWithValidRadix : operationInt52ToString, result.gpr(), value.gpr(), radix.gpr());
+        break;
+    }
+#endif
+
+    case DoubleRepUse: {
+        SpeculateDoubleOperand value(this, node->child1());
+        SpeculateStrictInt32Operand radix(this, node->child2());
+        GPRFlushedCallResult result(this);
+        callToString(validRadixIsGuaranteed ? operationDoubleToStringWithValidRadix : operationDoubleToString, result.gpr(), value.fpr(), radix.gpr());
+        break;
+    }
+
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+    }
+}
+
 void SpeculativeJIT::compileNewStringObject(Node* node)
 {
     SpeculateCellOperand operand(this, node->child1());

Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (214773 => 214774)


--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2017-04-03 12:32:51 UTC (rev 214773)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h	2017-04-03 12:33:21 UTC (rev 214774)
@@ -1377,7 +1377,30 @@
         return appendCallSetResult(operation, result);
     }
 
+    JITCompiler::Call callOperation(P_JITOperation_EZZ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2);
+        return appendCallSetResult(operation, result);
+    }
 
+    JITCompiler::Call callOperation(P_JITOperation_EZZ operation, GPRReg result, GPRReg arg1, TrustedImm32 arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2);
+        return appendCallSetResult(operation, result);
+    }
+
+    JITCompiler::Call callOperation(P_JITOperation_EDZ operation, GPRReg result, FPRReg arg1, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2);
+        return appendCallSetResult(operation, result);
+    }
+
+    JITCompiler::Call callOperation(P_JITOperation_EDZ operation, GPRReg result, FPRReg arg1, TrustedImm32 arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2);
+        return appendCallSetResult(operation, result);
+    }
+
 #if USE(JSVALUE64)
     JITCompiler::Call callOperation(Z_JITOperation_EOJ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
     {
@@ -1601,6 +1624,17 @@
         m_jit.setupArgumentsWithExecState(TrustedImm32(arg1), arg2);
         return appendCallSetResult(operation, result);
     }
+    JITCompiler::Call callOperation(P_JITOperation_EQZ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2);
+        return appendCallSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(P_JITOperation_EQZ operation, GPRReg result, GPRReg arg1, TrustedImm32 arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2);
+        return appendCallSetResult(operation, result);
+    }
+
     JITCompiler::Call callOperation(J_JITOperation_EZIcfZ operation, GPRReg result, int32_t arg1, InlineCallFrame* inlineCallFrame, GPRReg arg2)
     {
         m_jit.setupArgumentsWithExecState(TrustedImm32(arg1), TrustedImmPtr(inlineCallFrame), arg2);
@@ -2657,7 +2691,9 @@
     void emitSwitchString(Node*, SwitchData*);
     void emitSwitch(Node*);
     
-    void compileToStringOrCallStringConstructorOnCell(Node*);
+    void compileToStringOrCallStringConstructor(Node*);
+    void compileToStringOrCallStringConstructorOnNumber(Node*);
+    void compileNumberToStringWithRadix(Node*);
     void compileNewStringObject(Node*);
     
     void compileNewTypedArray(Node*);

Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (214773 => 214774)


--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2017-04-03 12:32:51 UTC (rev 214773)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2017-04-03 12:33:21 UTC (rev 214774)
@@ -2796,6 +2796,11 @@
         break;
     }
 
+    case NumberToStringWithRadix: {
+        compileNumberToStringWithRadix(node);
+        break;
+    }
+
     case GetByValWithThis: {
         JSValueOperand base(this, node->child1());
         JSValueRegs baseRegs = base.jsValueRegs();
@@ -3730,7 +3735,7 @@
         
     case ToString:
     case CallStringConstructor: {
-        compileToStringOrCallStringConstructorOnCell(node);
+        compileToStringOrCallStringConstructor(node);
         break;
     }
         

Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (214773 => 214774)


--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2017-04-03 12:32:51 UTC (rev 214773)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2017-04-03 12:33:21 UTC (rev 214774)
@@ -3711,7 +3711,7 @@
         
     case ToString:
     case CallStringConstructor: {
-        compileToStringOrCallStringConstructorOnCell(node);
+        compileToStringOrCallStringConstructor(node);
         break;
     }
         
@@ -5007,6 +5007,11 @@
         break;
     }
 
+    case NumberToStringWithRadix: {
+        compileNumberToStringWithRadix(node);
+        break;
+    }
+
     case IsObject: {
         JSValueOperand value(this, node->child1());
         GPRTemporary result(this, Reuse, value);

Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGStrengthReductionPhase.cpp (214773 => 214774)


--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGStrengthReductionPhase.cpp	2017-04-03 12:32:51 UTC (rev 214773)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/dfg/DFGStrengthReductionPhase.cpp	2017-04-03 12:33:21 UTC (rev 214774)
@@ -390,6 +390,37 @@
             break;
         }
 
+        case ToString:
+        case CallStringConstructor: {
+            Edge& child1 = m_node->child1();
+            switch (child1.useKind()) {
+            case Int32Use:
+            case Int52RepUse:
+            case DoubleRepUse: {
+                if (child1->hasConstant()) {
+                    JSValue value = child1->constant()->value();
+                    if (value) {
+                        String result;
+                        if (value.isInt32())
+                            result = String::number(value.asInt32());
+                        else if (value.isNumber())
+                            result = String::numberToStringECMAScript(value.asNumber());
+
+                        if (!result.isNull()) {
+                            m_node->convertToLazyJSConstant(m_graph, LazyJSValue::newString(m_graph, result));
+                            m_changed = true;
+                        }
+                    }
+                }
+                break;
+            }
+
+            default:
+                break;
+            }
+            break;
+        }
+
         case GetArrayLength: {
             if (m_node->arrayMode().type() == Array::Generic
                 || m_node->arrayMode().type() == Array::String) {

Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/ftl/FTLCapabilities.cpp (214773 => 214774)


--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2017-04-03 12:32:51 UTC (rev 214773)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2017-04-03 12:33:21 UTC (rev 214774)
@@ -279,6 +279,7 @@
     case DefineDataProperty:
     case DefineAccessorProperty:
     case ToLowerCase:
+    case NumberToStringWithRadix:
     case CheckDOM:
     case CallDOM:
     case CallDOMGetter:

Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (214773 => 214774)


--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2017-04-03 12:32:51 UTC (rev 214773)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2017-04-03 12:33:21 UTC (rev 214774)
@@ -1076,6 +1076,9 @@
         case ToLowerCase:
             compileToLowerCase();
             break;
+        case NumberToStringWithRadix:
+            compileNumberToStringWithRadix();
+            break;
         case CheckDOM:
             compileCheckDOM();
             break;
@@ -4949,6 +4952,18 @@
             setJSValue(m_out.phi(Int64, simpleResult, convertedResult));
             return;
         }
+
+        case Int32Use:
+            setJSValue(vmCall(Int64, m_out.operation(operationInt32ToStringWithValidRadix), m_callFrame, lowInt32(m_node->child1()), m_out.constInt32(10)));
+            return;
+
+        case Int52RepUse:
+            setJSValue(vmCall(Int64, m_out.operation(operationInt52ToStringWithValidRadix), m_callFrame, lowStrictInt52(m_node->child1()), m_out.constInt32(10)));
+            return;
+
+        case DoubleRepUse:
+            setJSValue(vmCall(Int64, m_out.operation(operationDoubleToStringWithValidRadix), m_callFrame, lowDouble(m_node->child1()), m_out.constInt32(10)));
+            return;
             
         default:
             DFG_CRASH(m_graph, m_node, "Bad use kind");
@@ -9882,6 +9897,30 @@
         setJSValue(m_out.phi(pointerType(), fastResult, slowResult));
     }
 
+    void compileNumberToStringWithRadix()
+    {
+        bool validRadixIsGuaranteed = false;
+        if (m_node->child2()->isInt32Constant()) {
+            int32_t radix = m_node->child2()->asInt32();
+            if (radix >= 2 && radix <= 36)
+                validRadixIsGuaranteed = true;
+        }
+
+        switch (m_node->child1().useKind()) {
+        case Int32Use:
+            setJSValue(vmCall(pointerType(), m_out.operation(validRadixIsGuaranteed ? operationInt32ToStringWithValidRadix : operationInt32ToString), m_callFrame, lowInt32(m_node->child1()), lowInt32(m_node->child2())));
+            break;
+        case Int52RepUse:
+            setJSValue(vmCall(pointerType(), m_out.operation(validRadixIsGuaranteed ? operationInt52ToStringWithValidRadix : operationInt52ToString), m_callFrame, lowStrictInt52(m_node->child1()), lowInt32(m_node->child2())));
+            break;
+        case DoubleRepUse:
+            setJSValue(vmCall(pointerType(), m_out.operation(validRadixIsGuaranteed ? operationDoubleToStringWithValidRadix : operationDoubleToString), m_callFrame, lowDouble(m_node->child1()), lowInt32(m_node->child2())));
+            break;
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+        }
+    }
+
     void compileResolveScope()
     {
         UniquedStringImpl* uid = m_graph.identifiers()[m_node->identifierNumber()];

Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/jit/CCallHelpers.h (214773 => 214774)


--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/jit/CCallHelpers.h	2017-04-03 12:32:51 UTC (rev 214773)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/jit/CCallHelpers.h	2017-04-03 12:33:21 UTC (rev 214774)
@@ -868,6 +868,14 @@
         addCallArgument(arg2);
     }
 
+    ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, TrustedImm32 arg2)
+    {
+        resetCallArguments();
+        addCallArgument(GPRInfo::callFrameRegister);
+        addCallArgument(arg1);
+        addCallArgument(arg2);
+    }
+
     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, FPRReg arg3)
     {
         resetCallArguments();
@@ -1069,6 +1077,20 @@
         move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
     }
 
+    ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, TrustedImm32 arg2)
+    {
+#if OS(WINDOWS) && CPU(X86_64)
+        // On Windows, arguments map to designated registers based on the argument positions, even when there are interlaced scalar and floating point arguments.
+        // See http://msdn.microsoft.com/en-us/library/zthk2dkh.aspx
+        moveDouble(arg1, FPRInfo::argumentFPR1);
+        move(arg2, GPRInfo::argumentGPR2);
+#else
+        moveDouble(arg1, FPRInfo::argumentFPR0);
+        move(arg2, GPRInfo::argumentGPR1);
+#endif
+        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+    }
+
     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, FPRReg arg3)
     {
 #if OS(WINDOWS) && CPU(X86_64)
@@ -1111,6 +1133,13 @@
         move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
     }
 
+    ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, TrustedImm32 arg2)
+    {
+        moveDouble(arg1, FPRInfo::argumentFPR0);
+        move(arg2, GPRInfo::argumentGPR1);
+        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+    }
+
     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, FPRReg arg3)
     {
         moveDouble(arg3, FPRInfo::argumentFPR0);
@@ -1151,6 +1180,13 @@
         move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
     }
 
+    ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, TrustedImm32 arg2)
+    {
+        move(arg2, GPRInfo::argumentGPR3);
+        assembler().vmov(GPRInfo::argumentGPR1, GPRInfo::argumentGPR2, arg1);
+        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+    }
+
     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, FPRReg arg3)
     {
         setupStubArguments(arg1, arg2);
@@ -1204,6 +1240,13 @@
         poke(arg2, 4);
     }
 
+    ALWAYS_INLINE void setupArgumentsWithExecState(FPRReg arg1, TrustedImm32 arg2)
+    {
+        assembler().vmov(GPRInfo::argumentGPR2, GPRInfo::argumentGPR3, arg1);
+        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+        poke(arg2, 4);
+    }
+
     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, FPRReg arg3)
     {
         setupStubArguments(arg1, arg2);

Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/jit/JITOperations.h (214773 => 214774)


--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/jit/JITOperations.h	2017-04-03 12:32:51 UTC (rev 214773)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/jit/JITOperations.h	2017-04-03 12:33:21 UTC (rev 214774)
@@ -311,6 +311,8 @@
 typedef char* (JIT_OPERATION *P_JITOperation_EStZB)(ExecState*, Structure*, int32_t, Butterfly*);
 typedef char* (JIT_OPERATION *P_JITOperation_EStZP)(ExecState*, Structure*, int32_t, char*);
 typedef char* (JIT_OPERATION *P_JITOperation_EZZ)(ExecState*, int32_t, int32_t);
+typedef char* (JIT_OPERATION *P_JITOperation_EQZ)(ExecState*, int64_t, int32_t);
+typedef char* (JIT_OPERATION *P_JITOperation_EDZ)(ExecState*, double, int32_t);
 typedef SlowPathReturnType (JIT_OPERATION *Sprt_JITOperation_ECli)(ExecState*, CallLinkInfo*);
 typedef StringImpl* (JIT_OPERATION *T_JITOperation_EJss)(ExecState*, JSString*);
 typedef JSString* (JIT_OPERATION *Jss_JITOperation_EZ)(ExecState*, int32_t);

Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/Intrinsic.h (214773 => 214774)


--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/Intrinsic.h	2017-04-03 12:32:51 UTC (rev 214773)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/Intrinsic.h	2017-04-03 12:33:21 UTC (rev 214774)
@@ -56,6 +56,8 @@
     StringPrototypeValueOfIntrinsic,
     StringPrototypeReplaceIntrinsic,
     StringPrototypeReplaceRegExpIntrinsic,
+    StringPrototypeToLowerCaseIntrinsic,
+    NumberPrototypeToStringIntrinsic,
     IMulIntrinsic,
     RandomIntrinsic,
     FRoundIntrinsic,
@@ -78,7 +80,6 @@
     AtomicsWaitIntrinsic,
     AtomicsWakeIntrinsic,
     AtomicsXorIntrinsic,
-    ToLowerCaseIntrinsic,
     ParseIntIntrinsic,
 
     // Getter intrinsics.

Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/NumberPrototype.cpp (214773 => 214774)


--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/NumberPrototype.cpp	2017-04-03 12:32:51 UTC (rev 214773)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/NumberPrototype.cpp	2017-04-03 12:33:21 UTC (rev 214774)
@@ -58,7 +58,7 @@
 
 /* Source for NumberPrototype.lut.h
 @begin numberPrototypeTable
-  toString          numberProtoFuncToString         DontEnum|Function 1
+  toString          numberProtoFuncToString         DontEnum|Function 1 NumberPrototypeToStringIntrinsic
   toLocaleString    numberProtoFuncToLocaleString   DontEnum|Function 0
   valueOf           numberProtoFuncValueOf          DontEnum|Function 0
   toFixed           numberProtoFuncToFixed          DontEnum|Function 1
@@ -144,7 +144,7 @@
 // Mapping from integers 0..35 to digit identifying this value, for radix 2..36.
 static const char radixDigits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
 
-static char* int52ToStringWithRadix(char* startOfResultString, int64_t int52Value, unsigned radix)
+static inline char* int52ToStringWithRadix(char* startOfResultString, int64_t int52Value, unsigned radix)
 {
     bool negative = false;
     uint64_t positiveNumber = int52Value;
@@ -499,25 +499,68 @@
     return radix;
 }
 
-static inline EncodedJSValue integerValueToString(ExecState* exec, int32_t radix, int32_t value)
+static inline JSString* int32ToStringInternal(VM& vm, int32_t value, int32_t radix)
 {
+    ASSERT(!(radix < 2 || radix > 36));
     // A negative value casted to unsigned would be bigger than 36 (the max radix).
     if (static_cast<unsigned>(value) < static_cast<unsigned>(radix)) {
         ASSERT(value <= 36);
         ASSERT(value >= 0);
-        VM* vm = &exec->vm();
-        return JSValue::encode(vm->smallStrings.singleCharacterString(radixDigits[value]));
+        return vm.smallStrings.singleCharacterString(radixDigits[value]);
     }
 
     if (radix == 10) {
-        VM* vm = &exec->vm();
-        return JSValue::encode(jsString(vm, vm->numericStrings.add(value)));
+        return jsString(&vm, vm.numericStrings.add(value));
     }
 
-    return JSValue::encode(jsString(exec, toStringWithRadix(value, radix)));
+    return jsString(&vm, toStringWithRadix(value, radix));
 
 }
 
+static ALWAYS_INLINE JSString* numberToStringInternal(VM& vm, double doubleValue, int32_t radix)
+{
+    ASSERT(!(radix < 2 || radix > 36));
+
+    int32_t integerValue = static_cast<int32_t>(doubleValue);
+    if (integerValue == doubleValue)
+        return int32ToStringInternal(vm, integerValue, radix);
+
+    if (radix == 10)
+        return jsString(&vm, vm.numericStrings.add(doubleValue));
+
+    if (!std::isfinite(doubleValue))
+        return jsNontrivialString(&vm, String::numberToStringECMAScript(doubleValue));
+
+    RadixBuffer buffer;
+    return jsString(&vm, toStringWithRadix(buffer, doubleValue, radix));
+}
+
+JSString* int32ToString(VM& vm, int32_t value, int32_t radix)
+{
+    return int32ToStringInternal(vm, value, radix);
+}
+
+JSString* int52ToString(VM& vm, int64_t value, int32_t radix)
+{
+    ASSERT(!(radix < 2 || radix > 36));
+    if (radix == 10)
+        return jsString(&vm, vm.numericStrings.add(static_cast<double>(value)));
+
+    // Position the decimal point at the center of the string, set
+    // the startOfResultString pointer to point at the decimal point.
+    RadixBuffer buffer;
+    char* decimalPoint = buffer + sizeof(buffer) / 2;
+    char* startOfResultString = decimalPoint;
+    *decimalPoint = '\0';
+
+    return jsString(&vm, int52ToStringWithRadix(startOfResultString, value, radix));
+}
+
+JSString* numberToString(VM& vm, double doubleValue, int32_t radix)
+{
+    return numberToStringInternal(vm, doubleValue, radix);
+}
+
 EncodedJSValue JSC_HOST_CALL numberProtoFuncToString(ExecState* exec)
 {
     VM& vm = exec->vm();
@@ -531,18 +574,7 @@
     if (radix < 2 || radix > 36)
         return throwVMError(exec, scope, createRangeError(exec, ASCIILiteral("toString() radix argument must be between 2 and 36")));
 
-    int32_t integerValue = static_cast<int32_t>(doubleValue);
-    if (integerValue == doubleValue)
-        return integerValueToString(exec, radix, integerValue);
-
-    if (radix == 10)
-        return JSValue::encode(jsString(&vm, vm.numericStrings.add(doubleValue)));
-
-    if (!std::isfinite(doubleValue))
-        return JSValue::encode(jsNontrivialString(exec, String::numberToStringECMAScript(doubleValue)));
-
-    RadixBuffer s;
-    return JSValue::encode(jsString(exec, toStringWithRadix(s, doubleValue, radix)));
+    return JSValue::encode(numberToStringInternal(vm, doubleValue, radix));
 }
 
 EncodedJSValue JSC_HOST_CALL numberProtoFuncToLocaleString(ExecState* exec)

Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/NumberPrototype.h (214773 => 214774)


--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/NumberPrototype.h	2017-04-03 12:32:51 UTC (rev 214773)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/NumberPrototype.h	2017-04-03 12:33:21 UTC (rev 214774)
@@ -51,5 +51,8 @@
 };
 
 EncodedJSValue JSC_HOST_CALL numberProtoFuncValueOf(ExecState*);
+JSString* int32ToString(VM&, int32_t value, int32_t radix);
+JSString* int52ToString(VM&, int64_t value, int32_t radix);
+JSString* numberToString(VM&, double value, int32_t radix);
 
 } // namespace JSC

Modified: releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/StringPrototype.cpp (214773 => 214774)


--- releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/StringPrototype.cpp	2017-04-03 12:32:51 UTC (rev 214773)
+++ releases/WebKitGTK/webkit-2.16/Source/_javascript_Core/runtime/StringPrototype.cpp	2017-04-03 12:33:21 UTC (rev 214774)
@@ -142,7 +142,7 @@
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("slice", stringProtoFuncSlice, DontEnum, 2);
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("substr", stringProtoFuncSubstr, DontEnum, 2);
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("substring", stringProtoFuncSubstring, DontEnum, 2);
-    JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION("toLowerCase", stringProtoFuncToLowerCase, DontEnum, 0, ToLowerCaseIntrinsic);
+    JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION("toLowerCase", stringProtoFuncToLowerCase, DontEnum, 0, StringPrototypeToLowerCaseIntrinsic);
     JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("toUpperCase", stringProtoFuncToUpperCase, DontEnum, 0);
 #if ENABLE(INTL)
     JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION("localeCompare", stringPrototypeLocaleCompareCodeGenerator, DontEnum);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to