Bug 951722 - Add asserts that hash table postbarriers are working for new type objects r=terrence
authorJon Coppeard <jcoppeard@mozilla.com>
Fri, 20 Dec 2013 09:34:00 +0000
changeset 171794 4a1ec6b78880f225edffc6a3a90d696f4aab7ae9
parent 171793 4587af159a9ea86f81c49ad34a35e0c60b12b257
child 171795 56d3a3f8bb7c41d0d999031738995018f766464a
push id5166
push userlsblakk@mozilla.com
push dateTue, 04 Feb 2014 01:47:54 +0000
treeherdermozilla-aurora@977eb2548b2d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence
bugs951722
milestone29.0a1
Bug 951722 - Add asserts that hash table postbarriers are working for new type objects r=terrence
js/src/gc/Nursery.cpp
js/src/gc/StoreBuffer.cpp
js/src/jscompartment.h
js/src/jsinfer.cpp
--- a/js/src/gc/Nursery.cpp
+++ b/js/src/gc/Nursery.cpp
@@ -586,16 +586,29 @@ ShouldMoveToTenured(MinorCollectionTrace
 /* static */ void
 js::Nursery::MinorGCCallback(JSTracer *jstrc, void **thingp, JSGCTraceKind kind)
 {
     MinorCollectionTracer *trc = static_cast<MinorCollectionTracer *>(jstrc);
     if (ShouldMoveToTenured(trc, thingp))
         *thingp = trc->nursery->moveToTenured(trc, static_cast<JSObject *>(*thingp));
 }
 
+static void
+CheckHashTablesAfterMovingGC(JSRuntime *rt)
+{
+#if defined(DEBUG)
+    /* Check that internal hash tables no longer have any pointers into the nursery. */
+    for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) {
+        c->checkNewTypeObjectTableAfterMovingGC();
+        if (c->debugScopes)
+            c->debugScopes->checkHashTablesAfterMovingGC(rt);
+    }
+#endif
+}
+
 void
 js::Nursery::collect(JSRuntime *rt, JS::gcreason::Reason reason, TypeObjectList *pretenureTypes)
 {
     JS_AbortIfWrongThread(rt);
 
     if (rt->mainThread.suppressGC)
         return;
 
@@ -607,16 +620,17 @@ js::Nursery::collect(JSRuntime *rt, JS::
 
     AutoStopVerifyingBarriers av(rt, false);
 
     rt->gcHelperThread.waitBackgroundSweepEnd();
 
     /* Move objects pointed to by roots from the nursery to the major heap. */
     MinorCollectionTracer trc(rt, this);
     rt->gcStoreBuffer.mark(&trc); // This must happen first.
+    CheckHashTablesAfterMovingGC(rt);
     MarkRuntime(&trc);
     Debugger::markAll(&trc);
     for (CompartmentsIter comp(rt, SkipAtoms); !comp.done(); comp.next()) {
         comp->markAllCrossCompartmentWrappers(&trc);
         comp->markAllInitialShapeTableEntries(&trc);
     }
     rt->newObjectCache.clearNurseryObjects(rt);
 
--- a/js/src/gc/StoreBuffer.cpp
+++ b/js/src/gc/StoreBuffer.cpp
@@ -285,23 +285,16 @@ StoreBuffer::mark(JSTracer *trc)
 
     bufferVal.mark(this, trc);
     bufferCell.mark(this, trc);
     bufferSlot.mark(this, trc);
     bufferWholeCell.mark(this, trc);
     bufferRelocVal.mark(this, trc);
     bufferRelocCell.mark(this, trc);
     bufferGeneric.mark(this, trc);
-
-#if defined(DEBUG)
-    for (CompartmentsIter c(runtime_, SkipAtoms); !c.done(); c.next()) {
-        if (c->debugScopes)
-            c->debugScopes->checkHashTablesAfterMovingGC(runtime_);
-    }
-#endif
 }
 
 void
 StoreBuffer::setAboutToOverflow()
 {
     aboutToOverflow_ = true;
     runtime_->triggerOperationCallback(JSRuntime::TriggerCallbackMainThread);
 }
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -242,16 +242,19 @@ struct JSCompartment
     js::InitialShapeSet          initialShapes;
     void sweepInitialShapeTable();
     void markAllInitialShapeTableEntries(JSTracer *trc);
 
     /* Set of default 'new' or lazy types in the compartment. */
     js::types::TypeObjectWithNewScriptSet newTypeObjects;
     js::types::TypeObjectWithNewScriptSet lazyTypeObjects;
     void sweepNewTypeObjectTable(js::types::TypeObjectWithNewScriptSet &table);
+#if defined(DEBUG) && defined(JSGC_GENERATIONAL)
+    void checkNewTypeObjectTableAfterMovingGC();
+#endif
 
     /*
      * Hash table of all manually call site-cloned functions from within
      * self-hosted code. Cloning according to call site provides extra
      * sensitivity for type specialization and inlining.
      */
     js::CallsiteCloneTable callsiteClones;
     void sweepCallsiteClones();
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -3955,16 +3955,39 @@ ExclusiveContext::getNewType(const Class
             AddTypeProperty(this, type, "columnNumber", types::Type::Int32Type());
             AddTypeProperty(this, type, "stack", types::Type::StringType());
         }
     }
 
     return type;
 }
 
+#if defined(DEBUG) && defined(JSGC_GENERATIONAL)
+void
+JSCompartment::checkNewTypeObjectTableAfterMovingGC()
+{
+    /*
+     * Assert that the postbarriers have worked and that nothing is left in
+     * newTypeObjects that points into the nursery, and that the hash table
+     * entries are discoverable.
+     */
+    JS::shadow::Runtime *rt = JS::shadow::Runtime::asShadowRuntime(runtimeFromMainThread());
+    for (TypeObjectWithNewScriptSet::Enum e(newTypeObjects); !e.empty(); e.popFront()) {
+        TypeObjectWithNewScriptEntry entry = e.front();
+        JS_ASSERT(!IsInsideNursery(rt, entry.newFunction));
+        TaggedProto proto = entry.object->proto();
+        JS_ASSERT_IF(proto.isObject(), !IsInsideNursery(rt, proto.toObject()));
+        TypeObjectWithNewScriptEntry::Lookup
+            lookup(entry.object->clasp(), proto, entry.newFunction);
+        TypeObjectWithNewScriptSet::Ptr ptr = newTypeObjects.lookup(lookup);
+        JS_ASSERT(ptr.found() && &*ptr == &e.front());
+    }
+}
+#endif
+
 TypeObject *
 ExclusiveContext::getLazyType(const Class *clasp, TaggedProto proto)
 {
     JS_ASSERT_IF(proto.isObject(), compartment() == proto.toObject()->compartment());
 
     AutoEnterAnalysis enter(this);
 
     TypeObjectWithNewScriptSet &table = compartment()->lazyTypeObjects;