Add liveness intervals to indicate variable writes within try blocks, bug 714645. r=dvander
authorBrian Hackett <bhackett1024@gmail.com>
Thu, 05 Jan 2012 07:01:18 -0800
changeset 86328 d9011e124a959f0acc35bff27fdf3239bc53a8ff
parent 86327 1a8a06e6c634608db279ebf9a4719add45549f75
child 86329 1f35778a02a8f98bf45fe0ffe0fcc0b4039ded60
push idunknown
push userunknown
push dateunknown
reviewersdvander
bugs714645
milestone12.0a1
Add liveness intervals to indicate variable writes within try blocks, bug 714645. r=dvander
js/src/jit-test/tests/jaeger/bug714645.js
js/src/jsanalyze.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/jaeger/bug714645.js
@@ -0,0 +1,12 @@
+
+function testAddInconvertibleObjectAny() {
+  var count = 0;
+  function toString() {  }
+  try {
+    for (var i = 0; i < 100; i++)
+        var q = count[count] && this ? testAddInconvertibleObjectAny : ++toString;
+  }  catch (e)  {
+    var dbg = count(toString);
+  }
+}
+testAddInconvertibleObjectAny();
--- a/js/src/jsanalyze.cpp
+++ b/js/src/jsanalyze.cpp
@@ -955,34 +955,44 @@ ScriptAnalysis::killVariable(JSContext *
             setOOM(cx);
             return;
         }
         var.saved->write = true;
         var.savedEnd = 0;
         return;
     }
 
-    if (var.ensured)
-        return;
-
-    JS_ASSERT(offset < var.lifetime->start);
+    JS_ASSERT_IF(!var.ensured, offset < var.lifetime->start);
+    unsigned start = var.lifetime->start;
 
     /*
      * The variable is considered to be live at the bytecode which kills it
      * (just not at earlier bytecodes). This behavior is needed by downstream
      * register allocation (see FrameState::bestEvictReg).
      */
     var.lifetime->start = offset;
     var.lifetime->write = true;
 
-    var.saved = var.lifetime;
-    var.savedEnd = 0;
-    var.lifetime = NULL;
+    if (var.ensured) {
+        /*
+         * The variable is live even before the write, due to an enclosing try
+         * block. We need to split the lifetime to indicate there was a write.
+         */
+        var.lifetime = cx->typeLifoAlloc().new_<Lifetime>(start, offset, var.lifetime);
+        if (!var.lifetime) {
+            setOOM(cx);
+            return;
+        }
+    } else {
+        var.saved = var.lifetime;
+        var.savedEnd = 0;
+        var.lifetime = NULL;
 
-    saved[savedCount++] = &var;
+        saved[savedCount++] = &var;
+    }
 }
 
 inline void
 ScriptAnalysis::extendVariable(JSContext *cx, LifetimeVariable &var,
                                unsigned start, unsigned end)
 {
     JS_ASSERT(var.lifetime);
     if (var.ensured) {