[INFER] Don't mark type as synced after writing known-undefined values to locals, bug 655508.
authorBrian Hackett <bhackett1024@gmail.com>
Mon, 09 May 2011 10:56:54 -0700
changeset 75009 66f61893f67d5d6a384cee93f855c097902876e7
parent 75008 16ae7aed77f3e55851fc9179c9fa674aee467bd6
child 75010 c14db8ce8f48e473868e56dc436ad79db7a7984d
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
bugs655508
milestone6.0a1
[INFER] Don't mark type as synced after writing known-undefined values to locals, bug 655508.
js/src/jit-test/tests/jaeger/bug655508.js
js/src/methodjit/FrameState.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/jaeger/bug655508.js
@@ -0,0 +1,15 @@
+switch (3) {
+case
+    function () {
+        var x;
+        (function () {})() && false;
+        x = undefined;
+        try {
+            JSON.parse(x)
+        } catch (e) {}
+    }([]):
+case
+    function () {
+        [typeof loopa1]
+    }(0):
+}
--- a/js/src/methodjit/FrameState.cpp
+++ b/js/src/methodjit/FrameState.cpp
@@ -2112,21 +2112,27 @@ FrameState::storeTop(FrameEntry *target)
     if (top->isCopy() && top->copyOf() == target) {
         JS_ASSERT(target->isCopied());
         return;
     }
 
     /*
      * If this is overwriting a known non-double type with another value of the
      * same type, then make sure we keep the type marked as synced after doing
-     * the copy.
+     * the copy. Skip this for variables with undefined type --- for locals
+     * with no use-before-def, the initial undefined type is not synced but is
+     * marked as synced. If the local is then written with a known-undefined
+     * value, we need to make sure the in-memory type gets updated.
      */
     bool wasSynced = target->type.synced();
     JSValueType oldType = target->isTypeKnown() ? target->getKnownType() : JSVAL_TYPE_UNKNOWN;
-    bool trySyncType = wasSynced && oldType != JSVAL_TYPE_UNKNOWN && oldType != JSVAL_TYPE_DOUBLE;
+    bool trySyncType = wasSynced &&
+        oldType != JSVAL_TYPE_UNKNOWN &&
+        oldType != JSVAL_TYPE_DOUBLE &&
+        oldType != JSVAL_TYPE_UNDEFINED;
 
     /* Completely invalidate the local variable. */
     forgetEntry(target);
     target->resetUnsynced();
 
     /* Constants are easy to propagate. */
     if (top->isConstant()) {
         target->clear();