Bug 991457 - Don't DCE MLoadElement if it needs a hole check. r=h4writer, a=sledru
authorJan de Mooij <jdemooij@mozilla.com>
Mon, 14 Apr 2014 15:20:11 +0200
changeset 183757 3437e5663d9e7962be2226ffe378317d8df56182
parent 183756 3960907890b7dbcd94a9afb9d3c1dc851f16f8df
child 183758 31f09e1b357db655bf3381507e88086bf7671d22
child 183760 3a4f085a63987a613c4fc2cf1a060b8369664a76
child 183762 7938ad1529f98fb30d09387e23002bb524510d8c
push id3473
push userryanvm@gmail.com
push dateMon, 14 Apr 2014 20:03:53 +0000
treeherdermozilla-beta@3437e5663d9e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersh4writer, sledru
bugs991457
milestone29.0
Bug 991457 - Don't DCE MLoadElement if it needs a hole check. r=h4writer, a=sledru
js/src/jit-test/tests/ion/bug991457.js
js/src/jit/MIR.h
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug991457.js
@@ -0,0 +1,64 @@
+function test() {
+    this.init();
+    for (var i=0; i<10; i++) {
+        delete this.blocks[10][9];
+        this.collapse_blocks();
+    }
+    this.look_for_holes();
+}
+test.prototype.init = function() {
+    this.blocks = new Array(20);
+    for (var x=0; x<this.blocks.length; x++) {
+        this.blocks[x] = new Array(10);
+        for (var y=0; y<this.blocks[x].length; y++) {
+            this.blocks[x][y] = {};
+        }
+    }
+}
+test.prototype.move_block = function(x,y,x1,y1) {
+    this.blocks[x][y] = this.blocks[x1][y1];
+    if (this.blocks[x][y])
+        delete this.blocks[x1][y1];
+}
+test.prototype.collapse_blocks = function() {
+    var didSomething=0;
+    do {
+        didSomething=0;
+        for (var x=0; x<this.blocks.length; x++)
+            for (var y=1; y<this.blocks[x].length; y++) {
+                if (!this.blocks[x][y] && this.blocks[x][y-1]) {
+                    this.move_block(x,y,x,y-1);
+                    didSomething=1;
+                }
+            }
+    } while (didSomething);
+
+    do {
+        didSomething = 0;
+        for (var x=0; x<this.blocks.length-1; x++) {
+            if (!this.blocks[x][9] && this.blocks[x+1][9]) {
+                for (var y=0; y<this.blocks[x].length; y++)
+                    this.move_block(x,y,x+1,y);
+                didSomething = 1;
+            }
+	}
+    } while (didSomething);
+}
+test.prototype.look_for_holes = function() {
+    var was_empty = false;
+    var n_empty = 0;
+    for (var x=0; x<this.blocks.length; x++) {
+        var empty = true;
+        for (var y=0; y<this.blocks[x].length; y++) {
+            if (this.blocks[x][y]) {
+                empty = false;
+		n_empty++;
+	    }
+	}
+	if (was_empty)
+	    assertEq(empty, true);
+        was_empty = empty;
+    }
+    assertEq(n_empty, 190);
+}
+new test();
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -5743,16 +5743,22 @@ class MLoadElement
     bool needsHoleCheck_;
     bool loadDoubles_;
 
     MLoadElement(MDefinition *elements, MDefinition *index, bool needsHoleCheck, bool loadDoubles)
       : MBinaryInstruction(elements, index),
         needsHoleCheck_(needsHoleCheck),
         loadDoubles_(loadDoubles)
     {
+        if (needsHoleCheck) {
+            // Uses may be optimized away based on this instruction's result
+            // type. This means it's invalid to DCE this instruction, as we
+            // have to invalidate when we read a hole.
+            setGuard();
+        }
         setResultType(MIRType_Value);
         setMovable();
         JS_ASSERT(elements->type() == MIRType_Elements);
         JS_ASSERT(index->type() == MIRType_Int32);
     }
 
   public:
     INSTRUCTION_HEADER(LoadElement)