Bug 1500978 - Some follow-up changes/tests for bug 1493900. r=sunfish
authorJan de Mooij <jdemooij@mozilla.com>
Mon, 22 Oct 2018 18:16:54 +0200
changeset 490660 214a7b40bd26f08c24e70183fe1acc2656f26ef9
parent 490659 15811bce212a0bbe0603ff31f3f95934050afe95
child 490662 97b682ea485d8f5d2f483051dcc53c59883344d1
push id247
push userfmarier@mozilla.com
push dateSat, 27 Oct 2018 01:06:44 +0000
reviewerssunfish
bugs1500978, 1493900
milestone64.0a1
Bug 1500978 - Some follow-up changes/tests for bug 1493900. r=sunfish
js/src/jit-test/tests/ion/bug1493900-1.js
js/src/jit-test/tests/ion/bug1493900-2.js
js/src/jit/BacktrackingAllocator.cpp
js/src/jit/BacktrackingAllocator.h
new file mode 100644
--- /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();
new file mode 100644
--- /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);
--- a/js/src/jit/BacktrackingAllocator.cpp
+++ b/js/src/jit/BacktrackingAllocator.cpp
@@ -1948,16 +1948,28 @@ BacktrackingAllocator::deadRange(LiveRan
     if (reg.usedByPhi()) {
         return false;
     }
 
     return true;
 }
 
 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.
     JitSpew(JitSpew_RegAlloc, "Resolving control flow (vreg loop)");
 
     // Look for places where a register's assignment changes in the middle of a
     // basic block.
     MOZ_ASSERT(!vregs[0u].hasRanges());
@@ -2065,25 +2077,21 @@ BacktrackingAllocator::resolveControlFlo
 
                 LAllocation* input = phi->getOperand(k);
                 LiveRange* from = vreg(input).rangeFor(exitOf(predecessor), /* preferRegister = */ true);
                 MOZ_ASSERT(from);
 
                 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;
                 }
             }
         }
     }
 
     // Add moves to resolve graph edges with different allocations at their
     // source and target.
     for (size_t i = 1; i < graph.numVirtualRegisters(); i++) {
@@ -2111,25 +2119,18 @@ BacktrackingAllocator::resolveControlFlo
                     if (targetRange->covers(exitOf(predecessor))) {
                         continue;
                     }
 
                     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;
                     }
                 }
             }
         }
     }
 
     return true;
 }
--- a/js/src/jit/BacktrackingAllocator.h
+++ b/js/src/jit/BacktrackingAllocator.h
@@ -825,16 +825,19 @@ class BacktrackingAllocator : protected 
                                   LDefinition::Type type) {
         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();
 
     struct PrintLiveRange;
 
     bool minimalDef(LiveRange* range, LNode* ins);
     bool minimalUse(LiveRange* range, UsePosition* use);
     bool minimalBundle(LiveBundle* bundle, bool* pfixed = nullptr);