Bug 1144738 - Check for invalidated script when updating SetPropertyIC cache r=jandem
authorJon Coppeard <jcoppeard@mozilla.com>
Wed, 25 Mar 2015 10:49:52 +0000
changeset 265803 1550b7322e45cc67ca53af2281608bede1cf3f2c
parent 265802 7cf3406ac1cd9977cb0da4c96f00c1db69230c04
child 265804 4b576200b148d2f02afed6df6c013b7fb2fdd1e1
push id830
push userraliiev@mozilla.com
push dateFri, 19 Jun 2015 19:24:37 +0000
treeherdermozilla-release@932614382a68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1144738
milestone39.0a1
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 1144738 - Check for invalidated script when updating SetPropertyIC cache r=jandem
js/src/jit-test/tests/gc/bug-1144738.js
js/src/jit/IonCaches.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/gc/bug-1144738.js
@@ -0,0 +1,32 @@
+// |jit-test| error: ReferenceError; --fuzzing-safe; --thread-count=1; --ion-eager
+const ALL_TESTS =  [
+    "CONTEXT_OBJECT_PROPERTY_DOT_REFERENCE_IS_FUNCTION",
+    ];
+function r(keyword, tests) {
+  function Reserved(keyword, tests) {
+    this.keyword = keyword;
+    if (tests)
+      this.tests = tests;
+    else
+      this.tests = ALL_TESTS;
+  }
+  return new Reserved(keyword, tests);
+}
+for (var i = 2; i >= 0; i--) {
+  gc();
+  gczeal(14, 17);
+  [
+    r("break"),
+    r("case"),
+    r("catch"),
+    r("continue"),
+    ];
+  [
+    r("true"),
+    r("null"),
+    r("each"),
+    r("let")
+    ];
+}
+Failure;
+
--- a/js/src/jit/IonCaches.cpp
+++ b/js/src/jit/IonCaches.cpp
@@ -3266,35 +3266,41 @@ SetPropertyIC::update(JSContext *cx, Han
         if (UnboxedExpandoObject *expando = obj->as<UnboxedPlainObject>().maybeExpando())
             oldShape = expando->lastProperty();
     }
 
     // Set/Add the property on the object, the inlined cache are setup for the next execution.
     if (!SetProperty(cx, obj, name, value, cache.strict(), cache.pc()))
         return false;
 
-    // The property did not exist before, now we can try to inline the property add.
-    bool checkTypeset;
-    if (!addedSetterStub && canCache == MaybeCanAttachAddSlot &&
-        IsPropertyAddInlineable(&obj->as<NativeObject>(), id, cache.value(), oldShape,
-                                cache.needsTypeBarrier(), &checkTypeset))
-    {
-        if (!cache.attachAddSlot(cx, outerScript, ion, obj, oldShape, oldGroup, checkTypeset))
-            return false;
-        addedSetterStub = true;
-    }
-
-    checkTypeset = false;
-    if (!addedSetterStub && cache.canAttachStub() &&
-        CanAttachAddUnboxedExpando(cx, obj, oldShape, id, cache.value(),
-                                   cache.needsTypeBarrier(), &checkTypeset))
-    {
-        if (!cache.attachAddSlot(cx, outerScript, ion, obj, oldShape, oldGroup, checkTypeset))
-            return false;
-        addedSetterStub = true;
+    // A GC may have caused cache.value() to become stale as it is not traced.
+    // In this case the IonScript will have been invalidated, so check for that.
+    // Assert no further GC is possible past this point.
+    JS::AutoAssertNoAlloc nogc;
+    if (!ion->invalidated()) {
+        // The property did not exist before, now we can try to inline the property add.
+        bool checkTypeset;
+        if (!addedSetterStub && canCache == MaybeCanAttachAddSlot &&
+            IsPropertyAddInlineable(&obj->as<NativeObject>(), id, cache.value(), oldShape,
+                                    cache.needsTypeBarrier(), &checkTypeset))
+        {
+            if (!cache.attachAddSlot(cx, outerScript, ion, obj, oldShape, oldGroup, checkTypeset))
+                return false;
+            addedSetterStub = true;
+        }
+
+        checkTypeset = false;
+        if (!addedSetterStub && cache.canAttachStub() &&
+            CanAttachAddUnboxedExpando(cx, obj, oldShape, id, cache.value(),
+                                       cache.needsTypeBarrier(), &checkTypeset))
+        {
+            if (!cache.attachAddSlot(cx, outerScript, ion, obj, oldShape, oldGroup, checkTypeset))
+                return false;
+            addedSetterStub = true;
+        }
     }
 
     if (!addedSetterStub)
         JitSpew(JitSpew_IonIC, "Failed to attach SETPROP cache");
 
     return true;
 }