Add support for Math.imul
authoroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 26 Apr 2013 00:41:38 +0000 (00:41 +0000)
committeroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 26 Apr 2013 00:41:38 +0000 (00:41 +0000)
https://bugs.webkit.org/show_bug.cgi?id=115143

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

Add support for Math.imul, a thunk generator for Math.imul,
and an intrinsic.

Fairly self explanatory set of changes, DFG intrinsics simply
leverages the existing ValueToInt32 nodes.

* create_hash_table:
* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::executeEffects):
* dfg/DFGBackwardsPropagationPhase.cpp:
(JSC::DFG::BackwardsPropagationPhase::propagate):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleIntrinsic):
* dfg/DFGCSEPhase.cpp:
(JSC::DFG::CSEPhase::performNodeCSE):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGNodeType.h:
(DFG):
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileArithIMul):
* dfg/DFGSpeculativeJIT.h:
(SpeculativeJIT):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* jit/ThunkGenerators.cpp:
(JSC::imulThunkGenerator):
(JSC):
* jit/ThunkGenerators.h:
(JSC):
* runtime/Intrinsic.h:
* runtime/MathObject.cpp:
(JSC):
(JSC::mathProtoFuncIMul):
* runtime/VM.cpp:
(JSC::thunkGeneratorForIntrinsic):

LayoutTests:

Add a bunch of tests for Math.imul

* fast/js/Object-getOwnPropertyNames-expected.txt:
* fast/js/imul-expected.txt: Added.
* fast/js/imul.html: Added.
* fast/js/regress/imul-double-only-expected.txt: Added.
* fast/js/regress/imul-double-only.html: Added.
* fast/js/regress/imul-int-only-expected.txt: Added.
* fast/js/regress/imul-int-only.html: Added.
* fast/js/regress/imul-mixed-expected.txt: Added.
* fast/js/regress/imul-mixed.html: Added.
* fast/js/regress/script-tests/imul-double-only.js: Added.
(f):
* fast/js/regress/script-tests/imul-int-only.js: Added.
(f):
* fast/js/regress/script-tests/imul-mixed.js: Added.
(f):
* fast/js/script-tests/Object-getOwnPropertyNames.js:
* fast/js/script-tests/imul.js: Added.
(testIMul):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@149159 268f45cc-cd09-0410-ab3c-d52691b4dbfc

33 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/js/Object-getOwnPropertyNames-expected.txt
LayoutTests/fast/js/imul-expected.txt [new file with mode: 0644]
LayoutTests/fast/js/imul.html [new file with mode: 0644]
LayoutTests/fast/js/regress/imul-double-only-expected.txt [new file with mode: 0644]
LayoutTests/fast/js/regress/imul-double-only.html [new file with mode: 0644]
LayoutTests/fast/js/regress/imul-int-only-expected.txt [new file with mode: 0644]
LayoutTests/fast/js/regress/imul-int-only.html [new file with mode: 0644]
LayoutTests/fast/js/regress/imul-mixed-expected.txt [new file with mode: 0644]
LayoutTests/fast/js/regress/imul-mixed.html [new file with mode: 0644]
LayoutTests/fast/js/regress/script-tests/imul-double-only.js [new file with mode: 0644]
LayoutTests/fast/js/regress/script-tests/imul-int-only.js [new file with mode: 0644]
LayoutTests/fast/js/regress/script-tests/imul-mixed.js [new file with mode: 0644]
LayoutTests/fast/js/script-tests/Object-getOwnPropertyNames.js
LayoutTests/fast/js/script-tests/imul.js [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/create_hash_table
Source/JavaScriptCore/dfg/DFGAbstractState.cpp
Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
Source/JavaScriptCore/dfg/DFGNodeType.h
Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
Source/JavaScriptCore/jit/ThunkGenerators.cpp
Source/JavaScriptCore/jit/ThunkGenerators.h
Source/JavaScriptCore/runtime/Intrinsic.h
Source/JavaScriptCore/runtime/MathObject.cpp
Source/JavaScriptCore/runtime/VM.cpp

index 7a1ba2e..d67571f 100644 (file)
@@ -1,3 +1,31 @@
+2013-04-24  Oliver Hunt  <oliver@apple.com>
+
+        Add support for Math.imul
+        https://bugs.webkit.org/show_bug.cgi?id=115143
+
+        Reviewed by Filip Pizlo.
+
+        Add a bunch of tests for Math.imul
+
+        * fast/js/Object-getOwnPropertyNames-expected.txt:
+        * fast/js/imul-expected.txt: Added.
+        * fast/js/imul.html: Added.
+        * fast/js/regress/imul-double-only-expected.txt: Added.
+        * fast/js/regress/imul-double-only.html: Added.
+        * fast/js/regress/imul-int-only-expected.txt: Added.
+        * fast/js/regress/imul-int-only.html: Added.
+        * fast/js/regress/imul-mixed-expected.txt: Added.
+        * fast/js/regress/imul-mixed.html: Added.
+        * fast/js/regress/script-tests/imul-double-only.js: Added.
+        (f):
+        * fast/js/regress/script-tests/imul-int-only.js: Added.
+        (f):
+        * fast/js/regress/script-tests/imul-mixed.js: Added.
+        (f):
+        * fast/js/script-tests/Object-getOwnPropertyNames.js:
+        * fast/js/script-tests/imul.js: Added.
+        (testIMul):
+
 2013-04-25  Chris Fleizach  <cfleizach@apple.com>
 
         <meter> element not exposed to accessibility
index 892062b..4814eb7 100644 (file)
@@ -58,7 +58,7 @@ PASS getSortedOwnPropertyNames(RegExp) is ['$&', "$'", '$*', '$+', '$1', '$2', '
 PASS getSortedOwnPropertyNames(RegExp.prototype) is ['compile', 'constructor', 'exec', 'global', 'ignoreCase', 'lastIndex', 'multiline', 'source', 'test', 'toString']
 PASS getSortedOwnPropertyNames(Error) is ['length', 'name', 'prototype']
 PASS getSortedOwnPropertyNames(Error.prototype) is ['constructor', 'message', 'name', 'toString']
-PASS getSortedOwnPropertyNames(Math) is ['E', 'LN10', 'LN2', 'LOG10E', 'LOG2E', 'PI', 'SQRT1_2', 'SQRT2', 'abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'random', 'round', 'sin', 'sqrt', 'tan']
+PASS getSortedOwnPropertyNames(Math) is ['E', 'LN10', 'LN2', 'LOG10E', 'LOG2E', 'PI', 'SQRT1_2', 'SQRT2', 'abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'imul', 'log', 'max', 'min', 'pow', 'random', 'round', 'sin', 'sqrt', 'tan']
 PASS getSortedOwnPropertyNames(JSON) is ['parse', 'stringify']
 PASS globalPropertyNames.indexOf('NaN') != -1 is true
 PASS globalPropertyNames.indexOf('Infinity') != -1 is true
diff --git a/LayoutTests/fast/js/imul-expected.txt b/LayoutTests/fast/js/imul-expected.txt
new file mode 100644 (file)
index 0000000..b0d2164
--- /dev/null
@@ -0,0 +1,53 @@
+Test Math.imul behaviour
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Math.imul(1, 0.5) is 0
+PASS Math.imul(1, -0.5) is 0
+PASS Math.imul(2, 1<<30) is -2147483648
+PASS Math.imul(4, 1<<30) is 0
+PASS Math.imul(1, NaN) is 0
+PASS Math.imul(1, Infinity) is 0
+PASS Math.imul({valueOf:function(){throw 'left'}},{valueOf:function(){throw 'right'}}) threw exception left.
+PASS Math.imul(0.5, 1) is 0
+PASS Math.imul(-0.5, 1) is 0
+PASS Math.imul(1<<30, 2) is -2147483648
+PASS Math.imul(1<<30, 4) is 0
+PASS Math.imul(NaN, 1) is 0
+PASS Math.imul(Infinity, 1) is 0
+PASS Math.imul(NaN, NaN) is 0
+PASS Math.imul(Infinity, Infinity) is 0
+PASS Math.imul(Infinity, -Infinity) is 0
+PASS Math.imul(-Infinity, Infinity) is 0
+PASS Math.imul(-Infinity, -Infinity) is 0
+PASS testIMul(2,2,10000) is 40000
+PASS testIMul(2.5,2,10000) is 40000
+PASS testIMul(2,2.5,10000) is 40000
+PASS testIMul(2.5,2.5,10000) is 40000
+PASS testIMul(2.5,2.5,10000) is 40000
+PASS testIMul(-2,-2,10000) is 40000
+PASS testIMul(-2.5,-2,10000) is 40000
+PASS testIMul(-2,-2.5,10000) is 40000
+PASS testIMul(-2.5,-2.5,10000) is 40000
+PASS testIMul(-2.5,-2.5,10000) is 40000
+PASS testIMul(-2,2,10000) is -40000
+PASS testIMul(-2.5,2,10000) is -40000
+PASS testIMul(-2,2.5,10000) is -40000
+PASS testIMul(-2.5,2.5,10000) is -40000
+PASS testIMul(-2.5,2.5,10000) is -40000
+PASS testIMul(2,-2,10000) is -40000
+PASS testIMul(2.5,-2,10000) is -40000
+PASS testIMul(2,-2.5,10000) is -40000
+PASS testIMul(2.5,-2.5,10000) is -40000
+PASS testIMul(2.5,-2.5,10000) is -40000
+PASS testIMul(NaN, 1, 10000) is 0
+PASS testIMul(Infinity, 1, 10000) is 0
+PASS testIMul(1e40, 1, 10000) is 0
+PASS testIMul(1, NaN, 10000) is 0
+PASS testIMul(1, Infinity, 10000) is 0
+PASS testIMul(1, 1e40, 10000) is 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/js/imul.html b/LayoutTests/fast/js/imul.html
new file mode 100644 (file)
index 0000000..64c9da1
--- /dev/null
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="script-tests/imul.js"></script>
+<script src="resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/js/regress/imul-double-only-expected.txt b/LayoutTests/fast/js/regress/imul-double-only-expected.txt
new file mode 100644 (file)
index 0000000..a0727b6
--- /dev/null
@@ -0,0 +1,10 @@
+JSRegress/imul-double-only
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/js/regress/imul-double-only.html b/LayoutTests/fast/js/regress/imul-double-only.html
new file mode 100644 (file)
index 0000000..2c80e8e
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="resources/regress-pre.js"></script>
+<script src="script-tests/imul-double-only.js"></script>
+<script src="resources/regress-post.js"></script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/js/regress/imul-int-only-expected.txt b/LayoutTests/fast/js/regress/imul-int-only-expected.txt
new file mode 100644 (file)
index 0000000..7270147
--- /dev/null
@@ -0,0 +1,10 @@
+JSRegress/imul-int-only
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/js/regress/imul-int-only.html b/LayoutTests/fast/js/regress/imul-int-only.html
new file mode 100644 (file)
index 0000000..83b54ee
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="resources/regress-pre.js"></script>
+<script src="script-tests/imul-int-only.js"></script>
+<script src="resources/regress-post.js"></script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/js/regress/imul-mixed-expected.txt b/LayoutTests/fast/js/regress/imul-mixed-expected.txt
new file mode 100644 (file)
index 0000000..4d124be
--- /dev/null
@@ -0,0 +1,10 @@
+JSRegress/imul-mixed
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/js/regress/imul-mixed.html b/LayoutTests/fast/js/regress/imul-mixed.html
new file mode 100644 (file)
index 0000000..9298bd4
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="resources/regress-pre.js"></script>
+<script src="script-tests/imul-mixed.js"></script>
+<script src="resources/regress-post.js"></script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/js/regress/script-tests/imul-double-only.js b/LayoutTests/fast/js/regress/script-tests/imul-double-only.js
new file mode 100644 (file)
index 0000000..40d38c5
--- /dev/null
@@ -0,0 +1,12 @@
+function f(a,b) {
+    var result = 0;
+    for (var i = 0; i < 10000; i++)
+        result = (result + Math.imul(a,b)) | 0
+    return result;
+}
+var result = 0;
+for (var i = 0.5; i < 10000; i++)
+    result = result ^ f(i, i);
+
+if (result != -375267328) 
+    throw "Bad result: " + result;
diff --git a/LayoutTests/fast/js/regress/script-tests/imul-int-only.js b/LayoutTests/fast/js/regress/script-tests/imul-int-only.js
new file mode 100644 (file)
index 0000000..4213655
--- /dev/null
@@ -0,0 +1,12 @@
+function f(a,b) {
+    var result = 0;
+    for (var i = 0; i < 10000; i++)
+        result = (result + Math.imul(a,b)) | 0
+    return result;
+}
+var result = 0;
+for (var i = 0; i < 10000; i++)
+    result = result ^ f(i + 1, i)
+
+if (result != 1656994304) 
+    throw "Bad result: " + result;
diff --git a/LayoutTests/fast/js/regress/script-tests/imul-mixed.js b/LayoutTests/fast/js/regress/script-tests/imul-mixed.js
new file mode 100644 (file)
index 0000000..e1466a2
--- /dev/null
@@ -0,0 +1,12 @@
+function f(a,b) {
+    var result = 0;
+    for (var i = 0; i < 10000; i++)
+        result = (result + Math.imul(a,b)) | 0
+    return result;
+}
+var result = 0;
+for (var i = 0; i < 10000; i++)
+    result = result + f(result | 1, i+0.5) ^ f(i+1.3, result | 1);
+
+if (result != -420098048) 
+    throw "Bad result: " + result;
\ No newline at end of file
index daea97c..43df417 100644 (file)
@@ -66,7 +66,7 @@ var expectedPropertyNamesSet = {
     "RegExp.prototype": "['compile', 'constructor', 'exec', 'global', 'ignoreCase', 'lastIndex', 'multiline', 'source', 'test', 'toString']",
     "Error": "['length', 'name', 'prototype']",
     "Error.prototype": "['constructor', 'message', 'name', 'toString']",
-    "Math": "['E', 'LN10', 'LN2', 'LOG10E', 'LOG2E', 'PI', 'SQRT1_2', 'SQRT2', 'abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'random', 'round', 'sin', 'sqrt', 'tan']",
+    "Math": "['E', 'LN10', 'LN2', 'LOG10E', 'LOG2E', 'PI', 'SQRT1_2', 'SQRT2', 'abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'imul', 'log', 'max', 'min', 'pow', 'random', 'round', 'sin', 'sqrt', 'tan']",
     "JSON": "['parse', 'stringify']"
 };
 
diff --git a/LayoutTests/fast/js/script-tests/imul.js b/LayoutTests/fast/js/script-tests/imul.js
new file mode 100644 (file)
index 0000000..1385ce6
--- /dev/null
@@ -0,0 +1,64 @@
+description("Test Math.imul behaviour");
+
+shouldBe("Math.imul(1, 0.5)", "0");
+shouldBe("Math.imul(1, -0.5)", "0");
+shouldBe("Math.imul(2, 1<<30)", "-2147483648");
+shouldBe("Math.imul(4, 1<<30)", "0");
+shouldBe("Math.imul(1, NaN)", "0");
+shouldBe("Math.imul(1, Infinity)", "0");
+
+shouldThrow("Math.imul({valueOf:function(){throw 'left'}},{valueOf:function(){throw 'right'}})", "'left'");
+
+shouldBe("Math.imul(0.5, 1)", "0");
+shouldBe("Math.imul(-0.5, 1)", "0");
+shouldBe("Math.imul(1<<30, 2)", "-2147483648");
+shouldBe("Math.imul(1<<30, 4)", "0");
+shouldBe("Math.imul(NaN, 1)", "0");
+shouldBe("Math.imul(Infinity, 1)", "0");
+shouldBe("Math.imul(NaN, NaN)", "0");
+shouldBe("Math.imul(Infinity, Infinity)", "0");
+shouldBe("Math.imul(Infinity, -Infinity)", "0");
+shouldBe("Math.imul(-Infinity, Infinity)", "0");
+shouldBe("Math.imul(-Infinity, -Infinity)", "0");
+
+function testIMul(left, right, count)
+{
+    var result = 0;
+    for (var i = 0; i < count; i++)
+        result += Math.imul(left, right);
+    return result;
+}
+
+shouldBe("testIMul(2,2,10000)", "40000")
+shouldBe("testIMul(2.5,2,10000)", "40000")
+shouldBe("testIMul(2,2.5,10000)", "40000")
+shouldBe("testIMul(2.5,2.5,10000)", "40000")
+shouldBe("testIMul(2.5,2.5,10000)", "40000")
+shouldBe("testIMul(-2,-2,10000)", "40000")
+shouldBe("testIMul(-2.5,-2,10000)", "40000")
+shouldBe("testIMul(-2,-2.5,10000)", "40000")
+shouldBe("testIMul(-2.5,-2.5,10000)", "40000")
+shouldBe("testIMul(-2.5,-2.5,10000)", "40000")
+
+shouldBe("testIMul(-2,2,10000)", "-40000")
+shouldBe("testIMul(-2.5,2,10000)", "-40000")
+shouldBe("testIMul(-2,2.5,10000)", "-40000")
+shouldBe("testIMul(-2.5,2.5,10000)", "-40000")
+shouldBe("testIMul(-2.5,2.5,10000)", "-40000")
+
+
+shouldBe("testIMul(2,-2,10000)", "-40000")
+shouldBe("testIMul(2.5,-2,10000)", "-40000")
+shouldBe("testIMul(2,-2.5,10000)", "-40000")
+shouldBe("testIMul(2.5,-2.5,10000)", "-40000")
+shouldBe("testIMul(2.5,-2.5,10000)", "-40000")
+
+
+shouldBe("testIMul(NaN, 1, 10000)", "0")
+shouldBe("testIMul(Infinity, 1, 10000)", "0")
+shouldBe("testIMul(1e40, 1, 10000)", "0")
+shouldBe("testIMul(1, NaN, 10000)", "0")
+shouldBe("testIMul(1, Infinity, 10000)", "0")
+shouldBe("testIMul(1, 1e40, 10000)", "0")
+
+successfullyParsed = true;
index b87fba9..52d72f1 100644 (file)
@@ -1,3 +1,51 @@
+2013-04-24  Oliver Hunt  <oliver@apple.com>
+
+        Add support for Math.imul
+        https://bugs.webkit.org/show_bug.cgi?id=115143
+
+        Reviewed by Filip Pizlo.
+
+        Add support for Math.imul, a thunk generator for Math.imul,
+        and an intrinsic.
+
+        Fairly self explanatory set of changes, DFG intrinsics simply
+        leverages the existing ValueToInt32 nodes.
+
+        * create_hash_table:
+        * dfg/DFGAbstractState.cpp:
+        (JSC::DFG::AbstractState::executeEffects):
+        * dfg/DFGBackwardsPropagationPhase.cpp:
+        (JSC::DFG::BackwardsPropagationPhase::propagate):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::handleIntrinsic):
+        * dfg/DFGCSEPhase.cpp:
+        (JSC::DFG::CSEPhase::performNodeCSE):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGNodeType.h:
+        (DFG):
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        (JSC::DFG::PredictionPropagationPhase::propagate):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileArithIMul):
+        * dfg/DFGSpeculativeJIT.h:
+        (SpeculativeJIT):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * jit/ThunkGenerators.cpp:
+        (JSC::imulThunkGenerator):
+        (JSC):
+        * jit/ThunkGenerators.h:
+        (JSC):
+        * runtime/Intrinsic.h:
+        * runtime/MathObject.cpp:
+        (JSC):
+        (JSC::mathProtoFuncIMul):
+        * runtime/VM.cpp:
+        (JSC::thunkGeneratorForIntrinsic):
+
 2013-04-25  Filip Pizlo  <fpizlo@apple.com>
 
         Unreviewed, roll out http://trac.webkit.org/changeset/148999
index 875018c..1bd531a 100755 (executable)
@@ -283,6 +283,7 @@ sub output() {
             $intrinsic = "RoundIntrinsic" if ($key eq "round");
             $intrinsic = "ExpIntrinsic" if ($key eq "exp");
             $intrinsic = "LogIntrinsic" if ($key eq "log");
+            $intrinsic = "IMulIntrinsic" if ($key eq "imul");
         }
         if ($name eq "arrayPrototypeTable") {
             $intrinsic = "ArrayPushIntrinsic" if ($key eq "push");
index d598685..76e69ee 100644 (file)
@@ -428,7 +428,7 @@ bool AbstractState::executeEffects(unsigned indexInBlock, Node* node)
         forNode(node).set(SpecInt32);
         break;
     }
-        
+
     case Int32ToDouble:
     case ForwardInt32ToDouble: {
         JSValue child = forNode(node->child1()).value();
@@ -555,6 +555,11 @@ bool AbstractState::executeEffects(unsigned indexInBlock, Node* node)
         }
         break;
     }
+
+    case ArithIMul: {
+        forNode(node).set(SpecInt32);
+        break;
+    }
         
     case ArithDiv:
     case ArithMin:
index 5e2b10f..2f06646 100644 (file)
@@ -192,7 +192,8 @@ private:
         case BitXor:
         case BitRShift:
         case BitLShift:
-        case BitURShift: {
+        case BitURShift:
+        case ArithIMul: {
             flags |= NodeUsedAsInt;
             flags &= ~(NodeUsedAsNumber | NodeNeedsNegZero | NodeUsedAsOther);
             node->child1()->mergeFlags(flags);
index 98ea8fa..58c9ccf 100644 (file)
@@ -1600,6 +1600,17 @@ bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrins
         
         return true;
     }
+
+    case IMulIntrinsic: {
+        if (argumentCountIncludingThis != 3)
+            return false;
+        int leftOperand = registerOffset + argumentToOperand(1);
+        int rightOperand = registerOffset + argumentToOperand(2);
+        Node* left = getToInt32(leftOperand);
+        Node* right = getToInt32(rightOperand);
+        setIntrinsicResult(usesResult, resultOperand, addToGraph(ArithIMul, left, right));
+        return true;
+    }
         
     default:
         return false;
index 2c8cc50..47af696 100644 (file)
@@ -1059,6 +1059,7 @@ private:
         case ArithSub:
         case ArithNegate:
         case ArithMul:
+        case ArithIMul:
         case ArithMod:
         case ArithDiv:
         case ArithAbs:
index a0bfca8..3af1b58 100644 (file)
@@ -100,7 +100,8 @@ private:
         case BitXor:
         case BitRShift:
         case BitLShift:
-        case BitURShift: {
+        case BitURShift:
+        case ArithIMul: {
             fixIntEdge(node->child1());
             fixIntEdge(node->child2());
             break;
index 6ef9542..29d7e0a 100644 (file)
@@ -105,6 +105,7 @@ namespace JSC { namespace DFG {
     macro(ArithSub, NodeResultNumber | NodeMustGenerate) \
     macro(ArithNegate, NodeResultNumber | NodeMustGenerate) \
     macro(ArithMul, NodeResultNumber | NodeMustGenerate) \
+    macro(ArithIMul, NodeResultInt32 | NodeMustGenerate) \
     macro(ArithDiv, NodeResultNumber | NodeMustGenerate) \
     macro(ArithMod, NodeResultNumber | NodeMustGenerate) \
     macro(ArithAbs, NodeResultNumber | NodeMustGenerate) \
index 3377f26..63a135b 100644 (file)
@@ -164,7 +164,8 @@ private:
         case BitXor:
         case BitRShift:
         case BitLShift:
-        case BitURShift: {
+        case BitURShift:
+        case ArithIMul: {
             changed |= setPrediction(SpecInt32);
             break;
         }
index b6c5907..4337e80 100644 (file)
@@ -3332,6 +3332,20 @@ void SpeculativeJIT::compileArithNegate(Node* node)
         return;
     }
 }
+void SpeculativeJIT::compileArithIMul(Node* node)
+{
+    SpeculateIntegerOperand op1(this, node->child1());
+    SpeculateIntegerOperand op2(this, node->child2());
+    GPRTemporary result(this);
+
+    GPRReg reg1 = op1.gpr();
+    GPRReg reg2 = op2.gpr();
+
+    m_jit.move(reg1, result.gpr());
+    m_jit.mul32(reg2, result.gpr());
+    integerResult(result.gpr(), node);
+    return;
+}
 
 void SpeculativeJIT::compileArithMul(Node* node)
 {
index 82679d0..6d1defa 100644 (file)
@@ -1968,6 +1968,7 @@ public:
     void compileArithSub(Node*);
     void compileArithNegate(Node*);
     void compileArithMul(Node*);
+    void compileArithIMul(Node*);
 #if CPU(X86) || CPU(X86_64)
     void compileIntegerArithDivForX86(Node*);
 #elif CPU(APPLE_ARMV7S)
index 172afee..3595753 100644 (file)
@@ -2244,6 +2244,10 @@ void SpeculativeJIT::compile(Node* node)
         compileArithMul(node);
         break;
 
+    case ArithIMul:
+        compileArithIMul(node);
+        break;
+
     case ArithDiv: {
         switch (node->binaryUseKind()) {
         case Int32Use: {
index e7a7791..8044049 100644 (file)
@@ -2182,6 +2182,10 @@ void SpeculativeJIT::compile(Node* node)
         compileArithMul(node);
         break;
 
+    case ArithIMul:
+        compileArithIMul(node);
+        break;
+
     case ArithDiv: {
         switch (node->binaryUseKind()) {
         case Int32Use: {
index 8490fd7..a450789 100644 (file)
@@ -768,6 +768,39 @@ MacroAssemblerCodeRef powThunkGenerator(VM* vm)
     return jit.finalize(*vm, vm->jitStubs->ctiNativeCall(vm), "pow");
 }
 
+MacroAssemblerCodeRef imulThunkGenerator(VM* vm)
+{
+    SpecializedThunkJIT jit(2);
+    MacroAssembler::Jump nonIntArg0Jump;
+    jit.loadInt32Argument(0, SpecializedThunkJIT::regT0, nonIntArg0Jump);
+    SpecializedThunkJIT::Label doneLoadingArg0(&jit);
+    MacroAssembler::Jump nonIntArg1Jump;
+    jit.loadInt32Argument(1, SpecializedThunkJIT::regT1, nonIntArg1Jump);
+    SpecializedThunkJIT::Label doneLoadingArg1(&jit);
+    jit.mul32(SpecializedThunkJIT::regT1, SpecializedThunkJIT::regT0);
+    jit.returnInt32(SpecializedThunkJIT::regT0);
+
+    if (jit.supportsFloatingPointTruncate()) {
+        nonIntArg0Jump.link(&jit);
+        jit.loadDoubleArgument(0, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0);
+        jit.branchTruncateDoubleToInt32(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT0, SpecializedThunkJIT::BranchIfTruncateSuccessful).linkTo(doneLoadingArg0, &jit);
+        jit.xor32(SpecializedThunkJIT::regT0, SpecializedThunkJIT::regT0);
+        jit.jump(doneLoadingArg0);
+    } else
+        jit.appendFailure(nonIntArg0Jump);
+
+    if (jit.supportsFloatingPointTruncate()) {
+        nonIntArg1Jump.link(&jit);
+        jit.loadDoubleArgument(1, SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT1);
+        jit.branchTruncateDoubleToInt32(SpecializedThunkJIT::fpRegT0, SpecializedThunkJIT::regT1, SpecializedThunkJIT::BranchIfTruncateSuccessful).linkTo(doneLoadingArg1, &jit);
+        jit.xor32(SpecializedThunkJIT::regT1, SpecializedThunkJIT::regT1);
+        jit.jump(doneLoadingArg1);
+    } else
+        jit.appendFailure(nonIntArg1Jump);
+
+    return jit.finalize(*vm, vm->jitStubs->ctiNativeCall(vm), "imul");
+}
+
 }
 
 #endif // ENABLE(JIT)
index f01c427..a4b0fc4 100644 (file)
@@ -51,6 +51,7 @@ MacroAssemblerCodeRef logThunkGenerator(VM*);
 MacroAssemblerCodeRef roundThunkGenerator(VM*);
 MacroAssemblerCodeRef sqrtThunkGenerator(VM*);
 MacroAssemblerCodeRef powThunkGenerator(VM*);
+MacroAssemblerCodeRef imulThunkGenerator(VM*);
 
 }
 #endif // ENABLE(JIT)
index 76fb92a..313826e 100644 (file)
@@ -47,7 +47,8 @@ enum Intrinsic {
     LogIntrinsic,
     RegExpExecIntrinsic,
     RegExpTestIntrinsic,
-    StringPrototypeValueOfIntrinsic
+    StringPrototypeValueOfIntrinsic,
+    IMulIntrinsic
 };
 
 } // namespace JSC
index 6e467dc..71c53a3 100644 (file)
@@ -52,6 +52,7 @@ static EncodedJSValue JSC_HOST_CALL mathProtoFuncRound(ExecState*);
 static EncodedJSValue JSC_HOST_CALL mathProtoFuncSin(ExecState*);
 static EncodedJSValue JSC_HOST_CALL mathProtoFuncSqrt(ExecState*);
 static EncodedJSValue JSC_HOST_CALL mathProtoFuncTan(ExecState*);
+static EncodedJSValue JSC_HOST_CALL mathProtoFuncIMul(ExecState*);
 
 }
 
@@ -81,6 +82,7 @@ const ClassInfo MathObject::s_info = { "Math", &Base::s_info, 0, ExecState::math
   sin           mathProtoFuncSin               DontEnum|Function 1
   sqrt          mathProtoFuncSqrt              DontEnum|Function 1
   tan           mathProtoFuncTan               DontEnum|Function 1
+  imul          mathProtoFuncIMul              DontEnum|Function 2
 @end
 */
 
@@ -278,6 +280,15 @@ EncodedJSValue JSC_HOST_CALL mathProtoFuncTan(ExecState* exec)
     return JSValue::encode(jsDoubleNumber(tan(exec->argument(0).toNumber(exec))));
 }
 
+EncodedJSValue JSC_HOST_CALL mathProtoFuncIMul(ExecState* exec)
+{
+    int32_t left = exec->argument(0).toInt32(exec);
+    if (exec->hadException())
+        return JSValue::encode(jsNull());
+    int32_t right = exec->argument(1).toInt32(exec);
+    return JSValue::encode(jsNumber(left * right));
+}
+
 #if PLATFORM(IOS) && CPU(ARM_THUMB2)
 
 // The following code is taken from netlib.org:
index 95b6527..b352063 100644 (file)
@@ -395,6 +395,8 @@ static ThunkGenerator thunkGeneratorForIntrinsic(Intrinsic intrinsic)
         return expThunkGenerator;
     case LogIntrinsic:
         return logThunkGenerator;
+    case IMulIntrinsic:
+        return imulThunkGenerator;
     default:
         return 0;
     }