Title: [115655] trunk
Revision
115655
Author
[email protected]
Date
2012-04-30 12:02:25 -0700 (Mon, 30 Apr 2012)

Log Message

Source/_javascript_Core: Add fast patch for radix == 10 on numberProtoFuncToString
https://bugs.webkit.org/show_bug.cgi?id=85120

Patch by Benjamin Poulain <[email protected]> on 2012-04-30
Reviewed by Darin Adler.

When radix, we use to turn the doubleValue into a JSValue just to convert
it to a String. The problem is that was using the slow path for conversion and
for the toString() operation.

This patch shortcuts the creation of a JSValue and uses NumericStrings directly.
The conversion is split between Integer and Double to ensure the fastest conversion
for the common case of integer arguments.

Converting number with radix 10 becomes 5% faster.

Due to the simpler conversion of number to string for integer, converting
integers that do not fall in the two previous optimizations get 32% faster.

* runtime/NumberPrototype.cpp:
(JSC::extractRadixFromArgs):
(JSC::integerValueToString):
(JSC::numberProtoFuncToString):

LayoutTests: Add fast path for radix == 10 to numberProtoFuncToString
https://bugs.webkit.org/show_bug.cgi?id=85120

Patch by Benjamin Poulain <[email protected]> on 2012-04-30
Reviewed by Darin Adler.

Add more test coverage for Number.proto.toString.

* platform/chromium/test_expectations.txt: Mark the test as failing on Chromium.
* fast/js/toString-number-expected.txt: Added.
* fast/js/toString-number.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (115654 => 115655)


--- trunk/LayoutTests/ChangeLog	2012-04-30 18:51:27 UTC (rev 115654)
+++ trunk/LayoutTests/ChangeLog	2012-04-30 19:02:25 UTC (rev 115655)
@@ -1,3 +1,16 @@
+2012-04-30  Benjamin Poulain  <[email protected]>
+
+        Add fast path for radix == 10 to numberProtoFuncToString
+        https://bugs.webkit.org/show_bug.cgi?id=85120
+
+        Reviewed by Darin Adler.
+
+        Add more test coverage for Number.proto.toString.
+
+        * platform/chromium/test_expectations.txt: Mark the test as failing on Chromium.
+        * fast/js/toString-number-expected.txt: Added.
+        * fast/js/toString-number.html: Added.
+
 2012-04-30  Tommy Widenflycht  <[email protected]>
 
         MediaStream API: Adding a test for the experimental PeerConnection00

Added: trunk/LayoutTests/fast/js/toString-number-expected.txt (0 => 115655)


--- trunk/LayoutTests/fast/js/toString-number-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/js/toString-number-expected.txt	2012-04-30 19:02:25 UTC (rev 115655)
@@ -0,0 +1,306 @@
+Test the conversion performed by the function Number.prototype.toString.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Number(0).toString() is "0"
+PASS Number.prototype.toString.call(0) is "0"
+PASS Number.prototype.toString.call(new Number(0)) is "0"
+PASS Number("0").toString() is "0"
+PASS Number(0).toString(10) is "0"
+PASS Number(0).toString(2) is "0"
+PASS Number.prototype.toString.call(0, 2) is "0"
+PASS Number.prototype.toString.call(new Number(0), 2) is "0"
+PASS Number(0).toString(36) is "0"
+PASS Number.prototype.toString.call(0, 36) is "0"
+PASS Number.prototype.toString.call(new Number(0), 36) is "0"
+PASS Number(-1).toString() is "-1"
+PASS Number.prototype.toString.call(-1) is "-1"
+PASS Number.prototype.toString.call(new Number(-1)) is "-1"
+PASS Number("-1").toString() is "-1"
+PASS Number(-1).toString(10) is "-1"
+PASS Number(-1).toString(2) is "-1"
+PASS Number.prototype.toString.call(-1, 2) is "-1"
+PASS Number.prototype.toString.call(new Number(-1), 2) is "-1"
+PASS Number(-1).toString(36) is "-1"
+PASS Number.prototype.toString.call(-1, 36) is "-1"
+PASS Number.prototype.toString.call(new Number(-1), 36) is "-1"
+PASS Number(1).toString() is "1"
+PASS Number.prototype.toString.call(1) is "1"
+PASS Number.prototype.toString.call(new Number(1)) is "1"
+PASS Number("1").toString() is "1"
+PASS Number(1).toString(10) is "1"
+PASS Number(1).toString(2) is "1"
+PASS Number.prototype.toString.call(1, 2) is "1"
+PASS Number.prototype.toString.call(new Number(1), 2) is "1"
+PASS Number(1).toString(36) is "1"
+PASS Number.prototype.toString.call(1, 36) is "1"
+PASS Number.prototype.toString.call(new Number(1), 36) is "1"
+PASS Number(1984).toString() is "1984"
+PASS Number.prototype.toString.call(1984) is "1984"
+PASS Number.prototype.toString.call(new Number(1984)) is "1984"
+PASS Number("1984").toString() is "1984"
+PASS Number(1984).toString(10) is "1984"
+PASS Number(1984).toString(2) is "11111000000"
+PASS Number.prototype.toString.call(1984, 2) is "11111000000"
+PASS Number.prototype.toString.call(new Number(1984), 2) is "11111000000"
+PASS Number(1984).toString(36) is "1j4"
+PASS Number.prototype.toString.call(1984, 36) is "1j4"
+PASS Number.prototype.toString.call(new Number(1984), 36) is "1j4"
+PASS Number(-1984).toString() is "-1984"
+PASS Number.prototype.toString.call(-1984) is "-1984"
+PASS Number.prototype.toString.call(new Number(-1984)) is "-1984"
+PASS Number("-1984").toString() is "-1984"
+PASS Number(-1984).toString(10) is "-1984"
+PASS Number(-1984).toString(2) is "-11111000000"
+PASS Number.prototype.toString.call(-1984, 2) is "-11111000000"
+PASS Number.prototype.toString.call(new Number(-1984), 2) is "-11111000000"
+PASS Number(-1984).toString(36) is "-1j4"
+PASS Number.prototype.toString.call(-1984, 36) is "-1j4"
+PASS Number.prototype.toString.call(new Number(-1984), 36) is "-1j4"
+PASS Number(2147483647).toString() is "2147483647"
+PASS Number.prototype.toString.call(2147483647) is "2147483647"
+PASS Number.prototype.toString.call(new Number(2147483647)) is "2147483647"
+PASS Number("2147483647").toString() is "2147483647"
+PASS Number(2147483647).toString(10) is "2147483647"
+PASS Number(2147483647).toString(2) is "1111111111111111111111111111111"
+PASS Number.prototype.toString.call(2147483647, 2) is "1111111111111111111111111111111"
+PASS Number.prototype.toString.call(new Number(2147483647), 2) is "1111111111111111111111111111111"
+PASS Number(2147483647).toString(36) is "zik0zj"
+PASS Number.prototype.toString.call(2147483647, 36) is "zik0zj"
+PASS Number.prototype.toString.call(new Number(2147483647), 36) is "zik0zj"
+PASS Number(-2147483648).toString() is "-2147483648"
+PASS Number.prototype.toString.call(-2147483648) is "-2147483648"
+PASS Number.prototype.toString.call(new Number(-2147483648)) is "-2147483648"
+PASS Number("-2147483648").toString() is "-2147483648"
+PASS Number(-2147483648).toString(10) is "-2147483648"
+PASS Number(-2147483648).toString(2) is "-10000000000000000000000000000000"
+PASS Number.prototype.toString.call(-2147483648, 2) is "-10000000000000000000000000000000"
+PASS Number.prototype.toString.call(new Number(-2147483648), 2) is "-10000000000000000000000000000000"
+PASS Number(-2147483648).toString(36) is "-zik0zk"
+PASS Number.prototype.toString.call(-2147483648, 36) is "-zik0zk"
+PASS Number.prototype.toString.call(new Number(-2147483648), 36) is "-zik0zk"
+PASS Number(9007199254740992).toString() is "9007199254740992"
+PASS Number.prototype.toString.call(9007199254740992) is "9007199254740992"
+PASS Number.prototype.toString.call(new Number(9007199254740992)) is "9007199254740992"
+PASS Number("9007199254740992").toString() is "9007199254740992"
+PASS Number(9007199254740992).toString(10) is "9007199254740992"
+PASS Number(9007199254740992).toString(2) is "100000000000000000000000000000000000000000000000000000"
+PASS Number.prototype.toString.call(9007199254740992, 2) is "100000000000000000000000000000000000000000000000000000"
+PASS Number.prototype.toString.call(new Number(9007199254740992), 2) is "100000000000000000000000000000000000000000000000000000"
+PASS Number(9007199254740992).toString(36) is "2gosa7pa2gw"
+PASS Number.prototype.toString.call(9007199254740992, 36) is "2gosa7pa2gw"
+PASS Number.prototype.toString.call(new Number(9007199254740992), 36) is "2gosa7pa2gw"
+PASS Number(-9007199254740992).toString() is "-9007199254740992"
+PASS Number.prototype.toString.call(-9007199254740992) is "-9007199254740992"
+PASS Number.prototype.toString.call(new Number(-9007199254740992)) is "-9007199254740992"
+PASS Number("-9007199254740992").toString() is "-9007199254740992"
+PASS Number(-9007199254740992).toString(10) is "-9007199254740992"
+PASS Number(-9007199254740992).toString(2) is "-100000000000000000000000000000000000000000000000000000"
+PASS Number.prototype.toString.call(-9007199254740992, 2) is "-100000000000000000000000000000000000000000000000000000"
+PASS Number.prototype.toString.call(new Number(-9007199254740992), 2) is "-100000000000000000000000000000000000000000000000000000"
+PASS Number(-9007199254740992).toString(36) is "-2gosa7pa2gw"
+PASS Number.prototype.toString.call(-9007199254740992, 36) is "-2gosa7pa2gw"
+PASS Number.prototype.toString.call(new Number(-9007199254740992), 36) is "-2gosa7pa2gw"
+PASS Number(0).toString() is "0"
+PASS Number.prototype.toString.call(0) is "0"
+PASS Number.prototype.toString.call(new Number(0)) is "0"
+PASS Number("0").toString() is "0"
+PASS Number(0).toString(10) is "0"
+PASS Number(0).toString(2) is "0"
+PASS Number.prototype.toString.call(0, 2) is "0"
+PASS Number.prototype.toString.call(new Number(0), 2) is "0"
+PASS Number(0).toString(36) is "0"
+PASS Number.prototype.toString.call(0, 36) is "0"
+PASS Number.prototype.toString.call(new Number(0), 36) is "0"
+PASS Number(-1).toString() is "-1"
+PASS Number.prototype.toString.call(-1) is "-1"
+PASS Number.prototype.toString.call(new Number(-1)) is "-1"
+PASS Number("-1").toString() is "-1"
+PASS Number(-1).toString(10) is "-1"
+PASS Number(-1).toString(2) is "-1"
+PASS Number.prototype.toString.call(-1, 2) is "-1"
+PASS Number.prototype.toString.call(new Number(-1), 2) is "-1"
+PASS Number(-1).toString(36) is "-1"
+PASS Number.prototype.toString.call(-1, 36) is "-1"
+PASS Number.prototype.toString.call(new Number(-1), 36) is "-1"
+PASS Number(1).toString() is "1"
+PASS Number.prototype.toString.call(1) is "1"
+PASS Number.prototype.toString.call(new Number(1)) is "1"
+PASS Number("1").toString() is "1"
+PASS Number(1).toString(10) is "1"
+PASS Number(1).toString(2) is "1"
+PASS Number.prototype.toString.call(1, 2) is "1"
+PASS Number.prototype.toString.call(new Number(1), 2) is "1"
+PASS Number(1).toString(36) is "1"
+PASS Number.prototype.toString.call(1, 36) is "1"
+PASS Number.prototype.toString.call(new Number(1), 36) is "1"
+PASS Number(1984).toString() is "1984"
+PASS Number.prototype.toString.call(1984) is "1984"
+PASS Number.prototype.toString.call(new Number(1984)) is "1984"
+PASS Number("1984").toString() is "1984"
+PASS Number(1984).toString(10) is "1984"
+PASS Number(1984).toString(2) is "11111000000"
+PASS Number.prototype.toString.call(1984, 2) is "11111000000"
+PASS Number.prototype.toString.call(new Number(1984), 2) is "11111000000"
+PASS Number(1984).toString(36) is "1j4"
+PASS Number.prototype.toString.call(1984, 36) is "1j4"
+PASS Number.prototype.toString.call(new Number(1984), 36) is "1j4"
+PASS Number(-1984).toString() is "-1984"
+PASS Number.prototype.toString.call(-1984) is "-1984"
+PASS Number.prototype.toString.call(new Number(-1984)) is "-1984"
+PASS Number("-1984").toString() is "-1984"
+PASS Number(-1984).toString(10) is "-1984"
+PASS Number(-1984).toString(2) is "-11111000000"
+PASS Number.prototype.toString.call(-1984, 2) is "-11111000000"
+PASS Number.prototype.toString.call(new Number(-1984), 2) is "-11111000000"
+PASS Number(-1984).toString(36) is "-1j4"
+PASS Number.prototype.toString.call(-1984, 36) is "-1j4"
+PASS Number.prototype.toString.call(new Number(-1984), 36) is "-1j4"
+PASS Number(2147483647).toString() is "2147483647"
+PASS Number.prototype.toString.call(2147483647) is "2147483647"
+PASS Number.prototype.toString.call(new Number(2147483647)) is "2147483647"
+PASS Number("2147483647").toString() is "2147483647"
+PASS Number(2147483647).toString(10) is "2147483647"
+PASS Number(2147483647).toString(2) is "1111111111111111111111111111111"
+PASS Number.prototype.toString.call(2147483647, 2) is "1111111111111111111111111111111"
+PASS Number.prototype.toString.call(new Number(2147483647), 2) is "1111111111111111111111111111111"
+PASS Number(2147483647).toString(36) is "zik0zj"
+PASS Number.prototype.toString.call(2147483647, 36) is "zik0zj"
+PASS Number.prototype.toString.call(new Number(2147483647), 36) is "zik0zj"
+PASS Number(-2147483648).toString() is "-2147483648"
+PASS Number.prototype.toString.call(-2147483648) is "-2147483648"
+PASS Number.prototype.toString.call(new Number(-2147483648)) is "-2147483648"
+PASS Number("-2147483648").toString() is "-2147483648"
+PASS Number(-2147483648).toString(10) is "-2147483648"
+PASS Number(-2147483648).toString(2) is "-10000000000000000000000000000000"
+PASS Number.prototype.toString.call(-2147483648, 2) is "-10000000000000000000000000000000"
+PASS Number.prototype.toString.call(new Number(-2147483648), 2) is "-10000000000000000000000000000000"
+PASS Number(-2147483648).toString(36) is "-zik0zk"
+PASS Number.prototype.toString.call(-2147483648, 36) is "-zik0zk"
+PASS Number.prototype.toString.call(new Number(-2147483648), 36) is "-zik0zk"
+PASS Number(9007199254740992).toString() is "9007199254740992"
+PASS Number.prototype.toString.call(9007199254740992) is "9007199254740992"
+PASS Number.prototype.toString.call(new Number(9007199254740992)) is "9007199254740992"
+PASS Number("9007199254740992").toString() is "9007199254740992"
+PASS Number(9007199254740992).toString(10) is "9007199254740992"
+PASS Number(9007199254740992).toString(2) is "100000000000000000000000000000000000000000000000000000"
+PASS Number.prototype.toString.call(9007199254740992, 2) is "100000000000000000000000000000000000000000000000000000"
+PASS Number.prototype.toString.call(new Number(9007199254740992), 2) is "100000000000000000000000000000000000000000000000000000"
+PASS Number(9007199254740992).toString(36) is "2gosa7pa2gw"
+PASS Number.prototype.toString.call(9007199254740992, 36) is "2gosa7pa2gw"
+PASS Number.prototype.toString.call(new Number(9007199254740992), 36) is "2gosa7pa2gw"
+PASS Number(-9007199254740992).toString() is "-9007199254740992"
+PASS Number.prototype.toString.call(-9007199254740992) is "-9007199254740992"
+PASS Number.prototype.toString.call(new Number(-9007199254740992)) is "-9007199254740992"
+PASS Number("-9007199254740992").toString() is "-9007199254740992"
+PASS Number(-9007199254740992).toString(10) is "-9007199254740992"
+PASS Number(-9007199254740992).toString(2) is "-100000000000000000000000000000000000000000000000000000"
+PASS Number.prototype.toString.call(-9007199254740992, 2) is "-100000000000000000000000000000000000000000000000000000"
+PASS Number.prototype.toString.call(new Number(-9007199254740992), 2) is "-100000000000000000000000000000000000000000000000000000"
+PASS Number(-9007199254740992).toString(36) is "-2gosa7pa2gw"
+PASS Number.prototype.toString.call(-9007199254740992, 36) is "-2gosa7pa2gw"
+PASS Number.prototype.toString.call(new Number(-9007199254740992), 36) is "-2gosa7pa2gw"
+PASS Number(0.1).toString() is "0.1"
+PASS Number.prototype.toString.call(0.1) is "0.1"
+PASS Number.prototype.toString.call(new Number(0.1)) is "0.1"
+PASS Number("0.1").toString() is "0.1"
+PASS Number(0.1).toString(10) is "0.1"
+PASS Number(0.1).toString(2) is "0.0001100110011001100110011001100110011001100110011001101"
+PASS Number.prototype.toString.call(0.1, 2) is "0.0001100110011001100110011001100110011001100110011001101"
+PASS Number.prototype.toString.call(new Number(0.1), 2) is "0.0001100110011001100110011001100110011001100110011001101"
+PASS Number(0.1).toString(36) is "0.3lllllllllm"
+PASS Number.prototype.toString.call(0.1, 36) is "0.3lllllllllm"
+PASS Number.prototype.toString.call(new Number(0.1), 36) is "0.3lllllllllm"
+PASS Number(-1.1).toString() is "-1.1"
+PASS Number.prototype.toString.call(-1.1) is "-1.1"
+PASS Number.prototype.toString.call(new Number(-1.1)) is "-1.1"
+PASS Number("-1.1").toString() is "-1.1"
+PASS Number(-1.1).toString(10) is "-1.1"
+PASS Number(-1.1).toString(2) is "-1.000110011001100110011001100110011001100110011001101"
+PASS Number.prototype.toString.call(-1.1, 2) is "-1.000110011001100110011001100110011001100110011001101"
+PASS Number.prototype.toString.call(new Number(-1.1), 2) is "-1.000110011001100110011001100110011001100110011001101"
+PASS Number(-1.1).toString(36) is "-1.3llllllllm"
+PASS Number.prototype.toString.call(-1.1, 36) is "-1.3llllllllm"
+PASS Number.prototype.toString.call(new Number(-1.1), 36) is "-1.3llllllllm"
+PASS Number(1.1).toString() is "1.1"
+PASS Number.prototype.toString.call(1.1) is "1.1"
+PASS Number.prototype.toString.call(new Number(1.1)) is "1.1"
+PASS Number("1.1").toString() is "1.1"
+PASS Number(1.1).toString(10) is "1.1"
+PASS Number(1.1).toString(2) is "1.000110011001100110011001100110011001100110011001101"
+PASS Number.prototype.toString.call(1.1, 2) is "1.000110011001100110011001100110011001100110011001101"
+PASS Number.prototype.toString.call(new Number(1.1), 2) is "1.000110011001100110011001100110011001100110011001101"
+PASS Number(1.1).toString(36) is "1.3llllllllm"
+PASS Number.prototype.toString.call(1.1, 36) is "1.3llllllllm"
+PASS Number.prototype.toString.call(new Number(1.1), 36) is "1.3llllllllm"
+PASS Number(1984.1).toString() is "1984.1"
+PASS Number.prototype.toString.call(1984.1) is "1984.1"
+PASS Number.prototype.toString.call(new Number(1984.1)) is "1984.1"
+PASS Number("1984.1").toString() is "1984.1"
+PASS Number(1984.1).toString(10) is "1984.1"
+PASS Number(1984.1).toString(2) is "11111000000.00011001100110011001100110011001100110011"
+PASS Number.prototype.toString.call(1984.1, 2) is "11111000000.00011001100110011001100110011001100110011"
+PASS Number.prototype.toString.call(new Number(1984.1), 2) is "11111000000.00011001100110011001100110011001100110011"
+PASS Number(1984.1).toString(36) is "1j4.3lllllllc"
+PASS Number.prototype.toString.call(1984.1, 36) is "1j4.3lllllllc"
+PASS Number.prototype.toString.call(new Number(1984.1), 36) is "1j4.3lllllllc"
+PASS Number(-1984.1).toString() is "-1984.1"
+PASS Number.prototype.toString.call(-1984.1) is "-1984.1"
+PASS Number.prototype.toString.call(new Number(-1984.1)) is "-1984.1"
+PASS Number("-1984.1").toString() is "-1984.1"
+PASS Number(-1984.1).toString(10) is "-1984.1"
+PASS Number(-1984.1).toString(2) is "-11111000000.00011001100110011001100110011001100110011"
+PASS Number.prototype.toString.call(-1984.1, 2) is "-11111000000.00011001100110011001100110011001100110011"
+PASS Number.prototype.toString.call(new Number(-1984.1), 2) is "-11111000000.00011001100110011001100110011001100110011"
+PASS Number(-1984.1).toString(36) is "-1j4.3lllllllc"
+PASS Number.prototype.toString.call(-1984.1, 36) is "-1j4.3lllllllc"
+PASS Number.prototype.toString.call(new Number(-1984.1), 36) is "-1j4.3lllllllc"
+PASS Number(2147483647.1).toString() is "2147483647.1"
+PASS Number.prototype.toString.call(2147483647.1) is "2147483647.1"
+PASS Number.prototype.toString.call(new Number(2147483647.1)) is "2147483647.1"
+PASS Number("2147483647.1").toString() is "2147483647.1"
+PASS Number(2147483647.1).toString(10) is "2147483647.1"
+PASS Number(2147483647.1).toString(2) is "1111111111111111111111111111111.000110011001100110011"
+PASS Number.prototype.toString.call(2147483647.1, 2) is "1111111111111111111111111111111.000110011001100110011"
+PASS Number.prototype.toString.call(new Number(2147483647.1), 2) is "1111111111111111111111111111111.000110011001100110011"
+PASS Number(2147483647.1).toString(36) is "zik0zj.3lllg"
+PASS Number.prototype.toString.call(2147483647.1, 36) is "zik0zj.3lllg"
+PASS Number.prototype.toString.call(new Number(2147483647.1), 36) is "zik0zj.3lllg"
+PASS Number(-2147483648.1).toString() is "-2147483648.1"
+PASS Number.prototype.toString.call(-2147483648.1) is "-2147483648.1"
+PASS Number.prototype.toString.call(new Number(-2147483648.1)) is "-2147483648.1"
+PASS Number("-2147483648.1").toString() is "-2147483648.1"
+PASS Number(-2147483648.1).toString(10) is "-2147483648.1"
+PASS Number(-2147483648.1).toString(2) is "-10000000000000000000000000000000.000110011001100110011"
+PASS Number.prototype.toString.call(-2147483648.1, 2) is "-10000000000000000000000000000000.000110011001100110011"
+PASS Number.prototype.toString.call(new Number(-2147483648.1), 2) is "-10000000000000000000000000000000.000110011001100110011"
+PASS Number(-2147483648.1).toString(36) is "-zik0zk.3lllg"
+PASS Number.prototype.toString.call(-2147483648.1, 36) is "-zik0zk.3lllg"
+PASS Number.prototype.toString.call(new Number(-2147483648.1), 36) is "-zik0zk.3lllg"
+PASS Number(9007199254740992).toString() is "9007199254740992"
+PASS Number.prototype.toString.call(9007199254740992) is "9007199254740992"
+PASS Number.prototype.toString.call(new Number(9007199254740992)) is "9007199254740992"
+PASS Number("9007199254740992").toString() is "9007199254740992"
+PASS Number(9007199254740992).toString(10) is "9007199254740992"
+PASS Number(9007199254740992).toString(2) is "100000000000000000000000000000000000000000000000000000"
+PASS Number.prototype.toString.call(9007199254740992, 2) is "100000000000000000000000000000000000000000000000000000"
+PASS Number.prototype.toString.call(new Number(9007199254740992), 2) is "100000000000000000000000000000000000000000000000000000"
+PASS Number(9007199254740992).toString(36) is "2gosa7pa2gw"
+PASS Number.prototype.toString.call(9007199254740992, 36) is "2gosa7pa2gw"
+PASS Number.prototype.toString.call(new Number(9007199254740992), 36) is "2gosa7pa2gw"
+PASS Number(-9007199254740992).toString() is "-9007199254740992"
+PASS Number.prototype.toString.call(-9007199254740992) is "-9007199254740992"
+PASS Number.prototype.toString.call(new Number(-9007199254740992)) is "-9007199254740992"
+PASS Number("-9007199254740992").toString() is "-9007199254740992"
+PASS Number(-9007199254740992).toString(10) is "-9007199254740992"
+PASS Number(-9007199254740992).toString(2) is "-100000000000000000000000000000000000000000000000000000"
+PASS Number.prototype.toString.call(-9007199254740992, 2) is "-100000000000000000000000000000000000000000000000000000"
+PASS Number.prototype.toString.call(new Number(-9007199254740992), 2) is "-100000000000000000000000000000000000000000000000000000"
+PASS Number(-9007199254740992).toString(36) is "-2gosa7pa2gw"
+PASS Number.prototype.toString.call(-9007199254740992, 36) is "-2gosa7pa2gw"
+PASS Number.prototype.toString.call(new Number(-9007199254740992), 36) is "-2gosa7pa2gw"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/js/toString-number.html (0 => 115655)


--- trunk/LayoutTests/fast/js/toString-number.html	                        (rev 0)
+++ trunk/LayoutTests/fast/js/toString-number.html	2012-04-30 19:02:25 UTC (rev 115655)
@@ -0,0 +1,82 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script>
+    description("Test the conversion performed by the function Number.prototype.toString.");
+
+    var numberIndex = 0;
+    var base10StringIndex = 1;
+    var base2StringIndex = 2;
+    var base36StringIndex = 3;
+
+    var validNumberData = [
+    // Regular Integers:
+    [0, '0', '0', '0'],
+    [-1, '-1', '-1', '-1'],
+    [1, '1', '1', '1'],
+    [1984, '1984', '11111000000', '1j4'],
+    [-1984, '-1984', '-11111000000', '-1j4'],
+    // Limits:
+    [2147483647, '2147483647', '1111111111111111111111111111111', 'zik0zj'], // INT_MAX.
+    [-2147483648, '-2147483648', '-10000000000000000000000000000000', '-zik0zk'], // INT_MIN
+    [9007199254740992, '9007199254740992', '100000000000000000000000000000000000000000000000000000', '2gosa7pa2gw'], // Max Integer in a double.
+    [-9007199254740992, '-9007199254740992', '-100000000000000000000000000000000000000000000000000000', '-2gosa7pa2gw'], // Min Integer in a double.
+
+    // Integers represented as double.
+    [0.0, '0', '0', '0'],
+    [-1.0, '-1', '-1', '-1'],
+    [1.0, '1', '1', '1'],
+    [1984.0, '1984', '11111000000', '1j4'],
+    [-1984.0, '-1984', '-11111000000', '-1j4'],
+    // Limits:
+    [2147483647.0, '2147483647', '1111111111111111111111111111111', 'zik0zj'], // INT_MAX.
+    [-2147483648.0, '-2147483648', '-10000000000000000000000000000000', '-zik0zk'], // INT_MIN
+    [9007199254740992.0, '9007199254740992', '100000000000000000000000000000000000000000000000000000', '2gosa7pa2gw'], // Max Integer in a double.
+    [-9007199254740992.0, '-9007199254740992', '-100000000000000000000000000000000000000000000000000000', '-2gosa7pa2gw'], // Min Integer in a double.
+
+    // Double.
+    [0.1, '0.1', '0.0001100110011001100110011001100110011001100110011001101', '0.3lllllllllm'],
+    [-1.1, '-1.1', '-1.000110011001100110011001100110011001100110011001101', '-1.3llllllllm'],
+    [1.1, '1.1', '1.000110011001100110011001100110011001100110011001101', '1.3llllllllm'],
+    [1984.1, '1984.1', '11111000000.00011001100110011001100110011001100110011', '1j4.3lllllllc'],
+    [-1984.1, '-1984.1', '-11111000000.00011001100110011001100110011001100110011', '-1j4.3lllllllc'],
+    // Limits:
+    [2147483647.1, '2147483647.1', '1111111111111111111111111111111.000110011001100110011', 'zik0zj.3lllg'],
+    [-2147483648.1, '-2147483648.1', '-10000000000000000000000000000000.000110011001100110011', '-zik0zk.3lllg'],
+    [9007199254740992.1, '9007199254740992', '100000000000000000000000000000000000000000000000000000', '2gosa7pa2gw'],
+    [-9007199254740992.1, '-9007199254740992', '-100000000000000000000000000000000000000000000000000000', '-2gosa7pa2gw'],
+    ];
+
+    for (var i = 0; i < validNumberData.length; ++i) {
+        number = validNumberData[i][numberIndex];
+
+        // Base 10:
+        stringBase10 = validNumberData[i][base10StringIndex];
+        shouldBeEqualToString('Number(' + number + ').toString()', stringBase10);
+        shouldBeEqualToString('Number.prototype.toString.call(' + number + ')', stringBase10);
+        shouldBeEqualToString('Number.prototype.toString.call(new Number(' + number + '))', stringBase10);
+        // Passing the string to number should also lead to valid conversion.
+        shouldBeEqualToString('Number("' + number + '").toString()', stringBase10);
+        // Passing the base explicitly.
+        shouldBeEqualToString('Number(' + number + ').toString(10)', stringBase10);
+
+        // Base 2:
+        stringBase2 = validNumberData[i][base2StringIndex];
+        shouldBeEqualToString('Number(' + number + ').toString(2)', stringBase2);
+        shouldBeEqualToString('Number.prototype.toString.call(' + number + ', 2)', stringBase2);
+        shouldBeEqualToString('Number.prototype.toString.call(new Number(' + number + '), 2)', stringBase2);
+
+        // Base 36:
+        stringBase36 = validNumberData[i][base36StringIndex];
+        shouldBeEqualToString('Number(' + number + ').toString(36)', stringBase36);
+        shouldBeEqualToString('Number.prototype.toString.call(' + number + ', 36)', stringBase36);
+        shouldBeEqualToString('Number.prototype.toString.call(new Number(' + number + '), 36)', stringBase36);
+    }
+    successfullyParsed = true;
+</script>
+<script src=""
+</body>
+</html>

Modified: trunk/LayoutTests/platform/chromium/test_expectations.txt (115654 => 115655)


--- trunk/LayoutTests/platform/chromium/test_expectations.txt	2012-04-30 18:51:27 UTC (rev 115654)
+++ trunk/LayoutTests/platform/chromium/test_expectations.txt	2012-04-30 19:02:25 UTC (rev 115655)
@@ -3713,3 +3713,5 @@
 BUGWK85174 : storage/indexeddb/noblobs.html = TEXT
 
 BUGWK85176 MAC : fast/forms/date/input-date-commit-valid-only.html = TEXT
+
+BUGWK85120 : fast/js/toString-number.html = TEXT

Modified: trunk/Source/_javascript_Core/ChangeLog (115654 => 115655)


--- trunk/Source/_javascript_Core/ChangeLog	2012-04-30 18:51:27 UTC (rev 115654)
+++ trunk/Source/_javascript_Core/ChangeLog	2012-04-30 19:02:25 UTC (rev 115655)
@@ -1,3 +1,28 @@
+2012-04-30  Benjamin Poulain  <[email protected]>
+
+        Add fast patch for radix == 10 on numberProtoFuncToString
+        https://bugs.webkit.org/show_bug.cgi?id=85120
+
+        Reviewed by Darin Adler.
+
+        When radix, we use to turn the doubleValue into a JSValue just to convert
+        it to a String. The problem is that was using the slow path for conversion and
+        for the toString() operation.
+
+        This patch shortcuts the creation of a JSValue and uses NumericStrings directly.
+        The conversion is split between Integer and Double to ensure the fastest conversion
+        for the common case of integer arguments.
+
+        Converting number with radix 10 becomes 5% faster.
+
+        Due to the simpler conversion of number to string for integer, converting
+        integers that do not fall in the two previous optimizations get 32% faster.
+
+        * runtime/NumberPrototype.cpp:
+        (JSC::extractRadixFromArgs):
+        (JSC::integerValueToString):
+        (JSC::numberProtoFuncToString):
+
 2012-04-30  Carlos Garcia Campos  <[email protected]>
 
         Unreviewed. Fix make distcheck.

Modified: trunk/Source/_javascript_Core/runtime/NumberPrototype.cpp (115654 => 115655)


--- trunk/Source/_javascript_Core/runtime/NumberPrototype.cpp	2012-04-30 18:51:27 UTC (rev 115654)
+++ trunk/Source/_javascript_Core/runtime/NumberPrototype.cpp	2012-04-30 19:02:25 UTC (rev 115655)
@@ -148,7 +148,7 @@
 typedef char RadixBuffer[2180];
 
 // Mapping from integers 0..35 to digit identifying this value, for radix 2..36.
-static const char* const radixDigits = "0123456789abcdefghijklmnopqrstuvwxyz";
+static const char radixDigits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
 
 static char* toStringWithRadix(RadixBuffer& buffer, double number, unsigned radix)
 {
@@ -339,6 +339,32 @@
     return startOfResultString;
 }
 
+static UString toUStringWithRadix(int32_t number, unsigned radix)
+{
+    LChar buf[1 + 32]; // Worst case is radix == 2, which gives us 32 digits + sign.
+    LChar* end = buf + WTF_ARRAY_LENGTH(buf);
+    LChar* p = end;
+
+    bool negative = false;
+    uint32_t positiveNumber = number;
+    if (number < 0) {
+        negative = true;
+        positiveNumber = -number;
+    }
+
+    while (positiveNumber) {
+        uint32_t index = positiveNumber % radix;
+        ASSERT(index >= 0);
+        ASSERT(index < sizeof(radixDigits));
+        *--p = static_cast<LChar>(radixDigits[index]);
+        positiveNumber /= radix;
+    }
+    if (negative)
+        *--p = '-';
+
+    return UString(p, static_cast<unsigned>(end - p));
+}
+
 // toExponential converts a number to a string, always formatting as an expoential.
 // This method takes an optional argument specifying a number of *decimal places*
 // to round the significand to (or, put another way, this method optionally rounds
@@ -431,40 +457,63 @@
     return JSValue::encode(jsString(exec, UString(numberToFixedPrecisionString(x, significantFigures, buffer))));
 }
 
-EncodedJSValue JSC_HOST_CALL numberProtoFuncToString(ExecState* exec)
+static inline int32_t extractRadixFromArgs(ExecState* exec)
 {
-    double x;
-    if (!toThisNumber(exec->hostThisValue(), x))
-        return throwVMTypeError(exec);
-
     JSValue radixValue = exec->argument(0);
-    int radix;
+    int32_t radix;
     if (radixValue.isInt32())
         radix = radixValue.asInt32();
     else if (radixValue.isUndefined())
         radix = 10;
     else
-        radix = static_cast<int>(radixValue.toInteger(exec)); // nan -> 0
+        radix = static_cast<int32_t>(radixValue.toInteger(exec)); // nan -> 0
 
+    return radix;
+}
+
+static inline EncodedJSValue integerValueToString(ExecState* exec, int32_t radix, int32_t value)
+{
+    // 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);
+        JSGlobalData* globalData = &exec->globalData();
+        return JSValue::encode(globalData->smallStrings.singleCharacterString(globalData, radixDigits[value]));
+    }
+
+    if (radix == 10) {
+        JSGlobalData* globalData = &exec->globalData();
+        return JSValue::encode(jsString(globalData, globalData->numericStrings.add(value)));
+    }
+
+    return JSValue::encode(jsString(exec, toUStringWithRadix(value, radix)));
+
+}
+
+EncodedJSValue JSC_HOST_CALL numberProtoFuncToString(ExecState* exec)
+{
+    double doubleValue;
+    if (!toThisNumber(exec->hostThisValue(), doubleValue))
+        return throwVMTypeError(exec);
+
+    int32_t radix = extractRadixFromArgs(exec);
     if (radix < 2 || radix > 36)
         return throwVMError(exec, createRangeError(exec, "toString() radix argument must be between 2 and 36"));
 
-    // Fast path for number to character conversion.
-    unsigned c = static_cast<unsigned>(x);
-    unsigned unsignedRadix = static_cast<unsigned>(radix);
-    if (c == x && c < unsignedRadix) {
+    int32_t integerValue = static_cast<int32_t>(doubleValue);
+    if (integerValue == doubleValue)
+        return integerValueToString(exec, radix, integerValue);
+
+    if (radix == 10) {
         JSGlobalData* globalData = &exec->globalData();
-        return JSValue::encode(globalData->smallStrings.singleCharacterString(globalData, radixDigits[c]));
+        return JSValue::encode(jsString(globalData, globalData->numericStrings.add(doubleValue)));
     }
 
-    if (radix == 10)
-        return JSValue::encode(jsNumber(x).toString(exec));
+    if (!isfinite(doubleValue))
+        return JSValue::encode(jsString(exec, UString::number(doubleValue)));
 
-    if (!isfinite(x))
-        return JSValue::encode(jsString(exec, UString::number(x)));
-
     RadixBuffer s;
-    return JSValue::encode(jsString(exec, toStringWithRadix(s, x, unsignedRadix)));
+    return JSValue::encode(jsString(exec, toStringWithRadix(s, doubleValue, radix)));
 }
 
 EncodedJSValue JSC_HOST_CALL numberProtoFuncToLocaleString(ExecState* exec)
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to