Notify JS_CommenceRuntimeShutdown from CycleCollector (511522, r=graydon).
authorAndreas Gal <gal@mozilla.com>
Wed, 19 Aug 2009 15:13:02 -0700
changeset 31897 2e528cc8602a697b5c6fd63bdfe477ef8a997b7c
parent 31896 dc463a6bab6eb18f2e34a500624acf89c57998f3
child 31898 0307226048c86a41ad74b8d8be2c75c93763bf7c
push idunknown
push userunknown
push dateunknown
reviewersgraydon
bugs511522
milestone1.9.3a1pre
Notify JS_CommenceRuntimeShutdown from CycleCollector (511522, r=graydon).
js/src/jsapi.cpp
js/src/jstracer.cpp
js/src/xpconnect/src/nsXPConnect.cpp
js/src/xpconnect/src/xpcprivate.h
xpcom/base/nsCycleCollector.cpp
xpcom/base/nsCycleCollector.h
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -831,16 +831,19 @@ JS_NewRuntime(uint32 maxbytes)
 bad:
     JS_DestroyRuntime(rt);
     return NULL;
 }
 
 JS_PUBLIC_API(void)
 JS_CommenceRuntimeShutDown(JSRuntime *rt)
 {
+#ifdef DEBUG
+    fprintf(stderr, "JS_CommenceRuntimeShutDown\n");
+#endif
     rt->gcFlushCodeCaches = true;
 }
 
 JS_PUBLIC_API(void)
 JS_DestroyRuntime(JSRuntime *rt)
 {
 #ifdef DEBUG
     /* Don't hurt everyone in leaky ol' Mozilla with a fatal JS_ASSERT! */
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -2103,16 +2103,19 @@ oom:
      */
     tm->reservedDoublePoolPtr = tm->reservedDoublePool;
     return false;
 }
 
 void
 JSTraceMonitor::flush()
 {
+#ifdef DEBUG
+        fprintf(stderr, "JSTraceMonitor::flush()\n");
+#endif
     if (fragmento) {
         fragmento->clearFrags();
         for (size_t i = 0; i < FRAGMENT_TABLE_SIZE; ++i) {
             VMFragment* f = vmfragments[i];
             while (f) {
                 VMFragment* next = f->next;
                 fragmento->clearFragment(f);
                 f = next;
@@ -2139,16 +2142,19 @@ JSTraceMonitor::flush()
     lirbuf->clear();
     needFlush = JS_FALSE;
 }
 
 void
 JSTraceMonitor::mark(JSTracer* trc)
 {
     if (!trc->context->runtime->gcFlushCodeCaches) {
+#ifdef DEBUG
+        fprintf(stderr, "JSTraceMonitor::mark()\n");
+#endif
         for (size_t i = 0; i < FRAGMENT_TABLE_SIZE; ++i) {
             VMFragment* f = vmfragments[i];
             while (f) {
                 TreeInfo* ti = (TreeInfo*)f->vmprivate;
                 if (ti) {
                     jsval* vp = ti->gcthings.data();
                     unsigned len = ti->gcthings.length();
                     while (len--) {
--- a/js/src/xpconnect/src/nsXPConnect.cpp
+++ b/js/src/xpconnect/src/nsXPConnect.cpp
@@ -127,25 +127,22 @@ nsXPConnect::nsXPConnect()
 nsXPConnect::~nsXPConnect()
 {
     NS_ASSERTION(!mCycleCollectionContext,
                  "Didn't call FinishCycleCollection?");
     nsCycleCollector_forgetRuntime(nsIProgrammingLanguage::JAVASCRIPT);
 
     JSContext *cx = nsnull;
     if (mRuntime) {
-        // Tell the JS engine that we are about to destroy the runtime.
-        JSRuntime *rt = mRuntime->GetJSRuntime();
-        JS_CommenceRuntimeShutDown(rt);
         // Create our own JSContext rather than an XPCCallContext, since
         // otherwise we will create a new safe JS context and attach a
         // components object that won't get GCed.
         // And do this before calling CleanupAllThreads, so that we
         // don't create an extra xpcPerThreadData.
-        cx = JS_NewContext(rt, 8192);
+        cx = JS_NewContext(mRuntime->GetJSRuntime(), 8192);
     }
 
     XPCPerThreadData::CleanupAllThreads();
     mShuttingDown = JS_TRUE;
     if (cx) {
         JS_BeginRequest(cx);
 
         // XXX Call even if |mRuntime| null?
@@ -602,16 +599,26 @@ nsXPConnect::FinishCycleCollection()
 }
 
 nsCycleCollectionParticipant *
 nsXPConnect::ToParticipant(void *p)
 {
     return this;
 }
 
+void
+nsXPConnect::CommenceShutdown()
+{
+#ifdef DEBUG
+    fprintf(stderr, "nsXPConnect::CommenceShutdown()\n");
+#endif
+    // Tell the JS engine that we are about to destroy the runtime.
+    JS_CommenceRuntimeShutDown(mRuntime->GetJSRuntime());
+}
+
 NS_IMETHODIMP
 nsXPConnect::RootAndUnlinkJSObjects(void *p)
 {
     return NS_OK;
 }
 
 #ifdef DEBUG_CC
 void
--- a/js/src/xpconnect/src/xpcprivate.h
+++ b/js/src/xpconnect/src/xpcprivate.h
@@ -521,16 +521,17 @@ public:
     NS_IMETHOD Unroot(void *p);
     NS_IMETHOD Traverse(void *p,
                         nsCycleCollectionTraversalCallback &cb);
     
     // nsCycleCollectionLanguageRuntime
     virtual nsresult BeginCycleCollection(nsCycleCollectionTraversalCallback &cb);
     virtual nsresult FinishCycleCollection();
     virtual nsCycleCollectionParticipant *ToParticipant(void *p);
+    virtual void CommenceShutdown();
     virtual PRBool Collect();
 #ifdef DEBUG_CC
     virtual void PrintAllReferencesTo(void *p);
 #endif
 
     // We should not trace XPConnect JS roots when tracing the graph for the
     // cycle collector. Those should be traced from the XPCOM objects that hold
     // them when we know that they won't be collected by the cycle collector.
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -933,16 +933,20 @@ struct nsCycleCollectionXPCOMRuntime :
 
     nsresult FinishCycleCollection() 
     {
         return NS_OK;
     }
 
     inline nsCycleCollectionParticipant *ToParticipant(void *p);
 
+    void CommenceShutdown()
+    {
+    }
+
 #ifdef DEBUG_CC
     virtual void PrintAllReferencesTo(void *p) {}
 #endif
 };
 
 struct nsCycleCollector
 {
     PRBool mCollectionInProgress;
@@ -2623,16 +2627,21 @@ nsCycleCollector::SuspectedCount()
 }
 
 void
 nsCycleCollector::Shutdown()
 {
     // Here we want to run a final collection and then permanently
     // disable the collector because the program is shutting down.
 
+    for (PRUint32 i = 0; i <= nsIProgrammingLanguage::MAX; ++i) {
+        if (mRuntimes[i])
+            mRuntimes[i]->CommenceShutdown();
+    }
+
     Collect(SHUTDOWN_COLLECTIONS(mParams));
 
 #ifdef DEBUG_CC
     GCGraphBuilder builder(mGraph, mRuntimes);
     mScanInProgress = PR_TRUE;
     SelectPurple(builder);
     mScanInProgress = PR_FALSE;
     if (builder.Count() != 0) {
--- a/xpcom/base/nsCycleCollector.h
+++ b/xpcom/base/nsCycleCollector.h
@@ -49,16 +49,17 @@ class nsCycleCollectionTraversalCallback
 // An nsCycleCollectionLanguageRuntime is a per-language object that
 // implements language-specific aspects of the cycle collection task.
 
 struct nsCycleCollectionLanguageRuntime
 {
     virtual nsresult BeginCycleCollection(nsCycleCollectionTraversalCallback &cb) = 0;
     virtual nsresult FinishCycleCollection() = 0;
     virtual nsCycleCollectionParticipant *ToParticipant(void *p) = 0;
+    virtual void CommenceShutdown() = 0;
 #ifdef DEBUG_CC
     virtual void PrintAllReferencesTo(void *p) = 0;
 #endif
 };
 
 nsresult nsCycleCollector_startup();
 // Returns the number of collected nodes.
 NS_COM PRUint32 nsCycleCollector_collect();