Bug 1124563 - Fixup base shape table after moving GC r=terrence a=sylvestre
authorJon Coppeard <jcoppeard@mozilla.com>
Thu, 29 Jan 2015 09:58:06 +0000
changeset 243691 5eae334a2b31
parent 243690 e7fd0d7ff120
child 243692 18d9d9422db6
push id4438
push userjcoppeard@mozilla.com
push date2015-02-05 15:19 +0000
treeherdermozilla-beta@5eae334a2b31 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence, sylvestre
bugs1124563
milestone36.0
Bug 1124563 - Fixup base shape table after moving GC r=terrence a=sylvestre
js/src/jit-test/tests/gc/bug-1124563.js
js/src/jscompartment.cpp
js/src/jscompartment.h
js/src/vm/Shape.cpp
js/src/vm/Shape.h
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/gc/bug-1124563.js
@@ -0,0 +1,4 @@
+try {
+    gc(0, 'shrinking')({x: 0})
+} catch (e) {}
+eval("({x: 0, x: 0})[{x: 0}]")
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -655,16 +655,17 @@ JSCompartment::sweepCrossCompartmentWrap
 #ifdef JSGC_COMPACTING
 
 void JSCompartment::fixupAfterMovingGC()
 {
     fixupGlobal();
     fixupNewTypeObjectTable(newTypeObjects);
     fixupNewTypeObjectTable(lazyTypeObjects);
     fixupInitialShapeTable();
+    fixupBaseShapeTable();
 }
 
 void
 JSCompartment::fixupGlobal()
 {
     GlobalObject *global = *global_.unsafeGet();
     if (global)
         global_.set(MaybeForwarded(global));
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -393,16 +393,17 @@ struct JSCompartment
     void purge();
     void clearTables();
 
 #ifdef JSGC_COMPACTING
     void fixupInitialShapeTable();
     void fixupNewTypeObjectTable(js::types::TypeObjectWithNewScriptSet &table);
     void fixupAfterMovingGC();
     void fixupGlobal();
+    void fixupBaseShapeTable();
 #endif
 
     bool hasObjectMetadataCallback() const { return objectMetadataCallback; }
     void setObjectMetadataCallback(js::ObjectMetadataCallback callback);
     void forgetObjectMetadataCallback() {
         objectMetadataCallback = nullptr;
     }
     bool callObjectMetadataCallback(JSContext *cx, JSObject **obj) const {
--- a/js/src/vm/Shape.cpp
+++ b/js/src/vm/Shape.cpp
@@ -1579,28 +1579,66 @@ BaseShape::assertConsistency()
         UnownedBaseShape *unowned = baseUnowned();
         MOZ_ASSERT(getObjectParent() == unowned->getObjectParent());
         MOZ_ASSERT(getObjectMetadata() == unowned->getObjectMetadata());
         MOZ_ASSERT(getObjectFlags() == unowned->getObjectFlags());
     }
 #endif
 }
 
+#ifdef JSGC_COMPACTING
+
+bool
+BaseShape::fixupBaseShapeTableEntry()
+{
+    bool updated = false;
+    if (parent && IsForwarded(parent.get())) {
+        parent = Forwarded(parent.get());
+        updated = true;
+    }
+    if (metadata && IsForwarded(metadata.get())) {
+        metadata = Forwarded(metadata.get());
+        updated = true;
+    }
+    return updated;
+}
+
+void
+JSCompartment::fixupBaseShapeTable()
+{
+    if (!baseShapes.initialized())
+        return;
+
+    for (BaseShapeSet::Enum e(baseShapes); !e.empty(); e.popFront()) {
+        UnownedBaseShape *base = e.front().unbarrieredGet();
+        if (base->fixupBaseShapeTableEntry()) {
+            StackBaseShape sbase(base);
+            ReadBarriered<UnownedBaseShape *> b(base);
+            e.rekeyFront(base, b);
+        }
+    }
+}
+
+#endif
+
 void
 JSCompartment::sweepBaseShapeTable()
 {
-    if (baseShapes.initialized()) {
-        for (BaseShapeSet::Enum e(baseShapes); !e.empty(); e.popFront()) {
-            UnownedBaseShape *base = e.front().unbarrieredGet();
-            if (IsBaseShapeAboutToBeFinalizedFromAnyThread(&base)) {
-                e.removeFront();
-            } else if (base != e.front().unbarrieredGet()) {
-                ReadBarriered<UnownedBaseShape *> b(base);
-                e.rekeyFront(base, b);
-            }
+    if (!baseShapes.initialized())
+        return;
+
+    for (BaseShapeSet::Enum e(baseShapes); !e.empty(); e.popFront()) {
+        UnownedBaseShape *base = e.front().unbarrieredGet();
+        MOZ_ASSERT_IF(base->getObjectParent(), !IsForwarded(base->getObjectParent()));
+        MOZ_ASSERT_IF(base->getObjectMetadata(), !IsForwarded(base->getObjectMetadata()));
+        if (IsBaseShapeAboutToBeFinalizedFromAnyThread(&base)) {
+            e.removeFront();
+        } else if (base != e.front().unbarrieredGet()) {
+            ReadBarriered<UnownedBaseShape *> b(base);
+            e.rekeyFront(base, b);
         }
     }
 }
 
 #ifdef JSGC_HASH_TABLE_CHECKS
 
 void
 JSCompartment::checkBaseShapeTableAfterMovingGC()
--- a/js/src/vm/Shape.h
+++ b/js/src/vm/Shape.h
@@ -473,16 +473,17 @@ class BaseShape : public gc::TenuredCell
             gc::MarkObject(trc, &parent, "parent");
 
         if (metadata)
             gc::MarkObject(trc, &metadata, "metadata");
     }
 
 #ifdef JSGC_COMPACTING
     void fixupAfterMovingGC();
+    bool fixupBaseShapeTableEntry();
 #endif
 
   private:
     static void staticAsserts() {
         JS_STATIC_ASSERT(offsetof(BaseShape, clasp_) == offsetof(js::shadow::BaseShape, clasp_));
     }
 };