Diff
Modified: trunk/LayoutTests/ChangeLog (194112 => 194113)
--- trunk/LayoutTests/ChangeLog 2015-12-15 20:36:15 UTC (rev 194112)
+++ trunk/LayoutTests/ChangeLog 2015-12-15 21:19:31 UTC (rev 194113)
@@ -1,3 +1,41 @@
+2015-12-15 Mark Lam <mark....@apple.com>
+
+ Polymorphic operand types for DFG and FTL bit operators.
+ https://bugs.webkit.org/show_bug.cgi?id=152191
+
+ Reviewed by Saam Barati.
+
+ * js/regress/ftl-polymorphic-bitand-expected.txt: Added.
+ * js/regress/ftl-polymorphic-bitand.html: Added.
+ * js/regress/ftl-polymorphic-bitor-expected.txt: Added.
+ * js/regress/ftl-polymorphic-bitor.html: Added.
+ * js/regress/ftl-polymorphic-bitxor-expected.txt: Added.
+ * js/regress/ftl-polymorphic-bitxor.html: Added.
+ * js/regress/ftl-polymorphic-lshift-expected.txt: Added.
+ * js/regress/ftl-polymorphic-lshift.html: Added.
+ * js/regress/ftl-polymorphic-rshift-expected.txt: Added.
+ * js/regress/ftl-polymorphic-rshift.html: Added.
+ * js/regress/ftl-polymorphic-urshift-expected.txt: Added.
+ * js/regress/ftl-polymorphic-urshift.html: Added.
+ * js/regress/script-tests/ftl-polymorphic-bitand.js: Added.
+ (o1.valueOf):
+ (foo):
+ * js/regress/script-tests/ftl-polymorphic-bitor.js: Added.
+ (o1.valueOf):
+ (foo):
+ * js/regress/script-tests/ftl-polymorphic-bitxor.js: Added.
+ (o1.valueOf):
+ (foo):
+ * js/regress/script-tests/ftl-polymorphic-lshift.js: Added.
+ (o1.valueOf):
+ (foo):
+ * js/regress/script-tests/ftl-polymorphic-rshift.js: Added.
+ (o1.valueOf):
+ (foo):
+ * js/regress/script-tests/ftl-polymorphic-urshift.js: Added.
+ (o1.valueOf):
+ (foo):
+
2015-12-15 Adam Bergkvist <adam.bergkv...@ericsson.com>
WebRTC: Test that RTCPeerConnection promise functions reject on closed state
Added: trunk/LayoutTests/js/regress/ftl-polymorphic-bitand-expected.txt (0 => 194113)
--- trunk/LayoutTests/js/regress/ftl-polymorphic-bitand-expected.txt (rev 0)
+++ trunk/LayoutTests/js/regress/ftl-polymorphic-bitand-expected.txt 2015-12-15 21:19:31 UTC (rev 194113)
@@ -0,0 +1,10 @@
+JSRegress/ftl-polymorphic-bitand
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/js/regress/ftl-polymorphic-bitand.html (0 => 194113)
--- trunk/LayoutTests/js/regress/ftl-polymorphic-bitand.html (rev 0)
+++ trunk/LayoutTests/js/regress/ftl-polymorphic-bitand.html 2015-12-15 21:19:31 UTC (rev 194113)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/js/regress/ftl-polymorphic-bitor-expected.txt (0 => 194113)
--- trunk/LayoutTests/js/regress/ftl-polymorphic-bitor-expected.txt (rev 0)
+++ trunk/LayoutTests/js/regress/ftl-polymorphic-bitor-expected.txt 2015-12-15 21:19:31 UTC (rev 194113)
@@ -0,0 +1,10 @@
+JSRegress/ftl-polymorphic-bitor
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/js/regress/ftl-polymorphic-bitor.html (0 => 194113)
--- trunk/LayoutTests/js/regress/ftl-polymorphic-bitor.html (rev 0)
+++ trunk/LayoutTests/js/regress/ftl-polymorphic-bitor.html 2015-12-15 21:19:31 UTC (rev 194113)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/js/regress/ftl-polymorphic-bitxor-expected.txt (0 => 194113)
--- trunk/LayoutTests/js/regress/ftl-polymorphic-bitxor-expected.txt (rev 0)
+++ trunk/LayoutTests/js/regress/ftl-polymorphic-bitxor-expected.txt 2015-12-15 21:19:31 UTC (rev 194113)
@@ -0,0 +1,10 @@
+JSRegress/ftl-polymorphic-bitxor
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/js/regress/ftl-polymorphic-bitxor.html (0 => 194113)
--- trunk/LayoutTests/js/regress/ftl-polymorphic-bitxor.html (rev 0)
+++ trunk/LayoutTests/js/regress/ftl-polymorphic-bitxor.html 2015-12-15 21:19:31 UTC (rev 194113)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/js/regress/ftl-polymorphic-lshift-expected.txt (0 => 194113)
--- trunk/LayoutTests/js/regress/ftl-polymorphic-lshift-expected.txt (rev 0)
+++ trunk/LayoutTests/js/regress/ftl-polymorphic-lshift-expected.txt 2015-12-15 21:19:31 UTC (rev 194113)
@@ -0,0 +1,10 @@
+JSRegress/ftl-polymorphic-lshift
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/js/regress/ftl-polymorphic-lshift.html (0 => 194113)
--- trunk/LayoutTests/js/regress/ftl-polymorphic-lshift.html (rev 0)
+++ trunk/LayoutTests/js/regress/ftl-polymorphic-lshift.html 2015-12-15 21:19:31 UTC (rev 194113)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/js/regress/ftl-polymorphic-rshift-expected.txt (0 => 194113)
--- trunk/LayoutTests/js/regress/ftl-polymorphic-rshift-expected.txt (rev 0)
+++ trunk/LayoutTests/js/regress/ftl-polymorphic-rshift-expected.txt 2015-12-15 21:19:31 UTC (rev 194113)
@@ -0,0 +1,10 @@
+JSRegress/ftl-polymorphic-rshift
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/js/regress/ftl-polymorphic-rshift.html (0 => 194113)
--- trunk/LayoutTests/js/regress/ftl-polymorphic-rshift.html (rev 0)
+++ trunk/LayoutTests/js/regress/ftl-polymorphic-rshift.html 2015-12-15 21:19:31 UTC (rev 194113)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/js/regress/ftl-polymorphic-urshift-expected.txt (0 => 194113)
--- trunk/LayoutTests/js/regress/ftl-polymorphic-urshift-expected.txt (rev 0)
+++ trunk/LayoutTests/js/regress/ftl-polymorphic-urshift-expected.txt 2015-12-15 21:19:31 UTC (rev 194113)
@@ -0,0 +1,10 @@
+JSRegress/ftl-polymorphic-urshift
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/js/regress/ftl-polymorphic-urshift.html (0 => 194113)
--- trunk/LayoutTests/js/regress/ftl-polymorphic-urshift.html (rev 0)
+++ trunk/LayoutTests/js/regress/ftl-polymorphic-urshift.html 2015-12-15 21:19:31 UTC (rev 194113)
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/js/regress/script-tests/ftl-polymorphic-bitand.js (0 => 194113)
--- trunk/LayoutTests/js/regress/script-tests/ftl-polymorphic-bitand.js (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/ftl-polymorphic-bitand.js 2015-12-15 21:19:31 UTC (rev 194113)
@@ -0,0 +1,42 @@
+//@ runFTLNoCJIT
+var o1 = {
+ i: 0,
+ valueOf: function() { return this.i; }
+};
+
+result = 0;
+function foo(a, b) {
+ var result = 0;
+ for (var j = 0; j < 10; j++) {
+ var temp;
+ if (a > b)
+ temp = a & b;
+ else
+ temp = b & 1;
+ result += temp;
+ }
+ for (var i = 0; i < 1000; i++)
+ result += i;
+ return result;
+}
+noInline(foo);
+
+var iterations;
+var expectedResult;
+if (this.window) {
+ // The layout test doesn't like too many iterations and may time out.
+ iterations = 10000;
+ expectedResult = 4995999180;
+} else {
+ iterations = 100000;
+ expectedResult = 49955499180;
+}
+
+
+for (var i = 0; i <= iterations; i++) {
+ o1.i = i + 2;
+ result += foo(o1, 10);
+}
+
+if (result != expectedResult)
+ throw "Bad result: " + result;
Added: trunk/LayoutTests/js/regress/script-tests/ftl-polymorphic-bitor.js (0 => 194113)
--- trunk/LayoutTests/js/regress/script-tests/ftl-polymorphic-bitor.js (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/ftl-polymorphic-bitor.js 2015-12-15 21:19:31 UTC (rev 194113)
@@ -0,0 +1,42 @@
+//@ runFTLNoCJIT
+var o1 = {
+ i: 0,
+ valueOf: function() { return this.i; }
+};
+
+result = 0;
+function foo(a, b) {
+ var result = 0;
+ for (var j = 0; j < 10; j++) {
+ var temp;
+ if (a > b)
+ temp = a | b;
+ else
+ temp = b | 1;
+ result += temp;
+ }
+ for (var i = 0; i < 1000; i++)
+ result += i;
+ return result;
+}
+noInline(foo);
+
+var iterations;
+var expectedResult;
+if (this.window) {
+ // The layout test doesn't like too many iterations and may time out.
+ iterations = 10000;
+ expectedResult = 5496249490;
+} else {
+ iterations = 100000;
+ expectedResult = 99957999490;
+}
+
+
+for (var i = 0; i <= iterations; i++) {
+ o1.i = i + 2;
+ result += foo(o1, 10);
+}
+
+if (result != expectedResult)
+ throw "Bad result: " + result;
Added: trunk/LayoutTests/js/regress/script-tests/ftl-polymorphic-bitxor.js (0 => 194113)
--- trunk/LayoutTests/js/regress/script-tests/ftl-polymorphic-bitxor.js (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/ftl-polymorphic-bitxor.js 2015-12-15 21:19:31 UTC (rev 194113)
@@ -0,0 +1,42 @@
+//@ runFTLNoCJIT
+var o1 = {
+ i: 0,
+ valueOf: function() { return this.i; }
+};
+
+result = 0;
+function foo(a, b) {
+ var result = 0;
+ for (var j = 0; j < 10; j++) {
+ var temp;
+ if (a > b)
+ temp = a ^ b;
+ else
+ temp = b ^ 1;
+ result += temp;
+ }
+ for (var i = 0; i < 1000; i++)
+ result += i;
+ return result;
+}
+noInline(foo);
+
+var iterations;
+var expectedResult;
+if (this.window) {
+ // The layout test doesn't like too many iterations and may time out.
+ iterations = 10000;
+ expectedResult = 5495749810;
+} else {
+ iterations = 100000;
+ expectedResult = 99952999810;
+}
+
+
+for (var i = 0; i <= iterations; i++) {
+ o1.i = i + 2;
+ result += foo(o1, 10);
+}
+
+if (result != expectedResult)
+ throw "Bad result: " + result;
Added: trunk/LayoutTests/js/regress/script-tests/ftl-polymorphic-lshift.js (0 => 194113)
--- trunk/LayoutTests/js/regress/script-tests/ftl-polymorphic-lshift.js (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/ftl-polymorphic-lshift.js 2015-12-15 21:19:31 UTC (rev 194113)
@@ -0,0 +1,42 @@
+//@ runFTLNoCJIT
+var o1 = {
+ i: 0,
+ valueOf: function() { return this.i; }
+};
+
+result = 0;
+function foo(a, b) {
+ var result = 0;
+ for (var j = 0; j < 10; j++) {
+ var temp;
+ if (a > b)
+ temp = a << b;
+ else
+ temp = b << 1;
+ result += temp;
+ }
+ for (var i = 0; i < 1000; i++)
+ result += i;
+ return result;
+}
+noInline(foo);
+
+var iterations;
+var expectedResult;
+if (this.window) {
+ // The layout test doesn't like too many iterations and may time out.
+ iterations = 10000;
+ expectedResult = 517250968820;
+} else {
+ iterations = 100000;
+ expectedResult = 51252509968820;
+}
+
+
+for (var i = 0; i <= iterations; i++) {
+ o1.i = i + 2;
+ result += foo(o1, 10);
+}
+
+if (result != expectedResult)
+ throw "Bad result: " + result;
Added: trunk/LayoutTests/js/regress/script-tests/ftl-polymorphic-rshift.js (0 => 194113)
--- trunk/LayoutTests/js/regress/script-tests/ftl-polymorphic-rshift.js (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/ftl-polymorphic-rshift.js 2015-12-15 21:19:31 UTC (rev 194113)
@@ -0,0 +1,42 @@
+//@ runFTLNoCJIT
+var o1 = {
+ i: 0,
+ valueOf: function() { return this.i; }
+};
+
+result = 0;
+function foo(a, b) {
+ var result = 0;
+ for (var j = 0; j < 10; j++) {
+ var temp;
+ if (a > b)
+ temp = a >> b;
+ else
+ temp = b >> 1;
+ result += temp;
+ }
+ for (var i = 0; i < 1000; i++)
+ result += i;
+ return result;
+}
+noInline(foo);
+
+var iterations;
+var expectedResult;
+if (this.window) {
+ // The layout test doesn't like too many iterations and may time out.
+ iterations = 10000;
+ expectedResult = 4995939420;
+} else {
+ iterations = 100000;
+ expectedResult = 49998832140;
+}
+
+
+for (var i = 0; i <= iterations; i++) {
+ o1.i = i + 2;
+ result += foo(o1, 10);
+}
+
+if (result != expectedResult)
+ throw "Bad result: " + result;
Added: trunk/LayoutTests/js/regress/script-tests/ftl-polymorphic-urshift.js (0 => 194113)
--- trunk/LayoutTests/js/regress/script-tests/ftl-polymorphic-urshift.js (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/ftl-polymorphic-urshift.js 2015-12-15 21:19:31 UTC (rev 194113)
@@ -0,0 +1,42 @@
+//@ runFTLNoCJIT
+var o1 = {
+ i: 0,
+ valueOf: function() { return this.i; }
+};
+
+result = 0;
+function foo(a, b) {
+ var result = 0;
+ for (var j = 0; j < 10; j++) {
+ var temp;
+ if (a > b)
+ temp = a >>> b;
+ else
+ temp = b >>> 1;
+ result += temp;
+ }
+ for (var i = 0; i < 1000; i++)
+ result += i;
+ return result;
+}
+noInline(foo);
+
+var iterations;
+var expectedResult;
+if (this.window) {
+ // The layout test doesn't like too many iterations and may time out.
+ iterations = 10000;
+ expectedResult = 4995939420;
+} else {
+ iterations = 100000;
+ expectedResult = 49998832140;
+}
+
+
+for (var i = 0; i <= iterations; i++) {
+ o1.i = i + 2;
+ result += foo(o1, 10);
+}
+
+if (result != expectedResult)
+ throw "Bad result: " + result;
Modified: trunk/Source/_javascript_Core/ChangeLog (194112 => 194113)
--- trunk/Source/_javascript_Core/ChangeLog 2015-12-15 20:36:15 UTC (rev 194112)
+++ trunk/Source/_javascript_Core/ChangeLog 2015-12-15 21:19:31 UTC (rev 194113)
@@ -1,3 +1,126 @@
+2015-12-15 Mark Lam <mark....@apple.com>
+
+ Polymorphic operand types for DFG and FTL bit operators.
+ https://bugs.webkit.org/show_bug.cgi?id=152191
+
+ Reviewed by Saam Barati.
+
+ * bytecode/SpeculatedType.h:
+ (JSC::isUntypedSpeculationForBitOps):
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::shouldSpeculateUntypedForBitOps):
+ - Added check for types not supported by ValueToInt32, and therefore should be
+ treated as untyped for bitops.
+
+ * dfg/DFGClobberize.h:
+ (JSC::DFG::clobberize):
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::fixupNode):
+ - Handled untyped operands.
+
+ * dfg/DFGOperations.cpp:
+ * dfg/DFGOperations.h:
+ - Added DFG slow path functions for bitops.
+
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::emitUntypedBitOp):
+ (JSC::DFG::SpeculativeJIT::compileBitwiseOp):
+ (JSC::DFG::SpeculativeJIT::emitUntypedRightShiftBitOp):
+ (JSC::DFG::SpeculativeJIT::compileShiftOp):
+ * dfg/DFGSpeculativeJIT.h:
+ - Added DFG backend support untyped operands for bitops.
+
+ * dfg/DFGStrengthReductionPhase.cpp:
+ (JSC::DFG::StrengthReductionPhase::handleNode):
+ - Limit bitops strength reduction only to when we don't have untyped operands.
+ This is because values that are not int32s need to be converted to int32.
+ Without untyped operands, the ValueToInt32 node takes care of this.
+ With untyped operands, we cannot use ValueToInt32, and need to do the conversion
+ in the code emitted for the bitop node itself. For example:
+
+ 5.5 | 0; // yields 5 because ValueToInt32 converts the 5.5 to a 5.
+ "abc" | 0; // would yield "abc" instead of the expected 0 if we let
+ // strength reduction do its thing.
+
+ * ftl/FTLCompileBinaryOp.cpp:
+ (JSC::FTL::generateBinaryBitOpFastPath):
+ (JSC::FTL::generateRightShiftFastPath):
+ (JSC::FTL::generateBinaryOpFastPath):
+
+ * ftl/FTLInlineCacheDescriptor.h:
+ (JSC::FTL::BitAndDescriptor::BitAndDescriptor):
+ (JSC::FTL::BitAndDescriptor::icSize):
+ (JSC::FTL::BitAndDescriptor::nodeType):
+ (JSC::FTL::BitAndDescriptor::opName):
+ (JSC::FTL::BitAndDescriptor::slowPathFunction):
+ (JSC::FTL::BitAndDescriptor::nonNumberSlowPathFunction):
+ (JSC::FTL::BitOrDescriptor::BitOrDescriptor):
+ (JSC::FTL::BitOrDescriptor::icSize):
+ (JSC::FTL::BitOrDescriptor::nodeType):
+ (JSC::FTL::BitOrDescriptor::opName):
+ (JSC::FTL::BitOrDescriptor::slowPathFunction):
+ (JSC::FTL::BitOrDescriptor::nonNumberSlowPathFunction):
+ (JSC::FTL::BitXorDescriptor::BitXorDescriptor):
+ (JSC::FTL::BitXorDescriptor::icSize):
+ (JSC::FTL::BitXorDescriptor::nodeType):
+ (JSC::FTL::BitXorDescriptor::opName):
+ (JSC::FTL::BitXorDescriptor::slowPathFunction):
+ (JSC::FTL::BitXorDescriptor::nonNumberSlowPathFunction):
+ (JSC::FTL::BitLShiftDescriptor::BitLShiftDescriptor):
+ (JSC::FTL::BitLShiftDescriptor::icSize):
+ (JSC::FTL::BitLShiftDescriptor::nodeType):
+ (JSC::FTL::BitLShiftDescriptor::opName):
+ (JSC::FTL::BitLShiftDescriptor::slowPathFunction):
+ (JSC::FTL::BitLShiftDescriptor::nonNumberSlowPathFunction):
+ (JSC::FTL::BitRShiftDescriptor::BitRShiftDescriptor):
+ (JSC::FTL::BitRShiftDescriptor::icSize):
+ (JSC::FTL::BitRShiftDescriptor::nodeType):
+ (JSC::FTL::BitRShiftDescriptor::opName):
+ (JSC::FTL::BitRShiftDescriptor::slowPathFunction):
+ (JSC::FTL::BitRShiftDescriptor::nonNumberSlowPathFunction):
+ (JSC::FTL::BitURShiftDescriptor::BitURShiftDescriptor):
+ (JSC::FTL::BitURShiftDescriptor::icSize):
+ (JSC::FTL::BitURShiftDescriptor::nodeType):
+ (JSC::FTL::BitURShiftDescriptor::opName):
+ (JSC::FTL::BitURShiftDescriptor::slowPathFunction):
+ (JSC::FTL::BitURShiftDescriptor::nonNumberSlowPathFunction):
+ - Added support for bitop ICs.
+
+ * ftl/FTLInlineCacheSize.cpp:
+ (JSC::FTL::sizeOfBitAnd):
+ (JSC::FTL::sizeOfBitOr):
+ (JSC::FTL::sizeOfBitXor):
+ (JSC::FTL::sizeOfBitLShift):
+ (JSC::FTL::sizeOfBitRShift):
+ (JSC::FTL::sizeOfBitURShift):
+ * ftl/FTLInlineCacheSize.h:
+ - Added new bitop IC sizes. These are just estimates for now that work adequately,
+ and are shown to not impact performance on benchmarks. We will re-tune these
+ sizes values later in another patch once all snippet ICs have been added.
+
+ * ftl/FTLLowerDFGToLLVM.cpp:
+ (JSC::FTL::DFG::LowerDFGToLLVM::compileBitAnd):
+ (JSC::FTL::DFG::LowerDFGToLLVM::compileBitOr):
+ (JSC::FTL::DFG::LowerDFGToLLVM::compileBitXor):
+ (JSC::FTL::DFG::LowerDFGToLLVM::compileBitRShift):
+ (JSC::FTL::DFG::LowerDFGToLLVM::compileBitLShift):
+ (JSC::FTL::DFG::LowerDFGToLLVM::compileBitURShift):
+ - Added support for bitop ICs.
+
+ * jit/JITLeftShiftGenerator.cpp:
+ (JSC::JITLeftShiftGenerator::generateFastPath):
+ * jit/JITLeftShiftGenerator.h:
+ (JSC::JITLeftShiftGenerator::JITLeftShiftGenerator):
+ * jit/JITRightShiftGenerator.cpp:
+ (JSC::JITRightShiftGenerator::generateFastPath):
+ - The shift MASM operatons need to ensure that the shiftAmount is not in the same
+ register as the destination register. With the baselineJIT and DFG, this is
+ ensured in how we allocate these registers, and hence, the bug does not manifest.
+ With the FTL, these registers are not guaranteed to be unique. Hence, we need
+ to fix the shift op snippet code to compensate for this.
+
2015-12-15 Caitlin Potter <ca...@igalia.com>
[JSC] SyntaxError if AssignmentElement is `eval` or `arguments` in strict code
@@ -1605,7 +1728,6 @@
(JSC::ArrayPrototype::finishCreation):
* runtime/CommonIdentifiers.h:
->>>>>>> .r193940
2015-12-08 Filip Pizlo <fpi...@apple.com>
FTL B3 should have basic GetById support
Modified: trunk/Source/_javascript_Core/bytecode/SpeculatedType.h (194112 => 194113)
--- trunk/Source/_javascript_Core/bytecode/SpeculatedType.h 2015-12-15 20:36:15 UTC (rev 194112)
+++ trunk/Source/_javascript_Core/bytecode/SpeculatedType.h 2015-12-15 21:19:31 UTC (rev 194113)
@@ -390,6 +390,11 @@
return !(value & (SpecFullNumber | SpecBoolean));
}
+inline bool isUntypedSpeculationForBitOps(SpeculatedType value)
+{
+ return !(value & (SpecFullNumber | SpecBoolean | SpecOther));
+}
+
void dumpSpeculation(PrintStream&, SpeculatedType);
void dumpSpeculationAbbreviated(PrintStream&, SpeculatedType);
Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (194112 => 194113)
--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2015-12-15 20:36:15 UTC (rev 194112)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2015-12-15 21:19:31 UTC (rev 194113)
@@ -233,6 +233,12 @@
case BitRShift:
case BitLShift:
case BitURShift: {
+ if (node->child1().useKind() == UntypedUse || node->child2().useKind() == UntypedUse) {
+ clobberWorld(node->origin.semantic, clobberLimit);
+ forNode(node).setType(m_graph, SpecInt32);
+ break;
+ }
+
JSValue left = forNode(node->child1()).value();
JSValue right = forNode(node->child2()).value();
if (left && right && left.isInt32() && right.isInt32()) {
Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (194112 => 194113)
--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2015-12-15 20:36:15 UTC (rev 194112)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2015-12-15 21:19:31 UTC (rev 194113)
@@ -121,12 +121,6 @@
case CheckStructureImmediate:
return;
- case BitAnd:
- case BitOr:
- case BitXor:
- case BitLShift:
- case BitRShift:
- case BitURShift:
case ArithIMul:
case ArithAbs:
case ArithClz32:
@@ -164,6 +158,20 @@
def(PureValue(node));
return;
+ case BitAnd:
+ case BitOr:
+ case BitXor:
+ case BitLShift:
+ case BitRShift:
+ case BitURShift:
+ if (node->child1().useKind() == UntypedUse || node->child2().useKind() == UntypedUse) {
+ read(World);
+ write(Heap);
+ return;
+ }
+ def(PureValue(node));
+ return;
+
case ArithRandom:
read(MathDotRandomState);
write(MathDotRandomState);
Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (194112 => 194113)
--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2015-12-15 20:36:15 UTC (rev 194112)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2015-12-15 21:19:31 UTC (rev 194113)
@@ -105,6 +105,12 @@
case BitRShift:
case BitLShift:
case BitURShift: {
+ if (Node::shouldSpeculateUntypedForBitOps(node->child1().node(), node->child2().node())
+ && m_graph.hasExitSite(node->origin.semantic, BadType)) {
+ fixEdge<UntypedUse>(node->child1());
+ fixEdge<UntypedUse>(node->child2());
+ break;
+ }
fixIntConvertingEdge(node->child1());
fixIntConvertingEdge(node->child2());
break;
Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (194112 => 194113)
--- trunk/Source/_javascript_Core/dfg/DFGNode.h 2015-12-15 20:36:15 UTC (rev 194112)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h 2015-12-15 21:19:31 UTC (rev 194113)
@@ -2033,6 +2033,16 @@
return op1->shouldSpeculateUntypedForArithmetic() || op2->shouldSpeculateUntypedForArithmetic();
}
+ bool shouldSpeculateUntypedForBitOps()
+ {
+ return isUntypedSpeculationForBitOps(prediction());
+ }
+
+ static bool shouldSpeculateUntypedForBitOps(Node* op1, Node* op2)
+ {
+ return op1->shouldSpeculateUntypedForBitOps() || op2->shouldSpeculateUntypedForBitOps();
+ }
+
static bool shouldSpeculateBoolean(Node* op1, Node* op2)
{
return op1->shouldSpeculateBoolean() && op2->shouldSpeculateBoolean();
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (194112 => 194113)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2015-12-15 20:36:15 UTC (rev 194112)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2015-12-15 21:19:31 UTC (rev 194113)
@@ -173,6 +173,84 @@
return constructEmptyObject(exec, jsCast<JSFunction*>(constructor)->rareData(exec, inlineCapacity)->allocationProfile()->structure());
}
+EncodedJSValue JIT_OPERATION operationValueBitAnd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+{
+ VM* vm = &exec->vm();
+ NativeCallFrameTracer tracer(vm, exec);
+
+ JSValue op1 = JSValue::decode(encodedOp1);
+ JSValue op2 = JSValue::decode(encodedOp2);
+
+ int32_t a = op1.toInt32(exec);
+ int32_t b = op2.toInt32(exec);
+ return JSValue::encode(jsNumber(a & b));
+}
+
+EncodedJSValue JIT_OPERATION operationValueBitOr(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+{
+ VM* vm = &exec->vm();
+ NativeCallFrameTracer tracer(vm, exec);
+
+ JSValue op1 = JSValue::decode(encodedOp1);
+ JSValue op2 = JSValue::decode(encodedOp2);
+
+ int32_t a = op1.toInt32(exec);
+ int32_t b = op2.toInt32(exec);
+ return JSValue::encode(jsNumber(a | b));
+}
+
+EncodedJSValue JIT_OPERATION operationValueBitXor(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+{
+ VM* vm = &exec->vm();
+ NativeCallFrameTracer tracer(vm, exec);
+
+ JSValue op1 = JSValue::decode(encodedOp1);
+ JSValue op2 = JSValue::decode(encodedOp2);
+
+ int32_t a = op1.toInt32(exec);
+ int32_t b = op2.toInt32(exec);
+ return JSValue::encode(jsNumber(a ^ b));
+}
+
+EncodedJSValue JIT_OPERATION operationValueBitLShift(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+{
+ VM* vm = &exec->vm();
+ NativeCallFrameTracer tracer(vm, exec);
+
+ JSValue op1 = JSValue::decode(encodedOp1);
+ JSValue op2 = JSValue::decode(encodedOp2);
+
+ int32_t a = op1.toInt32(exec);
+ uint32_t b = op2.toUInt32(exec);
+ return JSValue::encode(jsNumber(a << (b & 0x1f)));
+}
+
+EncodedJSValue JIT_OPERATION operationValueBitRShift(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+{
+ VM* vm = &exec->vm();
+ NativeCallFrameTracer tracer(vm, exec);
+
+ JSValue op1 = JSValue::decode(encodedOp1);
+ JSValue op2 = JSValue::decode(encodedOp2);
+
+ int32_t a = op1.toInt32(exec);
+ uint32_t b = op2.toUInt32(exec);
+ return JSValue::encode(jsNumber(a >> (b & 0x1f)));
+}
+
+EncodedJSValue JIT_OPERATION operationValueBitURShift(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
+{
+ VM* vm = &exec->vm();
+ NativeCallFrameTracer tracer(vm, exec);
+
+ JSValue op1 = JSValue::decode(encodedOp1);
+ JSValue op2 = JSValue::decode(encodedOp2);
+
+ uint32_t a = op1.toUInt32(exec);
+ uint32_t b = op2.toUInt32(exec);
+ return JSValue::encode(jsNumber(static_cast<int32_t>(a >> (b & 0x1f))));
+}
+
EncodedJSValue JIT_OPERATION operationValueAdd(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
{
VM* vm = &exec->vm();
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (194112 => 194113)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.h 2015-12-15 20:36:15 UTC (rev 194112)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h 2015-12-15 21:19:31 UTC (rev 194113)
@@ -43,6 +43,12 @@
JSCell* JIT_OPERATION operationCreateThis(ExecState*, JSObject* constructor, int32_t inlineCapacity) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationToThis(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationToThisStrict(ExecState*, EncodedJSValue encodedOp1) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationValueBitAnd(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationValueBitOr(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationValueBitXor(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationValueBitLShift(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationValueBitRShift(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationValueBitURShift(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationValueAdd(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationValueAddNotNumber(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
EncodedJSValue JIT_OPERATION operationValueDiv(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2) WTF_INTERNAL;
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (194112 => 194113)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2015-12-15 20:36:15 UTC (rev 194112)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2015-12-15 21:19:31 UTC (rev 194113)
@@ -39,8 +39,13 @@
#include "DFGSlowPathGenerator.h"
#include "DirectArguments.h"
#include "JITAddGenerator.h"
+#include "JITBitAndGenerator.h"
+#include "JITBitOrGenerator.h"
+#include "JITBitXorGenerator.h"
#include "JITDivGenerator.h"
+#include "JITLeftShiftGenerator.h"
#include "JITMulGenerator.h"
+#include "JITRightShiftGenerator.h"
#include "JITSubGenerator.h"
#include "JSArrowFunction.h"
#include "JSCInlines.h"
@@ -2786,12 +2791,120 @@
blessedBooleanResult(scratchReg, node);
}
+template<typename SnippetGenerator, J_JITOperation_EJJ snippetSlowPathFunction>
+void SpeculativeJIT::emitUntypedBitOp(Node* node)
+{
+ Edge& leftChild = node->child1();
+ Edge& rightChild = node->child2();
+
+ if (isKnownNotNumber(leftChild.node()) || isKnownNotNumber(rightChild.node())) {
+ JSValueOperand left(this, leftChild);
+ JSValueOperand right(this, rightChild);
+ JSValueRegs leftRegs = left.jsValueRegs();
+ JSValueRegs rightRegs = right.jsValueRegs();
+#if USE(JSVALUE64)
+ GPRTemporary result(this);
+ JSValueRegs resultRegs = JSValueRegs(result.gpr());
+#else
+ GPRTemporary resultTag(this);
+ GPRTemporary resultPayload(this);
+ JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
+#endif
+ flushRegisters();
+ callOperation(snippetSlowPathFunction, resultRegs, leftRegs, rightRegs);
+ m_jit.exceptionCheck();
+
+ jsValueResult(resultRegs, node);
+ return;
+ }
+
+ Optional<JSValueOperand> left;
+ Optional<JSValueOperand> right;
+
+ JSValueRegs leftRegs;
+ JSValueRegs rightRegs;
+
+#if USE(JSVALUE64)
+ GPRTemporary result(this);
+ JSValueRegs resultRegs = JSValueRegs(result.gpr());
+ GPRTemporary scratch(this);
+ GPRReg scratchGPR = scratch.gpr();
+#else
+ GPRTemporary resultTag(this);
+ GPRTemporary resultPayload(this);
+ JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
+ GPRReg scratchGPR = resultTag.gpr();
+#endif
+
+ SnippetOperand leftOperand;
+ SnippetOperand rightOperand;
+
+ // The snippet generator does not support both operands being constant. If the left
+ // operand is already const, we'll ignore the right operand's constness.
+ if (leftChild->isInt32Constant())
+ leftOperand.setConstInt32(leftChild->asInt32());
+ else if (rightChild->isInt32Constant())
+ rightOperand.setConstInt32(rightChild->asInt32());
+
+ RELEASE_ASSERT(!leftOperand.isConst() || !rightOperand.isConst());
+
+ if (!leftOperand.isConst()) {
+ left = JSValueOperand(this, leftChild);
+ leftRegs = left->jsValueRegs();
+ }
+ if (!rightOperand.isConst()) {
+ right = JSValueOperand(this, rightChild);
+ rightRegs = right->jsValueRegs();
+ }
+
+ SnippetGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs, scratchGPR);
+ gen.generateFastPath(m_jit);
+
+ ASSERT(gen.didEmitFastPath());
+ gen.endJumpList().append(m_jit.jump());
+
+ gen.slowPathJumpList().link(&m_jit);
+ silentSpillAllRegisters(resultRegs);
+
+ if (leftOperand.isConst()) {
+ leftRegs = resultRegs;
+ m_jit.moveValue(leftChild->asJSValue(), leftRegs);
+ } else if (rightOperand.isConst()) {
+ rightRegs = resultRegs;
+ m_jit.moveValue(rightChild->asJSValue(), rightRegs);
+ }
+
+ callOperation(snippetSlowPathFunction, resultRegs, leftRegs, rightRegs);
+
+ silentFillAllRegisters(resultRegs);
+ m_jit.exceptionCheck();
+
+ gen.endJumpList().link(&m_jit);
+ jsValueResult(resultRegs, node);
+}
+
void SpeculativeJIT::compileBitwiseOp(Node* node)
{
NodeType op = node->op();
Edge& leftChild = node->child1();
Edge& rightChild = node->child2();
+ if (leftChild.useKind() == UntypedUse || rightChild.useKind() == UntypedUse) {
+ switch (op) {
+ case BitAnd:
+ emitUntypedBitOp<JITBitAndGenerator, operationValueBitAnd>(node);
+ return;
+ case BitOr:
+ emitUntypedBitOp<JITBitOrGenerator, operationValueBitOr>(node);
+ return;
+ case BitXor:
+ emitUntypedBitOp<JITBitXorGenerator, operationValueBitXor>(node);
+ return;
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ }
+ }
+
if (leftChild->isInt32Constant()) {
SpeculateInt32Operand op2(this, rightChild);
GPRTemporary result(this, Reuse, op2);
@@ -2821,12 +2934,130 @@
}
}
+void SpeculativeJIT::emitUntypedRightShiftBitOp(Node* node)
+{
+ J_JITOperation_EJJ snippetSlowPathFunction = node->op() == BitRShift
+ ? operationValueBitRShift : operationValueBitURShift;
+ JITRightShiftGenerator::ShiftType shiftType = node->op() == BitRShift
+ ? JITRightShiftGenerator::SignedShift : JITRightShiftGenerator::UnsignedShift;
+
+ Edge& leftChild = node->child1();
+ Edge& rightChild = node->child2();
+
+ if (isKnownNotNumber(leftChild.node()) || isKnownNotNumber(rightChild.node())) {
+ JSValueOperand left(this, leftChild);
+ JSValueOperand right(this, rightChild);
+ JSValueRegs leftRegs = left.jsValueRegs();
+ JSValueRegs rightRegs = right.jsValueRegs();
+#if USE(JSVALUE64)
+ GPRTemporary result(this);
+ JSValueRegs resultRegs = JSValueRegs(result.gpr());
+#else
+ GPRTemporary resultTag(this);
+ GPRTemporary resultPayload(this);
+ JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
+#endif
+ flushRegisters();
+ callOperation(snippetSlowPathFunction, resultRegs, leftRegs, rightRegs);
+ m_jit.exceptionCheck();
+
+ jsValueResult(resultRegs, node);
+ return;
+ }
+
+ Optional<JSValueOperand> left;
+ Optional<JSValueOperand> right;
+
+ JSValueRegs leftRegs;
+ JSValueRegs rightRegs;
+
+ FPRTemporary leftNumber(this);
+ FPRReg leftFPR = leftNumber.fpr();
+
+#if USE(JSVALUE64)
+ GPRTemporary result(this);
+ JSValueRegs resultRegs = JSValueRegs(result.gpr());
+ GPRTemporary scratch(this);
+ GPRReg scratchGPR = scratch.gpr();
+ FPRReg scratchFPR = InvalidFPRReg;
+#else
+ GPRTemporary resultTag(this);
+ GPRTemporary resultPayload(this);
+ JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
+ GPRReg scratchGPR = resultTag.gpr();
+ FPRTemporary fprScratch(this);
+ FPRReg scratchFPR = fprScratch.fpr();
+#endif
+
+ SnippetOperand leftOperand;
+ SnippetOperand rightOperand;
+
+ // The snippet generator does not support both operands being constant. If the left
+ // operand is already const, we'll ignore the right operand's constness.
+ if (leftChild->isInt32Constant())
+ leftOperand.setConstInt32(leftChild->asInt32());
+ else if (rightChild->isInt32Constant())
+ rightOperand.setConstInt32(rightChild->asInt32());
+
+ RELEASE_ASSERT(!leftOperand.isConst() || !rightOperand.isConst());
+
+ if (!leftOperand.isConst()) {
+ left = JSValueOperand(this, leftChild);
+ leftRegs = left->jsValueRegs();
+ }
+ if (!rightOperand.isConst()) {
+ right = JSValueOperand(this, rightChild);
+ rightRegs = right->jsValueRegs();
+ }
+
+ JITRightShiftGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs,
+ leftFPR, scratchGPR, scratchFPR, shiftType);
+ gen.generateFastPath(m_jit);
+
+ ASSERT(gen.didEmitFastPath());
+ gen.endJumpList().append(m_jit.jump());
+
+ gen.slowPathJumpList().link(&m_jit);
+ silentSpillAllRegisters(resultRegs);
+
+ if (leftOperand.isConst()) {
+ leftRegs = resultRegs;
+ m_jit.moveValue(leftChild->asJSValue(), leftRegs);
+ } else if (rightOperand.isConst()) {
+ rightRegs = resultRegs;
+ m_jit.moveValue(rightChild->asJSValue(), rightRegs);
+ }
+
+ callOperation(snippetSlowPathFunction, resultRegs, leftRegs, rightRegs);
+
+ silentFillAllRegisters(resultRegs);
+ m_jit.exceptionCheck();
+
+ gen.endJumpList().link(&m_jit);
+ jsValueResult(resultRegs, node);
+ return;
+}
+
void SpeculativeJIT::compileShiftOp(Node* node)
{
NodeType op = node->op();
Edge& leftChild = node->child1();
Edge& rightChild = node->child2();
+ if (leftChild.useKind() == UntypedUse || rightChild.useKind() == UntypedUse) {
+ switch (op) {
+ case BitLShift:
+ emitUntypedBitOp<JITLeftShiftGenerator, operationValueBitLShift>(node);
+ return;
+ case BitRShift:
+ case BitURShift:
+ emitUntypedRightShiftBitOp(node);
+ return;
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ }
+ }
+
if (rightChild->isInt32Constant()) {
SpeculateInt32Operand op1(this, leftChild);
GPRTemporary result(this, Reuse, op1);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (194112 => 194113)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2015-12-15 20:36:15 UTC (rev 194112)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2015-12-15 21:19:31 UTC (rev 194113)
@@ -2217,8 +2217,14 @@
void compileValueToInt32(Node*);
void compileUInt32ToNumber(Node*);
void compileDoubleAsInt32(Node*);
+
+ template<typename SnippetGenerator, J_JITOperation_EJJ slowPathFunction>
+ void emitUntypedBitOp(Node*);
void compileBitwiseOp(Node*);
+
+ void emitUntypedRightShiftBitOp(Node*);
void compileShiftOp(Node*);
+
void compileValueAdd(Node*);
void compileArithAdd(Node*);
void compileMakeRope(Node*);
Modified: trunk/Source/_javascript_Core/dfg/DFGStrengthReductionPhase.cpp (194112 => 194113)
--- trunk/Source/_javascript_Core/dfg/DFGStrengthReductionPhase.cpp 2015-12-15 20:36:15 UTC (rev 194112)
+++ trunk/Source/_javascript_Core/dfg/DFGStrengthReductionPhase.cpp 2015-12-15 21:19:31 UTC (rev 194113)
@@ -74,7 +74,7 @@
case BitOr:
handleCommutativity();
- if (m_node->child2()->isInt32Constant() && !m_node->child2()->asInt32()) {
+ if (m_node->child1().useKind() != UntypedUse && m_node->child2()->isInt32Constant() && !m_node->child2()->asInt32()) {
convertToIdentityOverChild1();
break;
}
@@ -88,7 +88,7 @@
case BitLShift:
case BitRShift:
case BitURShift:
- if (m_node->child2()->isInt32Constant() && !(m_node->child2()->asInt32() & 0x1f)) {
+ if (m_node->child1().useKind() != UntypedUse && m_node->child2()->isInt32Constant() && !(m_node->child2()->asInt32() & 0x1f)) {
convertToIdentityOverChild1();
break;
}
Modified: trunk/Source/_javascript_Core/ftl/FTLCompileBinaryOp.cpp (194112 => 194113)
--- trunk/Source/_javascript_Core/ftl/FTLCompileBinaryOp.cpp 2015-12-15 20:36:15 UTC (rev 194112)
+++ trunk/Source/_javascript_Core/ftl/FTLCompileBinaryOp.cpp 2015-12-15 21:19:31 UTC (rev 194113)
@@ -32,8 +32,13 @@
#include "FTLInlineCacheDescriptor.h"
#include "GPRInfo.h"
#include "JITAddGenerator.h"
+#include "JITBitAndGenerator.h"
+#include "JITBitOrGenerator.h"
+#include "JITBitXorGenerator.h"
#include "JITDivGenerator.h"
+#include "JITLeftShiftGenerator.h"
#include "JITMulGenerator.h"
+#include "JITRightShiftGenerator.h"
#include "JITSubGenerator.h"
#include "ScratchRegisterAllocator.h"
@@ -159,6 +164,76 @@
NeedScratchFPR
};
+template<typename SnippetGenerator>
+void generateBinaryBitOpFastPath(BinaryOpDescriptor& ic, CCallHelpers& jit,
+ GPRReg result, GPRReg left, GPRReg right, RegisterSet usedRegisters,
+ CCallHelpers::Jump& done, CCallHelpers::Jump& slowPathStart)
+{
+ ScratchRegisterAllocator allocator(usedRegisters);
+
+ BinarySnippetRegisterContext context(allocator, result, left, right);
+
+ GPRReg scratchGPR = allocator.allocateScratchGPR();
+
+ SnippetGenerator gen(ic.leftOperand(), ic.rightOperand(), JSValueRegs(result),
+ JSValueRegs(left), JSValueRegs(right), scratchGPR);
+
+ unsigned numberOfBytesUsedToPreserveReusedRegisters =
+ allocator.preserveReusedRegistersByPushing(jit, ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
+
+ context.initializeRegisters(jit);
+ gen.generateFastPath(jit);
+
+ ASSERT(gen.didEmitFastPath());
+ gen.endJumpList().link(&jit);
+
+ context.restoreRegisters(jit);
+ allocator.restoreReusedRegistersByPopping(jit, numberOfBytesUsedToPreserveReusedRegisters,
+ ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
+ done = jit.jump();
+
+ gen.slowPathJumpList().link(&jit);
+ context.restoreRegisters(jit);
+ allocator.restoreReusedRegistersByPopping(jit, numberOfBytesUsedToPreserveReusedRegisters,
+ ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
+ slowPathStart = jit.jump();
+}
+
+static void generateRightShiftFastPath(BinaryOpDescriptor& ic, CCallHelpers& jit,
+ GPRReg result, GPRReg left, GPRReg right, RegisterSet usedRegisters,
+ CCallHelpers::Jump& done, CCallHelpers::Jump& slowPathStart,
+ JITRightShiftGenerator::ShiftType shiftType)
+{
+ ScratchRegisterAllocator allocator(usedRegisters);
+
+ BinarySnippetRegisterContext context(allocator, result, left, right);
+
+ FPRReg leftFPR = allocator.allocateScratchFPR();
+ GPRReg scratchGPR = allocator.allocateScratchGPR();
+
+ JITRightShiftGenerator gen(ic.leftOperand(), ic.rightOperand(), JSValueRegs(result),
+ JSValueRegs(left), JSValueRegs(right), leftFPR, scratchGPR, InvalidFPRReg, shiftType);
+
+ unsigned numberOfBytesUsedToPreserveReusedRegisters =
+ allocator.preserveReusedRegistersByPushing(jit, ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
+
+ context.initializeRegisters(jit);
+ gen.generateFastPath(jit);
+
+ ASSERT(gen.didEmitFastPath());
+ gen.endJumpList().link(&jit);
+ context.restoreRegisters(jit);
+ allocator.restoreReusedRegistersByPopping(jit, numberOfBytesUsedToPreserveReusedRegisters,
+ ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
+ done = jit.jump();
+
+ gen.slowPathJumpList().link(&jit);
+ context.restoreRegisters(jit);
+ allocator.restoreReusedRegistersByPopping(jit, numberOfBytesUsedToPreserveReusedRegisters,
+ ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
+ slowPathStart = jit.jump();
+}
+
template<typename BinaryArithOpGenerator, ScratchFPRUsage scratchFPRUsage = DontNeedScratchFPR>
void generateBinaryArithOpFastPath(BinaryOpDescriptor& ic, CCallHelpers& jit,
GPRReg result, GPRReg left, GPRReg right, RegisterSet usedRegisters,
@@ -178,7 +253,7 @@
BinaryArithOpGenerator gen(ic.leftOperand(), ic.rightOperand(), JSValueRegs(result),
JSValueRegs(left), JSValueRegs(right), leftFPR, rightFPR, scratchGPR, scratchFPR);
- auto numberOfBytesUsedToPreserveReusedRegisters =
+ unsigned numberOfBytesUsedToPreserveReusedRegisters =
allocator.preserveReusedRegistersByPushing(jit, ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
context.initializeRegisters(jit);
@@ -188,13 +263,13 @@
gen.endJumpList().link(&jit);
context.restoreRegisters(jit);
allocator.restoreReusedRegistersByPopping(jit, numberOfBytesUsedToPreserveReusedRegisters,
- ScratchRegisterAllocator::ExtraStackSpace::SpaceForCCall);
+ ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
done = jit.jump();
gen.slowPathJumpList().link(&jit);
context.restoreRegisters(jit);
allocator.restoreReusedRegistersByPopping(jit, numberOfBytesUsedToPreserveReusedRegisters,
- ScratchRegisterAllocator::ExtraStackSpace::SpaceForCCall);
+ ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
slowPathStart = jit.jump();
}
@@ -203,6 +278,24 @@
CCallHelpers::Jump& done, CCallHelpers::Jump& slowPathStart)
{
switch (ic.nodeType()) {
+ case BitAnd:
+ generateBinaryBitOpFastPath<JITBitAndGenerator>(ic, jit, result, left, right, usedRegisters, done, slowPathStart);
+ break;
+ case BitOr:
+ generateBinaryBitOpFastPath<JITBitOrGenerator>(ic, jit, result, left, right, usedRegisters, done, slowPathStart);
+ break;
+ case BitXor:
+ generateBinaryBitOpFastPath<JITBitXorGenerator>(ic, jit, result, left, right, usedRegisters, done, slowPathStart);
+ break;
+ case BitLShift:
+ generateBinaryBitOpFastPath<JITLeftShiftGenerator>(ic, jit, result, left, right, usedRegisters, done, slowPathStart);
+ break;
+ case BitRShift:
+ generateRightShiftFastPath(ic, jit, result, left, right, usedRegisters, done, slowPathStart, JITRightShiftGenerator::SignedShift);
+ break;
+ case BitURShift:
+ generateRightShiftFastPath(ic, jit, result, left, right, usedRegisters, done, slowPathStart, JITRightShiftGenerator::UnsignedShift);
+ break;
case ArithDiv:
generateBinaryArithOpFastPath<JITDivGenerator, NeedScratchFPR>(ic, jit, result, left, right, usedRegisters, done, slowPathStart);
break;
Modified: trunk/Source/_javascript_Core/ftl/FTLInlineCacheDescriptor.h (194112 => 194113)
--- trunk/Source/_javascript_Core/ftl/FTLInlineCacheDescriptor.h 2015-12-15 20:36:15 UTC (rev 194112)
+++ trunk/Source/_javascript_Core/ftl/FTLInlineCacheDescriptor.h 2015-12-15 21:19:31 UTC (rev 194113)
@@ -164,6 +164,84 @@
SnippetOperand m_rightOperand;
};
+class BitAndDescriptor : public BinaryOpDescriptor {
+public:
+ BitAndDescriptor(unsigned stackmapID, CodeOrigin codeOrigin, const SnippetOperand& leftOperand, const SnippetOperand& rightOperand)
+ : BinaryOpDescriptor(nodeType(), stackmapID, codeOrigin, icSize(), opName(), slowPathFunction(), leftOperand, rightOperand)
+ { }
+
+ static size_t icSize() { return sizeOfBitAnd(); }
+ static unsigned nodeType() { return DFG::BitAnd; }
+ static const char* opName() { return "BitAnd"; }
+ static J_JITOperation_EJJ slowPathFunction() { return DFG::operationValueBitAnd; }
+ static J_JITOperation_EJJ nonNumberSlowPathFunction() { return slowPathFunction(); }
+};
+
+class BitOrDescriptor : public BinaryOpDescriptor {
+public:
+ BitOrDescriptor(unsigned stackmapID, CodeOrigin codeOrigin, const SnippetOperand& leftOperand, const SnippetOperand& rightOperand)
+ : BinaryOpDescriptor(nodeType(), stackmapID, codeOrigin, icSize(), opName(), slowPathFunction(), leftOperand, rightOperand)
+ { }
+
+ static size_t icSize() { return sizeOfBitOr(); }
+ static unsigned nodeType() { return DFG::BitOr; }
+ static const char* opName() { return "BitOr"; }
+ static J_JITOperation_EJJ slowPathFunction() { return DFG::operationValueBitOr; }
+ static J_JITOperation_EJJ nonNumberSlowPathFunction() { return slowPathFunction(); }
+};
+
+class BitXorDescriptor : public BinaryOpDescriptor {
+public:
+ BitXorDescriptor(unsigned stackmapID, CodeOrigin codeOrigin, const SnippetOperand& leftOperand, const SnippetOperand& rightOperand)
+ : BinaryOpDescriptor(nodeType(), stackmapID, codeOrigin, icSize(), opName(), slowPathFunction(), leftOperand, rightOperand)
+ { }
+
+ static size_t icSize() { return sizeOfBitXor(); }
+ static unsigned nodeType() { return DFG::BitXor; }
+ static const char* opName() { return "BitXor"; }
+ static J_JITOperation_EJJ slowPathFunction() { return DFG::operationValueBitXor; }
+ static J_JITOperation_EJJ nonNumberSlowPathFunction() { return slowPathFunction(); }
+};
+
+class BitLShiftDescriptor : public BinaryOpDescriptor {
+public:
+ BitLShiftDescriptor(unsigned stackmapID, CodeOrigin codeOrigin, const SnippetOperand& leftOperand, const SnippetOperand& rightOperand)
+ : BinaryOpDescriptor(nodeType(), stackmapID, codeOrigin, icSize(), opName(), slowPathFunction(), leftOperand, rightOperand)
+ { }
+
+ static size_t icSize() { return sizeOfBitLShift(); }
+ static unsigned nodeType() { return DFG::BitLShift; }
+ static const char* opName() { return "BitLShift"; }
+ static J_JITOperation_EJJ slowPathFunction() { return DFG::operationValueBitLShift; }
+ static J_JITOperation_EJJ nonNumberSlowPathFunction() { return slowPathFunction(); }
+};
+
+class BitRShiftDescriptor : public BinaryOpDescriptor {
+public:
+ BitRShiftDescriptor(unsigned stackmapID, CodeOrigin codeOrigin, const SnippetOperand& leftOperand, const SnippetOperand& rightOperand)
+ : BinaryOpDescriptor(nodeType(), stackmapID, codeOrigin, icSize(), opName(), slowPathFunction(), leftOperand, rightOperand)
+ { }
+
+ static size_t icSize() { return sizeOfBitRShift(); }
+ static unsigned nodeType() { return DFG::BitRShift; }
+ static const char* opName() { return "BitRShift"; }
+ static J_JITOperation_EJJ slowPathFunction() { return DFG::operationValueBitRShift; }
+ static J_JITOperation_EJJ nonNumberSlowPathFunction() { return slowPathFunction(); }
+};
+
+class BitURShiftDescriptor : public BinaryOpDescriptor {
+public:
+ BitURShiftDescriptor(unsigned stackmapID, CodeOrigin codeOrigin, const SnippetOperand& leftOperand, const SnippetOperand& rightOperand)
+ : BinaryOpDescriptor(nodeType(), stackmapID, codeOrigin, icSize(), opName(), slowPathFunction(), leftOperand, rightOperand)
+ { }
+
+ static size_t icSize() { return sizeOfBitURShift(); }
+ static unsigned nodeType() { return DFG::BitURShift; }
+ static const char* opName() { return "BitURShift"; }
+ static J_JITOperation_EJJ slowPathFunction() { return DFG::operationValueBitURShift; }
+ static J_JITOperation_EJJ nonNumberSlowPathFunction() { return slowPathFunction(); }
+};
+
class ArithDivDescriptor : public BinaryOpDescriptor {
public:
ArithDivDescriptor(unsigned stackmapID, CodeOrigin codeOrigin, const SnippetOperand& leftOperand, const SnippetOperand& rightOperand)
Modified: trunk/Source/_javascript_Core/ftl/FTLInlineCacheSize.cpp (194112 => 194113)
--- trunk/Source/_javascript_Core/ftl/FTLInlineCacheSize.cpp 2015-12-15 20:36:15 UTC (rev 194112)
+++ trunk/Source/_javascript_Core/ftl/FTLInlineCacheSize.cpp 2015-12-15 21:19:31 UTC (rev 194113)
@@ -128,6 +128,108 @@
#endif
}
+size_t sizeOfBitAnd()
+{
+#if CPU(ARM64)
+#ifdef NDEBUG
+return 180; // ARM64 release.
+#else
+return 276; // ARM64 debug.
+#endif
+#else // CPU(X86_64)
+#ifdef NDEBUG
+return 199; // X86_64 release.
+#else
+return 286; // X86_64 debug.
+#endif
+#endif
+}
+
+size_t sizeOfBitOr()
+{
+#if CPU(ARM64)
+#ifdef NDEBUG
+ return 180; // ARM64 release.
+#else
+ return 276; // ARM64 debug.
+#endif
+#else // CPU(X86_64)
+#ifdef NDEBUG
+ return 199; // X86_64 release.
+#else
+ return 286; // X86_64 debug.
+#endif
+#endif
+}
+
+size_t sizeOfBitXor()
+{
+#if CPU(ARM64)
+#ifdef NDEBUG
+ return 180; // ARM64 release.
+#else
+ return 276; // ARM64 debug.
+#endif
+#else // CPU(X86_64)
+#ifdef NDEBUG
+ return 199; // X86_64 release.
+#else
+ return 286; // X86_64 debug.
+#endif
+#endif
+}
+
+size_t sizeOfBitLShift()
+{
+#if CPU(ARM64)
+#ifdef NDEBUG
+ return 180; // ARM64 release.
+#else
+ return 276; // ARM64 debug.
+#endif
+#else // CPU(X86_64)
+#ifdef NDEBUG
+ return 199; // X86_64 release.
+#else
+ return 286; // X86_64 debug.
+#endif
+#endif
+}
+
+size_t sizeOfBitRShift()
+{
+#if CPU(ARM64)
+#ifdef NDEBUG
+ return 180; // ARM64 release.
+#else
+ return 276; // ARM64 debug.
+#endif
+#else // CPU(X86_64)
+#ifdef NDEBUG
+ return 199; // X86_64 release.
+#else
+ return 286; // X86_64 debug.
+#endif
+#endif
+}
+
+size_t sizeOfBitURShift()
+{
+#if CPU(ARM64)
+#ifdef NDEBUG
+ return 180; // ARM64 release.
+#else
+ return 276; // ARM64 debug.
+#endif
+#else // CPU(X86_64)
+#ifdef NDEBUG
+ return 199; // X86_64 release.
+#else
+ return 286; // X86_64 debug.
+#endif
+#endif
+}
+
size_t sizeOfArithDiv()
{
#if CPU(ARM64)
Modified: trunk/Source/_javascript_Core/ftl/FTLInlineCacheSize.h (194112 => 194113)
--- trunk/Source/_javascript_Core/ftl/FTLInlineCacheSize.h 2015-12-15 20:36:15 UTC (rev 194112)
+++ trunk/Source/_javascript_Core/ftl/FTLInlineCacheSize.h 2015-12-15 21:19:31 UTC (rev 194113)
@@ -46,6 +46,12 @@
size_t sizeOfConstructVarargs();
size_t sizeOfConstructForwardVarargs();
size_t sizeOfIn();
+size_t sizeOfBitAnd();
+size_t sizeOfBitOr();
+size_t sizeOfBitXor();
+size_t sizeOfBitLShift();
+size_t sizeOfBitRShift();
+size_t sizeOfBitURShift();
size_t sizeOfArithDiv();
size_t sizeOfArithMul();
size_t sizeOfArithSub();
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp (194112 => 194113)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2015-12-15 20:36:15 UTC (rev 194112)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToLLVM.cpp 2015-12-15 21:19:31 UTC (rev 194113)
@@ -2263,21 +2263,37 @@
void compileBitAnd()
{
+ if (m_node->child1().useKind() == UntypedUse || m_node->child2().useKind() == UntypedUse) {
+ compileUntypedBinaryOp<BitAndDescriptor>();
+ return;
+ }
setInt32(m_out.bitAnd(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
}
void compileBitOr()
{
+ if (m_node->child1().useKind() == UntypedUse || m_node->child2().useKind() == UntypedUse) {
+ compileUntypedBinaryOp<BitOrDescriptor>();
+ return;
+ }
setInt32(m_out.bitOr(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
}
void compileBitXor()
{
+ if (m_node->child1().useKind() == UntypedUse || m_node->child2().useKind() == UntypedUse) {
+ compileUntypedBinaryOp<BitXorDescriptor>();
+ return;
+ }
setInt32(m_out.bitXor(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
}
void compileBitRShift()
{
+ if (m_node->child1().useKind() == UntypedUse || m_node->child2().useKind() == UntypedUse) {
+ compileUntypedBinaryOp<BitRShiftDescriptor>();
+ return;
+ }
setInt32(m_out.aShr(
lowInt32(m_node->child1()),
m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31))));
@@ -2285,6 +2301,10 @@
void compileBitLShift()
{
+ if (m_node->child1().useKind() == UntypedUse || m_node->child2().useKind() == UntypedUse) {
+ compileUntypedBinaryOp<BitLShiftDescriptor>();
+ return;
+ }
setInt32(m_out.shl(
lowInt32(m_node->child1()),
m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31))));
@@ -2292,6 +2312,10 @@
void compileBitURShift()
{
+ if (m_node->child1().useKind() == UntypedUse || m_node->child2().useKind() == UntypedUse) {
+ compileUntypedBinaryOp<BitURShiftDescriptor>();
+ return;
+ }
setInt32(m_out.lShr(
lowInt32(m_node->child1()),
m_out.bitAnd(lowInt32(m_node->child2()), m_out.constInt32(31))));
Modified: trunk/Source/_javascript_Core/jit/JITLeftShiftGenerator.cpp (194112 => 194113)
--- trunk/Source/_javascript_Core/jit/JITLeftShiftGenerator.cpp 2015-12-15 20:36:15 UTC (rev 194112)
+++ trunk/Source/_javascript_Core/jit/JITLeftShiftGenerator.cpp 2015-12-15 21:19:31 UTC (rev 194113)
@@ -32,6 +32,14 @@
void JITLeftShiftGenerator::generateFastPath(CCallHelpers& jit)
{
+ ASSERT(m_scratchGPR != InvalidGPRReg);
+ ASSERT(m_scratchGPR != m_left.payloadGPR());
+ ASSERT(m_scratchGPR != m_right.payloadGPR());
+#if USE(JSVALUE32_64)
+ ASSERT(m_scratchGPR != m_left.tagGPR());
+ ASSERT(m_scratchGPR != m_right.tagGPR());
+#endif
+
ASSERT(!m_leftOperand.isConstInt32() || !m_rightOperand.isConstInt32());
m_didEmitFastPath = true;
@@ -47,6 +55,12 @@
// Try to do (intConstant << intVar) or (intVar << intVar).
m_slowPathJumpList.append(jit.branchIfNotInt32(m_right));
+ GPRReg rightOperandGPR = m_right.payloadGPR();
+ if (rightOperandGPR == m_result.payloadGPR()) {
+ jit.move(rightOperandGPR, m_scratchGPR);
+ rightOperandGPR = m_scratchGPR;
+ }
+
if (m_leftOperand.isConstInt32()) {
#if USE(JSVALUE32_64)
jit.move(m_right.tagGPR(), m_result.tagGPR());
@@ -57,7 +71,7 @@
jit.moveValueRegs(m_left, m_result);
}
- jit.lshift32(m_right.payloadGPR(), m_result.payloadGPR());
+ jit.lshift32(rightOperandGPR, m_result.payloadGPR());
}
#if USE(JSVALUE64)
Modified: trunk/Source/_javascript_Core/jit/JITLeftShiftGenerator.h (194112 => 194113)
--- trunk/Source/_javascript_Core/jit/JITLeftShiftGenerator.h 2015-12-15 20:36:15 UTC (rev 194112)
+++ trunk/Source/_javascript_Core/jit/JITLeftShiftGenerator.h 2015-12-15 21:19:31 UTC (rev 194113)
@@ -35,8 +35,8 @@
class JITLeftShiftGenerator : public JITBitBinaryOpGenerator {
public:
JITLeftShiftGenerator(const SnippetOperand& leftOperand, const SnippetOperand& rightOperand,
- JSValueRegs result, JSValueRegs left, JSValueRegs right, GPRReg unused = InvalidGPRReg)
- : JITBitBinaryOpGenerator(leftOperand, rightOperand, result, left, right, unused)
+ JSValueRegs result, JSValueRegs left, JSValueRegs right, GPRReg scratchGPR)
+ : JITBitBinaryOpGenerator(leftOperand, rightOperand, result, left, right, scratchGPR)
{ }
void generateFastPath(CCallHelpers&);
Modified: trunk/Source/_javascript_Core/jit/JITRightShiftGenerator.cpp (194112 => 194113)
--- trunk/Source/_javascript_Core/jit/JITRightShiftGenerator.cpp 2015-12-15 20:36:15 UTC (rev 194112)
+++ trunk/Source/_javascript_Core/jit/JITRightShiftGenerator.cpp 2015-12-15 21:19:31 UTC (rev 194113)
@@ -87,21 +87,27 @@
// Try to do (intConstant >> intVar) or (intVar >> intVar).
m_slowPathJumpList.append(jit.branchIfNotInt32(m_right));
+ GPRReg rightOperandGPR = m_right.payloadGPR();
+ if (rightOperandGPR == m_result.payloadGPR())
+ rightOperandGPR = m_scratchGPR;
+
CCallHelpers::Jump leftNotInt;
if (m_leftOperand.isConstInt32()) {
+ jit.move(m_right.payloadGPR(), rightOperandGPR);
#if USE(JSVALUE32_64)
jit.move(m_right.tagGPR(), m_result.tagGPR());
#endif
jit.move(CCallHelpers::Imm32(m_leftOperand.asConstInt32()), m_result.payloadGPR());
} else {
leftNotInt = jit.branchIfNotInt32(m_left);
+ jit.move(m_right.payloadGPR(), rightOperandGPR);
jit.moveValueRegs(m_left, m_result);
}
if (m_shiftType == SignedShift)
- jit.rshift32(m_right.payloadGPR(), m_result.payloadGPR());
+ jit.rshift32(rightOperandGPR, m_result.payloadGPR());
else
- jit.urshift32(m_right.payloadGPR(), m_result.payloadGPR());
+ jit.urshift32(rightOperandGPR, m_result.payloadGPR());
#if USE(JSVALUE64)
jit.or64(GPRInfo::tagTypeNumberRegister, m_result.payloadGPR());
#endif