Bug 566637 - TM: "this.a" reads from stale global object slots after global variable "a" changes value. r=gal.
authorJason Orendorff <jorendorff@mozilla.com>
Mon, 26 Jul 2010 18:19:23 -0500
changeset 48588 e0bc614d6ac250740766c1f458444a16c09ecb17
parent 48587 a0fd2ad3ac95ebe2c0256c4bf4bf0b712e8e28fa
child 48589 ff6cf05b19f1d41b85542c3def35d90d72e76c6c
push id14748
push userrsayre@mozilla.com
push dateSun, 01 Aug 2010 00:33:23 +0000
treeherdermozilla-central@f0df797bb2a9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgal
bugs566637
milestone2.0b2pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 566637 - TM: "this.a" reads from stale global object slots after global variable "a" changes value. r=gal.
js/src/jstracer.cpp
js/src/trace-test/tests/basic/bug566637.js
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -9285,19 +9285,26 @@ JS_REQUIRES_STACK RecordingStatus
 TraceRecorder::guardShape(LIns* obj_ins, JSObject* obj, uint32 shape, const char* guardName,
                           VMSideExit* exit)
 {
     // Test (with add if missing) for a remembered guard for (obj_ins, obj).
     GuardedShapeTable::AddPtr p = guardedShapeTable.lookupForAdd(obj_ins);
     if (p) {
         JS_ASSERT(p->value == obj);
         return RECORD_CONTINUE;
-    } else {
-        if (!guardedShapeTable.add(p, obj_ins, obj))
-            return RECORD_ERROR;
+    }
+    if (!guardedShapeTable.add(p, obj_ins, obj))
+        return RECORD_ERROR;
+
+    if (obj == globalObj) {
+        // In this case checking object identity is equivalent and faster.
+        guard(true,
+              addName(lir->ins2(LIR_eqp, obj_ins, INS_CONSTOBJ(globalObj)), "guard_global"),
+              exit);
+        return RECORD_CONTINUE;
     }
 
 #if defined DEBUG_notme && defined XP_UNIX
     DumpShape(obj, "guard");
     fprintf(shapefp, "for obj_ins %p\n", obj_ins);
 #endif
 
     // Finally, emit the shape guard.
@@ -13579,17 +13586,26 @@ TraceRecorder::propTail(JSObject* obj, L
          * we can "teleport" directly to obj2 by embedding it as a constant
          * (this constant object instruction will be CSE'ed with the constant
          * emitted by test_property_cache, whose shape is guarded).
          */
         obj_ins = (obj2 == obj->getProto()) ? stobj_get_proto(obj_ins) : INS_CONSTOBJ(obj2);
         obj = obj2;
     }
 
-    LIns *v_ins = unbox_slot(obj, obj_ins, slot, snapshot(BRANCH_EXIT));
+    LIns* v_ins;
+    if (obj2 == globalObj) {
+        if (isMethod)
+            RETURN_STOP("get global method");
+        if (!lazilyImportGlobalSlot(slot))
+            RETURN_STOP("lazy import of global slot failed");
+        v_ins = get(&globalObj->getSlotRef(slot));
+    } else {
+        v_ins = unbox_slot(obj, obj_ins, slot, snapshot(BRANCH_EXIT));
+    }
 
     /*
      * Joined function object stored as a method must be cloned when extracted
      * as a property value other than a callee. Note that shapes cover method
      * value as well as other property attributes and order, so this condition
      * is trace-invariant.
      *
      * We do not impose the method read barrier if in an imacro, assuming any
new file mode 100644
--- /dev/null
+++ b/js/src/trace-test/tests/basic/bug566637.js
@@ -0,0 +1,5 @@
+for (var j = 0; j < 9; j++) {
+    var a = j;
+    var b = this.a;
+}
+assertEq(b, 8);