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(