Title: [146100] trunk
Revision
146100
Author
msab...@apple.com
Date
2013-03-18 12:11:47 -0700 (Mon, 18 Mar 2013)

Log Message

Potentially unsafe register allocations in DFG code generation
https://bugs.webkit.org/show_bug.cgi?id=112477

Reviewed by Geoffrey Garen.

Source/_javascript_Core: 

Moved allocation of temporary GPRs to be before any generated branches in the functions below.

* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compileObjectToObjectOrOtherEquality):
(JSC::DFG::SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality):
(JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compileObjectToObjectOrOtherEquality):
(JSC::DFG::SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality):
(JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot):

LayoutTests: 

New tests added to verify proper operation of
SpeculativeJIT::compileObjectToObjectOrOtherEquality,
SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality
and SpeculativeJIT::compileObjectOrOtherLogicalNot.

* fast/js/dfg-compare-final-object-to-final-object-or-other-expected.txt: Added.
* fast/js/dfg-compare-final-object-to-final-object-or-other.html: Added.
* fast/js/dfg-logical-not-final-object-or-other-expected.txt: Added.
* fast/js/dfg-logical-not-final-object-or-other.html: Added.
* fast/js/dfg-peephole-compare-final-object-to-final-object-or-other-expected.txt: Added.
* fast/js/dfg-peephole-compare-final-object-to-final-object-or-other.html: Added.
* fast/js/script-tests/dfg-compare-final-object-to-final-object-or-other.js: Added.
* fast/js/script-tests/dfg-logical-not-final-object-or-other.js: Added.
* fast/js/script-tests/dfg-peephole-compare-final-object-to-final-object-or-other.js: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (146099 => 146100)


--- trunk/LayoutTests/ChangeLog	2013-03-18 19:05:01 UTC (rev 146099)
+++ trunk/LayoutTests/ChangeLog	2013-03-18 19:11:47 UTC (rev 146100)
@@ -1,3 +1,25 @@
+2013-03-18  Michael Saboff  <msab...@apple.com>
+
+        Potentially unsafe register allocations in DFG code generation
+        https://bugs.webkit.org/show_bug.cgi?id=112477
+
+        Reviewed by Geoffrey Garen.
+
+        New tests added to verify proper operation of
+        SpeculativeJIT::compileObjectToObjectOrOtherEquality,
+        SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality
+        and SpeculativeJIT::compileObjectOrOtherLogicalNot.
+
+        * fast/js/dfg-compare-final-object-to-final-object-or-other-expected.txt: Added.
+        * fast/js/dfg-compare-final-object-to-final-object-or-other.html: Added.
+        * fast/js/dfg-logical-not-final-object-or-other-expected.txt: Added.
+        * fast/js/dfg-logical-not-final-object-or-other.html: Added.
+        * fast/js/dfg-peephole-compare-final-object-to-final-object-or-other-expected.txt: Added.
+        * fast/js/dfg-peephole-compare-final-object-to-final-object-or-other.html: Added.
+        * fast/js/script-tests/dfg-compare-final-object-to-final-object-or-other.js: Added.
+        * fast/js/script-tests/dfg-logical-not-final-object-or-other.js: Added.
+        * fast/js/script-tests/dfg-peephole-compare-final-object-to-final-object-or-other.js: Added.
+
 2013-03-18  Julien Chaffraix  <jchaffr...@webkit.org>
 
         [CSS Grid Layout] Fix StyleGridData::operator==

Added: trunk/LayoutTests/fast/js/dfg-compare-final-object-to-final-object-or-other-expected.txt (0 => 146100)


--- trunk/LayoutTests/fast/js/dfg-compare-final-object-to-final-object-or-other-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/js/dfg-compare-final-object-to-final-object-or-other-expected.txt	2013-03-18 19:11:47 UTC (rev 146100)
@@ -0,0 +1,109 @@
+Tests that CompareEq for the case where one side is predicted final object and the other side is predicted either final object or other (i.e. null or undefined) when document.all is present.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/js/dfg-compare-final-object-to-final-object-or-other.html (0 => 146100)


--- trunk/LayoutTests/fast/js/dfg-compare-final-object-to-final-object-or-other.html	                        (rev 0)
+++ trunk/LayoutTests/fast/js/dfg-compare-final-object-to-final-object-or-other.html	2013-03-18 19:11:47 UTC (rev 146100)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/fast/js/dfg-logical-not-final-object-or-other-expected.txt (0 => 146100)


--- trunk/LayoutTests/fast/js/dfg-logical-not-final-object-or-other-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/js/dfg-logical-not-final-object-or-other-expected.txt	2013-03-18 19:11:47 UTC (rev 146100)
@@ -0,0 +1,109 @@
+Tests that logical not of an object where it is predicted either final object or other (i.e. null or undefined) performs correctly when document.all is present.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS foo(null) is false
+PASS foo(o) is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/js/dfg-logical-not-final-object-or-other.html (0 => 146100)


--- trunk/LayoutTests/fast/js/dfg-logical-not-final-object-or-other.html	                        (rev 0)
+++ trunk/LayoutTests/fast/js/dfg-logical-not-final-object-or-other.html	2013-03-18 19:11:47 UTC (rev 146100)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/fast/js/dfg-peephole-compare-final-object-to-final-object-or-other-expected.txt (0 => 146100)


--- trunk/LayoutTests/fast/js/dfg-peephole-compare-final-object-to-final-object-or-other-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/js/dfg-peephole-compare-final-object-to-final-object-or-other-expected.txt	2013-03-18 19:11:47 UTC (rev 146100)
@@ -0,0 +1,109 @@
+Tests that (Peephole) CompareEq for the case where one side is predicted final object and the other side is predicted either final object or other (i.e. null or undefined) when document.all is present.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS foo({f:42}, null) is false
+PASS foo(o, o) is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/js/dfg-peephole-compare-final-object-to-final-object-or-other.html (0 => 146100)


--- trunk/LayoutTests/fast/js/dfg-peephole-compare-final-object-to-final-object-or-other.html	                        (rev 0)
+++ trunk/LayoutTests/fast/js/dfg-peephole-compare-final-object-to-final-object-or-other.html	2013-03-18 19:11:47 UTC (rev 146100)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/fast/js/script-tests/dfg-compare-final-object-to-final-object-or-other.js (0 => 146100)


--- trunk/LayoutTests/fast/js/script-tests/dfg-compare-final-object-to-final-object-or-other.js	                        (rev 0)
+++ trunk/LayoutTests/fast/js/script-tests/dfg-compare-final-object-to-final-object-or-other.js	2013-03-18 19:11:47 UTC (rev 146100)
@@ -0,0 +1,27 @@
+description(
+"Tests that CompareEq for the case where one side is predicted final object and the other side is predicted either final object or other (i.e. null or undefined) when document.all is present."
+);
+
+if (document.all)
+    var unused = 1;
+
+function foo(a, b) {
+    var result = false;
+    var eq = (a == b);
+
+    if (b == 42)
+	return -1;
+
+    if (eq)
+        result = true;
+    return result;
+}
+
+for (var i = 0; i < 100; ++i) {
+    if (i%2) {
+        var o = {f:42};
+        shouldBe("foo(o, o)", "true");
+    } else
+        shouldBe("foo({f:42}, null)", "false");
+}
+

Added: trunk/LayoutTests/fast/js/script-tests/dfg-logical-not-final-object-or-other.js (0 => 146100)


--- trunk/LayoutTests/fast/js/script-tests/dfg-logical-not-final-object-or-other.js	                        (rev 0)
+++ trunk/LayoutTests/fast/js/script-tests/dfg-logical-not-final-object-or-other.js	2013-03-18 19:11:47 UTC (rev 146100)
@@ -0,0 +1,26 @@
+description(
+"Tests that logical not of an object where it is predicted either final object or other (i.e. null or undefined) performs correctly when document.all is present."
+);
+
+if (document.all)
+    var unused = 1;
+
+function foo(a) {
+    var t = !a;
+
+    if (a == 16)
+        return -1;
+
+    if (t)
+        return false;
+    return true;
+}
+
+for (var i = 0; i < 100; ++i) {
+    if (i%2) {
+        var o = {f:42};
+        shouldBe("foo(o)", "true");
+    } else
+        shouldBe("foo(null)", "false");
+}
+

Added: trunk/LayoutTests/fast/js/script-tests/dfg-peephole-compare-final-object-to-final-object-or-other.js (0 => 146100)


--- trunk/LayoutTests/fast/js/script-tests/dfg-peephole-compare-final-object-to-final-object-or-other.js	                        (rev 0)
+++ trunk/LayoutTests/fast/js/script-tests/dfg-peephole-compare-final-object-to-final-object-or-other.js	2013-03-18 19:11:47 UTC (rev 146100)
@@ -0,0 +1,23 @@
+description(
+"Tests that (Peephole) CompareEq for the case where one side is predicted final object and the other side is predicted either final object or other (i.e. null or undefined) when document.all is present."
+);
+
+if (document.all)
+    var unused = 1;
+
+function foo(a, b) {
+    var result = false;
+
+    if (a == b)
+        result = true;
+    return result;
+}
+
+for (var i = 0; i < 100; ++i) {
+    if (i%2) {
+        var o = {f:42};
+        shouldBe("foo(o, o)", "true");
+    } else
+        shouldBe("foo({f:42}, null)", "false");
+}
+

Modified: trunk/Source/_javascript_Core/ChangeLog (146099 => 146100)


--- trunk/Source/_javascript_Core/ChangeLog	2013-03-18 19:05:01 UTC (rev 146099)
+++ trunk/Source/_javascript_Core/ChangeLog	2013-03-18 19:11:47 UTC (rev 146100)
@@ -1,3 +1,21 @@
+2013-03-18  Michael Saboff  <msab...@apple.com>
+
+        Potentially unsafe register allocations in DFG code generation
+        https://bugs.webkit.org/show_bug.cgi?id=112477
+
+        Reviewed by Geoffrey Garen.
+
+        Moved allocation of temporary GPRs to be before any generated branches in the functions below.
+
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compileObjectToObjectOrOtherEquality):
+        (JSC::DFG::SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality):
+        (JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compileObjectToObjectOrOtherEquality):
+        (JSC::DFG::SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality):
+        (JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot):
+
 2013-03-15  Filip Pizlo  <fpi...@apple.com>
 
         DFG string conversions and allocations should be inlined

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (146099 => 146100)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2013-03-18 19:05:01 UTC (rev 146099)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2013-03-18 19:11:47 UTC (rev 146100)
@@ -1343,8 +1343,20 @@
     GPRReg op2TagGPR = op2.tagGPR();
     GPRReg op2PayloadGPR = op2.payloadGPR();
     GPRReg resultGPR = result.gpr();
-    
-    if (m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { 
+    GPRTemporary structure;
+    GPRReg structureGPR = InvalidGPRReg;
+
+    bool masqueradesAsUndefinedWatchpointValid = m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid();
+
+    if (!masqueradesAsUndefinedWatchpointValid) {
+        // The masquerades as undefined case will use the structure register, so allocate it here.
+        // Do this at the top of the function to avoid branching around a register allocation.
+        GPRTemporary realStructure(this);
+        structure.adopt(realStructure);
+        structureGPR = structure.gpr();
+    }
+
+    if (masqueradesAsUndefinedWatchpointValid) {
         m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint());
         DFG_TYPE_CHECK(
             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr(
@@ -1352,9 +1364,6 @@
                 MacroAssembler::Address(op1GPR, JSCell::structureOffset()), 
                 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
     } else {
-        GPRTemporary structure(this);
-        GPRReg structureGPR = structure.gpr();
-
         m_jit.loadPtr(MacroAssembler::Address(op1GPR, JSCell::structureOffset()), structureGPR);
         DFG_TYPE_CHECK(
             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr(
@@ -1375,7 +1384,7 @@
         m_jit.branch32(MacroAssembler::NotEqual, op2TagGPR, TrustedImm32(JSValue::CellTag));
     
     // We know that within this branch, rightChild must be a cell.
-    if (m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { 
+    if (masqueradesAsUndefinedWatchpointValid) {
         m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint());
         DFG_TYPE_CHECK(
             JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, (~SpecCell) | SpecObject,
@@ -1384,9 +1393,6 @@
                 MacroAssembler::Address(op2PayloadGPR, JSCell::structureOffset()), 
                 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
     } else {
-        GPRTemporary structure(this);
-        GPRReg structureGPR = structure.gpr();
-
         m_jit.loadPtr(MacroAssembler::Address(op2PayloadGPR, JSCell::structureOffset()), structureGPR);
         DFG_TYPE_CHECK(
             JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, (~SpecCell) | SpecObject,
@@ -1445,8 +1451,20 @@
     GPRReg op2TagGPR = op2.tagGPR();
     GPRReg op2PayloadGPR = op2.payloadGPR();
     GPRReg resultGPR = result.gpr();
-    
-    if (m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) {
+    GPRTemporary structure;
+    GPRReg structureGPR = InvalidGPRReg;
+
+    bool masqueradesAsUndefinedWatchpointValid = m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid();
+
+    if (!masqueradesAsUndefinedWatchpointValid) {
+        // The masquerades as undefined case will use the structure register, so allocate it here.
+        // Do this at the top of the function to avoid branching around a register allocation.
+        GPRTemporary realStructure(this);
+        structure.adopt(realStructure);
+        structureGPR = structure.gpr();
+    }
+
+    if (masqueradesAsUndefinedWatchpointValid) {
         m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint());
         DFG_TYPE_CHECK(
             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr(
@@ -1454,9 +1472,6 @@
                 MacroAssembler::Address(op1GPR, JSCell::structureOffset()), 
                 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
     } else {
-        GPRTemporary structure(this);
-        GPRReg structureGPR = structure.gpr();
-
         m_jit.loadPtr(MacroAssembler::Address(op1GPR, JSCell::structureOffset()), structureGPR);
         DFG_TYPE_CHECK(
             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr(
@@ -1476,7 +1491,7 @@
         m_jit.branch32(MacroAssembler::NotEqual, op2TagGPR, TrustedImm32(JSValue::CellTag));
     
     // We know that within this branch, rightChild must be a cell.
-    if (m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) {
+    if (masqueradesAsUndefinedWatchpointValid) {
         m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint());
         DFG_TYPE_CHECK(
             JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, (~SpecCell) | SpecObject,
@@ -1485,9 +1500,6 @@
                 MacroAssembler::Address(op2PayloadGPR, JSCell::structureOffset()), 
                 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
     } else {
-        GPRTemporary structure(this);
-        GPRReg structureGPR = structure.gpr();
-
         m_jit.loadPtr(MacroAssembler::Address(op2PayloadGPR, JSCell::structureOffset()), structureGPR);
         DFG_TYPE_CHECK(
             JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, (~SpecCell) | SpecObject,
@@ -1583,9 +1595,21 @@
     GPRReg valueTagGPR = value.tagGPR();
     GPRReg valuePayloadGPR = value.payloadGPR();
     GPRReg resultPayloadGPR = resultPayload.gpr();
-    
+    GPRTemporary structure;
+    GPRReg structureGPR = InvalidGPRReg;
+
+    bool masqueradesAsUndefinedWatchpointValid = m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid();
+
+    if (!masqueradesAsUndefinedWatchpointValid) {
+        // The masquerades as undefined case will use the structure register, so allocate it here.
+        // Do this at the top of the function to avoid branching around a register allocation.
+        GPRTemporary realStructure(this);
+        structure.adopt(realStructure);
+        structureGPR = structure.gpr();
+    }
+
     MacroAssembler::Jump notCell = m_jit.branch32(MacroAssembler::NotEqual, valueTagGPR, TrustedImm32(JSValue::CellTag));
-    if (m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) {
+    if (masqueradesAsUndefinedWatchpointValid) {
         m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint());
 
         DFG_TYPE_CHECK(
@@ -1595,9 +1619,6 @@
                 MacroAssembler::Address(valuePayloadGPR, JSCell::structureOffset()),
                 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
     } else {
-        GPRTemporary structure(this);
-        GPRReg structureGPR = structure.gpr();
-
         m_jit.loadPtr(MacroAssembler::Address(valuePayloadGPR, JSCell::structureOffset()), structureGPR);
 
         DFG_TYPE_CHECK(

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (146099 => 146100)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2013-03-18 19:05:01 UTC (rev 146099)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2013-03-18 19:11:47 UTC (rev 146100)
@@ -1369,8 +1369,20 @@
     GPRReg op1GPR = op1.gpr();
     GPRReg op2GPR = op2.gpr();
     GPRReg resultGPR = result.gpr();
-   
-    if (m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { 
+    GPRTemporary structure;
+    GPRReg structureGPR = InvalidGPRReg;
+
+    bool masqueradesAsUndefinedWatchpointValid = m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid();
+
+    if (!masqueradesAsUndefinedWatchpointValid) {
+        // The masquerades as undefined case will use the structure register, so allocate it here.
+        // Do this at the top of the function to avoid branching around a register allocation.
+        GPRTemporary realStructure(this);
+        structure.adopt(realStructure);
+        structureGPR = structure.gpr();
+    }
+
+    if (masqueradesAsUndefinedWatchpointValid) {
         m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint());
         DFG_TYPE_CHECK(
             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr(
@@ -1378,9 +1390,6 @@
                 MacroAssembler::Address(op1GPR, JSCell::structureOffset()), 
                 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
     } else {
-        GPRTemporary structure(this);
-        GPRReg structureGPR = structure.gpr();
-
         m_jit.loadPtr(MacroAssembler::Address(op1GPR, JSCell::structureOffset()), structureGPR);
         DFG_TYPE_CHECK(
             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr(
@@ -1400,7 +1409,7 @@
         m_jit.branchTest64(MacroAssembler::NonZero, op2GPR, GPRInfo::tagMaskRegister);
     
     // We know that within this branch, rightChild must be a cell. 
-    if (m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { 
+    if (masqueradesAsUndefinedWatchpointValid) { 
         m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint());
         DFG_TYPE_CHECK(
             JSValueRegs(op2GPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchPtr(
@@ -1408,9 +1417,6 @@
                 MacroAssembler::Address(op2GPR, JSCell::structureOffset()), 
                 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
     } else {
-        GPRTemporary structure(this);
-        GPRReg structureGPR = structure.gpr();
-
         m_jit.loadPtr(MacroAssembler::Address(op2GPR, JSCell::structureOffset()), structureGPR);
         DFG_TYPE_CHECK(
             JSValueRegs(op2GPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchPtr(
@@ -1467,8 +1473,20 @@
     GPRReg op1GPR = op1.gpr();
     GPRReg op2GPR = op2.gpr();
     GPRReg resultGPR = result.gpr();
+    GPRTemporary structure;
+    GPRReg structureGPR = InvalidGPRReg;
     
-    if (m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) {
+    bool masqueradesAsUndefinedWatchpointValid = m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid();
+
+    if (!masqueradesAsUndefinedWatchpointValid) {
+        // The masquerades as undefined case will use the structure register, so allocate it here.
+        // Do this at the top of the function to avoid branching around a register allocation.
+        GPRTemporary realStructure(this);
+        structure.adopt(realStructure);
+        structureGPR = structure.gpr();
+    }
+
+    if (masqueradesAsUndefinedWatchpointValid) {
         m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint());
         DFG_TYPE_CHECK(
             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr(
@@ -1476,9 +1494,6 @@
                 MacroAssembler::Address(op1GPR, JSCell::structureOffset()), 
                 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
     } else {
-        GPRTemporary structure(this);
-        GPRReg structureGPR = structure.gpr();
-
         m_jit.loadPtr(MacroAssembler::Address(op1GPR, JSCell::structureOffset()), structureGPR);
         DFG_TYPE_CHECK(
             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr(
@@ -1491,14 +1506,14 @@
                 MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), 
                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
     }
-    
+
     // It seems that most of the time when programs do a == b where b may be either null/undefined
     // or an object, b is usually an object. Balance the branches to make that case fast.
     MacroAssembler::Jump rightNotCell =
         m_jit.branchTest64(MacroAssembler::NonZero, op2GPR, GPRInfo::tagMaskRegister);
     
     // We know that within this branch, rightChild must be a cell. 
-    if (m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) {
+    if (masqueradesAsUndefinedWatchpointValid) {
         m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint());
         DFG_TYPE_CHECK(
             JSValueRegs(op2GPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchPtr(
@@ -1506,9 +1521,6 @@
                 MacroAssembler::Address(op2GPR, JSCell::structureOffset()), 
                 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
     } else {
-        GPRTemporary structure(this);
-        GPRReg structureGPR = structure.gpr();
-
         m_jit.loadPtr(MacroAssembler::Address(op2GPR, JSCell::structureOffset()), structureGPR);
         DFG_TYPE_CHECK(
             JSValueRegs(op2GPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchPtr(
@@ -1599,9 +1611,21 @@
     GPRTemporary result(this);
     GPRReg valueGPR = value.gpr();
     GPRReg resultGPR = result.gpr();
-    
+    GPRTemporary structure;
+    GPRReg structureGPR = InvalidGPRReg;
+
+    bool masqueradesAsUndefinedWatchpointValid = m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid();
+
+    if (!masqueradesAsUndefinedWatchpointValid) {
+        // The masquerades as undefined case will use the structure register, so allocate it here.
+        // Do this at the top of the function to avoid branching around a register allocation.
+        GPRTemporary realStructure(this);
+        structure.adopt(realStructure);
+        structureGPR = structure.gpr();
+    }
+
     MacroAssembler::Jump notCell = m_jit.branchTest64(MacroAssembler::NonZero, valueGPR, GPRInfo::tagMaskRegister);
-    if (m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) {
+    if (masqueradesAsUndefinedWatchpointValid) {
         m_jit.graph().globalObjectFor(m_currentNode->codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint());
         DFG_TYPE_CHECK(
             JSValueRegs(valueGPR), nodeUse, (~SpecCell) | SpecObject, m_jit.branchPtr(
@@ -1609,9 +1633,6 @@
                 MacroAssembler::Address(valueGPR, JSCell::structureOffset()),
                 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
     } else {
-        GPRTemporary structure(this);
-        GPRReg structureGPR = structure.gpr();
-
         m_jit.loadPtr(MacroAssembler::Address(valueGPR, JSCell::structureOffset()), structureGPR);
 
         DFG_TYPE_CHECK(
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to