summaryrefslogtreecommitdiffstats
path: root/js
diff options
context:
space:
mode:
Diffstat (limited to 'js')
-rw-r--r--js/src/jit-test/tests/ion/bug1493900-1.js17
-rw-r--r--js/src/jit-test/tests/ion/bug1493900-2.js7
-rw-r--r--js/src/jit/BacktrackingAllocator.cpp38
-rw-r--r--js/src/jit/BacktrackingAllocator.h30
4 files changed, 66 insertions, 26 deletions
diff --git a/js/src/jit-test/tests/ion/bug1493900-1.js b/js/src/jit-test/tests/ion/bug1493900-1.js
new file mode 100644
index 000000000..643c1943d
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug1493900-1.js
@@ -0,0 +1,17 @@
+function f() {
+ var objs = [];
+ for (var i = 0; i < 100; i++) {
+ objs[i] = {};
+ }
+ var o = objs[0];
+ var a = new Float64Array(1024);
+ function g(a, b) {
+ let p = b;
+ for (; p.x < 0; p = p.x) {
+ while (p === p) {}
+ }
+ for (var i = 0; i < 10000; ++i) {}
+ }
+ g(a, o);
+}
+f();
diff --git a/js/src/jit-test/tests/ion/bug1493900-2.js b/js/src/jit-test/tests/ion/bug1493900-2.js
new file mode 100644
index 000000000..7e7f5fdec
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug1493900-2.js
@@ -0,0 +1,7 @@
+function f(a, b) {
+ for (; b.x < 0; b = b.x) {
+ while (b === b) {};
+ }
+ for (var i = 0; i < 99999; ++i) {}
+}
+f(0, 0);
diff --git a/js/src/jit/BacktrackingAllocator.cpp b/js/src/jit/BacktrackingAllocator.cpp
index 741ed1592..645aefc4f 100644
--- a/js/src/jit/BacktrackingAllocator.cpp
+++ b/js/src/jit/BacktrackingAllocator.cpp
@@ -1736,6 +1736,18 @@ BacktrackingAllocator::deadRange(LiveRange* range)
}
bool
+BacktrackingAllocator::moveAtEdge(LBlock* predecessor, LBlock* successor, LiveRange* from,
+ LiveRange* to, LDefinition::Type type)
+{
+ if (successor->mir()->numPredecessors() > 1) {
+ MOZ_ASSERT(predecessor->mir()->numSuccessors() == 1);
+ return moveAtExit(predecessor, from, to, type);
+ }
+
+ return moveAtEntry(successor, from, to, type);
+}
+
+bool
BacktrackingAllocator::resolveControlFlow()
{
// Add moves to handle changing assignments for vregs over their lifetime.
@@ -1846,15 +1858,11 @@ BacktrackingAllocator::resolveControlFlow()
if (!alloc().ensureBallast()) {
return false;
}
- if (mSuccessor->numPredecessors() > 1) {
- MOZ_ASSERT(predecessor->mir()->numSuccessors() == 1);
- if (!moveAtExit(predecessor, from, to, def->type())) {
- return false;
- }
- } else {
- if (!moveAtEntry(successor, from, to, def->type())) {
- return false;
- }
+
+ // Note: we have to use moveAtEdge both here and below (for edge
+ // resolution) to avoid conflicting moves. See bug 1493900.
+ if (!moveAtEdge(predecessor, successor, from, to, def->type())) {
+ return false;
}
}
}
@@ -1884,16 +1892,12 @@ BacktrackingAllocator::resolveControlFlow()
if (targetRange->covers(exitOf(predecessor)))
continue;
- if (!alloc().ensureBallast())
+ if (!alloc().ensureBallast()) {
return false;
+ }
LiveRange* from = reg.rangeFor(exitOf(predecessor), true);
- if (successor->mir()->numPredecessors() > 1) {
- MOZ_ASSERT(predecessor->mir()->numSuccessors() == 1);
- if (!moveAtExit(predecessor, from, targetRange, reg.type()))
- return false;
- } else {
- if (!moveAtEntry(successor, from, targetRange, reg.type()))
- return false;
+ if (!moveAtEdge(predecessor, successor, from, targetRange, reg.type())) {
+ return false;
}
}
}
diff --git a/js/src/jit/BacktrackingAllocator.h b/js/src/jit/BacktrackingAllocator.h
index 9910498fb..c6cf26695 100644
--- a/js/src/jit/BacktrackingAllocator.h
+++ b/js/src/jit/BacktrackingAllocator.h
@@ -108,8 +108,9 @@ class Requirement
}
MOZ_ASSERT(newRequirement.kind() == Requirement::REGISTER);
- if (kind() == Requirement::FIXED)
+ if (kind() == Requirement::FIXED) {
return allocation().isRegister();
+ }
*this = newRequirement;
return true;
@@ -353,10 +354,12 @@ class LiveRange : public TempObject
// Comparator for use in range splay trees.
static int compare(LiveRange* v0, LiveRange* v1) {
// LiveRange includes 'from' but excludes 'to'.
- if (v0->to() <= v1->from())
+ if (v0->to() <= v1->from()) {
return -1;
- if (v0->from() >= v1->to())
+ }
+ if (v0->from() >= v1->to()) {
return 1;
+ }
return 0;
}
};
@@ -642,10 +645,12 @@ class BacktrackingAllocator : protected RegisterAllocator
// Comparator for use in splay tree.
static int compare(CallRange* v0, CallRange* v1) {
- if (v0->range.to <= v1->range.from)
+ if (v0->range.to <= v1->range.from) {
return -1;
- if (v0->range.from >= v1->range.to)
+ }
+ if (v0->range.from >= v1->range.to) {
return 1;
+ }
return 0;
}
};
@@ -744,36 +749,43 @@ class BacktrackingAllocator : protected RegisterAllocator
MOZ_MUST_USE bool moveInput(LInstruction* ins, LiveRange* from, LiveRange* to,
LDefinition::Type type) {
- if (from->bundle()->allocation() == to->bundle()->allocation())
+ if (from->bundle()->allocation() == to->bundle()->allocation()) {
return true;
+ }
LMoveGroup* moves = getInputMoveGroup(ins);
return addMove(moves, from, to, type);
}
MOZ_MUST_USE bool moveAfter(LInstruction* ins, LiveRange* from, LiveRange* to,
LDefinition::Type type) {
- if (from->bundle()->allocation() == to->bundle()->allocation())
+ if (from->bundle()->allocation() == to->bundle()->allocation()) {
return true;
+ }
LMoveGroup* moves = getMoveGroupAfter(ins);
return addMove(moves, from, to, type);
}
MOZ_MUST_USE bool moveAtExit(LBlock* block, LiveRange* from, LiveRange* to,
LDefinition::Type type) {
- if (from->bundle()->allocation() == to->bundle()->allocation())
+ if (from->bundle()->allocation() == to->bundle()->allocation()) {
return true;
+ }
LMoveGroup* moves = block->getExitMoveGroup(alloc());
return addMove(moves, from, to, type);
}
MOZ_MUST_USE bool moveAtEntry(LBlock* block, LiveRange* from, LiveRange* to,
LDefinition::Type type) {
- if (from->bundle()->allocation() == to->bundle()->allocation())
+ if (from->bundle()->allocation() == to->bundle()->allocation()) {
return true;
+ }
LMoveGroup* moves = block->getEntryMoveGroup(alloc());
return addMove(moves, from, to, type);
}
+ MOZ_MUST_USE bool moveAtEdge(LBlock* predecessor, LBlock* successor, LiveRange* from,
+ LiveRange* to, LDefinition::Type type);
+
// Debugging methods.
void dumpAllocations();