[INFER] Allow empty SSA stack values for scripts with switch and try blocks, bug 652314.
authorBrian Hackett <bhackett1024@gmail.com>
Sat, 23 Apr 2011 22:36:43 -0700
changeset 74975 460da05aa26f146bfe88815f788702aeda68329c
parent 74974 e044a9a69132c1df76297e2d3cfef8c0c49cfd53
child 74976 f394ef228e619fe6610a669902e65bdc2ea5bb17
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
bugs652314
milestone6.0a1
[INFER] Allow empty SSA stack values for scripts with switch and try blocks, bug 652314.
js/src/jit-test/tests/jaeger/bug652314.js
js/src/jsanalyze.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/jaeger/bug652314.js
@@ -0,0 +1,7 @@
+(function() {
+    for (a in [0]) {
+        try {
+            return
+        } catch(e) {}
+    }
+})()
--- a/js/src/jsanalyze.cpp
+++ b/js/src/jsanalyze.cpp
@@ -1534,19 +1534,32 @@ ScriptAnalysis::insertPhi(JSContext *cx,
     PodCopy(newOptions, node->options, node->length);
     node->options = newOptions;
     node->options[node->length++] = v;
 }
 
 inline void
 ScriptAnalysis::mergeValue(JSContext *cx, uint32 offset, const SSAValue &v, SlotValue *pv)
 {
-    JS_ASSERT(v.kind() != SSAValue::EMPTY && pv->value.kind() != SSAValue::EMPTY);
+    /* Make sure that v is accounted for in the pending value or phi value at pv. */
 
-    if (v.equals(pv->value))
+    /*
+     * Note: it would be nice to assert that v is also non-empty, but this can
+     * crop up when handling switch and try blocks. We don't track SSA values
+     * for variables in scripts containing these opcodes, and don't propagate
+     * the stack to all targets of the switch or try, under the assumption that
+     * code within the switch/try won't modify the stack. This assumption is
+     * not valid, however, when the script contains return statements within
+     * 'for in' blocks which then pop the stack with an ENDITER and clear out
+     * its contents before we get to the switch/try branch targets. This should
+     * be cleaned up.
+     */
+    JS_ASSERT(pv->value.kind() != SSAValue::EMPTY);
+
+    if (v.equals(pv->value) || v.kind() == SSAValue::EMPTY)
         return;
 
     if (pv->value.kind() != SSAValue::PHI || pv->value.phiOffset() < offset) {
         SSAValue ov = pv->value;
         if (makePhi(cx, pv->slot, offset, &pv->value)) {
             insertPhi(cx, pv->value, v);
             insertPhi(cx, pv->value, ov);
         }
@@ -1556,23 +1569,23 @@ ScriptAnalysis::mergeValue(JSContext *cx
     JS_ASSERT(pv->value.phiOffset() == offset);
     insertPhi(cx, pv->value, v);
 }
 
 void
 ScriptAnalysis::checkPendingValue(JSContext *cx, const SSAValue &v, uint32 slot,
                                   Vector<SlotValue> *pending)
 {
-    JS_ASSERT(v.kind() != SSAValue::EMPTY);
-
     for (unsigned i = 0; i < pending->length(); i++) {
         if ((*pending)[i].slot == slot)
             return;
     }
 
+    JS_ASSERT(v.kind() != SSAValue::EMPTY);
+
     if (!pending->append(SlotValue(slot, v)))
         setOOM(cx);
 }
 
 void
 ScriptAnalysis::mergeBranchTarget(JSContext *cx, const SSAValue &value, uint32 slot,
                                   const Vector<uint32> &branchTargets)
 {