From 02c8e710e7f96f7ff656e032bc78ebb55098d4c4 Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Fri, 7 Mar 2014 15:28:48 -0800 Subject: [PATCH] Bug 983399 - Make mozComponentLoader work with moving GC; r=sfink --HG-- extra : rebase_source : d5d04949c97be80bdf2212f82493686bd4a6cb28 --- js/xpconnect/loader/mozJSComponentLoader.cpp | 86 ++++++++++++++------ js/xpconnect/loader/mozJSComponentLoader.h | 25 +++--- 2 files changed, 78 insertions(+), 33 deletions(-) diff --git a/js/xpconnect/loader/mozJSComponentLoader.cpp b/js/xpconnect/loader/mozJSComponentLoader.cpp index 1dea5ebecea5..b66176fbcd66 100644 --- a/js/xpconnect/loader/mozJSComponentLoader.cpp +++ b/js/xpconnect/loader/mozJSComponentLoader.cpp @@ -309,7 +309,6 @@ mozJSComponentLoader::mozJSComponentLoader() mModules(32), mImports(32), mInProgressImports(32), - mThisObjects(32), mInitialized(false), mReuseLoaderGlobal(false) { @@ -342,6 +341,36 @@ NS_IMPL_ISUPPORTS3(mozJSComponentLoader, xpcIJSModuleLoader, nsIObserver) +static void +TraceComponentLoader(JSTracer* trc, void* data) +{ + auto loader = mozJSComponentLoader::Get(); + if (loader) { + MOZ_ASSERT(data == loader); + loader->Trace(trc); + } +} + +void +mozJSComponentLoader::Trace(JSTracer *trc) +{ + if (!mInitialized || !mThisObjects.initialized()) { + return; + } + + if (!mReuseLoaderGlobal) { + MOZ_ASSERT(mThisObjects.empty()); + return; + } + + for (ThisObjectsMap::Range r = mThisObjects.all(); !r.empty(); r.popFront()) { + JS_CallScriptTracer(trc, const_cast(&r.front().key()), + "mozJSComponentLoader::mThisObjects key"); + JS_CallHeapObjectTracer(trc, &r.front().value(), + "mozJSComponentLoader::mThisObjects value"); + } +} + nsresult mozJSComponentLoader::ReallyInit() { @@ -366,6 +395,12 @@ mozJSComponentLoader::ReallyInit() NS_FAILED(rv = mRuntimeService->GetRuntime(&mRuntime))) return rv; + if (!mThisObjects.init(32)) + return NS_ERROR_OUT_OF_MEMORY; + + if (!JS_AddExtraGCRootsTracer(mRuntime, TraceComponentLoader, this)) + return NS_ERROR_OUT_OF_MEMORY; + // Create our compilation context. mContext = JS_NewContext(mRuntime, 256); if (!mContext) @@ -415,7 +450,7 @@ mozJSComponentLoader::LoadModule(FileLocation &aFile) if (mModules.Get(spec, &mod)) return mod; - nsAutoPtr entry(new ModuleEntry); + nsAutoPtr entry(new ModuleEntry(mContext)); JSAutoRequest ar(mContext); RootedValue dummy(mContext); @@ -524,7 +559,10 @@ mozJSComponentLoader::FindTargetObject(JSContext* aCx, JSScript* script = js::GetOutermostEnclosingFunctionOfScriptedCaller(aCx); if (script) { - targetObject = mThisObjects.Get(script); + ThisObjectsMap::Ptr p = mThisObjects.lookup(script); + if (p.found()) { + targetObject = p->value(); + } } } @@ -562,11 +600,13 @@ mozJSComponentLoader::FindTargetObject(JSContext* aCx, void mozJSComponentLoader::NoteSubScript(HandleScript aScript, HandleObject aThisObject) { - if (!mInitialized && NS_FAILED(ReallyInit())) { - MOZ_CRASH(); - } + if (!mInitialized && NS_FAILED(ReallyInit())) { + MOZ_CRASH(); + } - mThisObjects.Put(aScript, aThisObject); + if (mReuseLoaderGlobal && !mThisObjects.put(aScript, aThisObject)) { + MOZ_CRASH(); + } } /* static */ size_t @@ -595,7 +635,7 @@ mozJSComponentLoader::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) amount += mModules.SizeOfExcludingThis(DataEntrySizeOfExcludingThis, aMallocSizeOf); amount += mImports.SizeOfExcludingThis(ClassEntrySizeOfExcludingThis, aMallocSizeOf); amount += mInProgressImports.SizeOfExcludingThis(DataEntrySizeOfExcludingThis, aMallocSizeOf); - amount += mThisObjects.SizeOfExcludingThis(nullptr, aMallocSizeOf); + amount += mThisObjects.sizeOfExcludingThis(aMallocSizeOf); return amount; } @@ -740,8 +780,8 @@ mozJSComponentLoader::PrepareObjectForLocation(JSCLContextHelper& aCx, nsresult mozJSComponentLoader::ObjectForLocation(nsIFile *aComponentFile, nsIURI *aURI, - JSObject **aObject, - JSScript **aTableScript, + JS::MutableHandle aObject, + JS::MutableHandle aTableScript, char **aLocation, bool aPropagateExceptions, MutableHandleValue aException) @@ -988,7 +1028,7 @@ mozJSComponentLoader::ObjectForLocation(nsIFile *aComponentFile, // Assign aObject here so that it's available to recursive imports. // See bug 384168. - *aObject = obj; + aObject.set(obj); RootedScript tableScript(cx, script); if (!tableScript) { @@ -996,12 +1036,14 @@ mozJSComponentLoader::ObjectForLocation(nsIFile *aComponentFile, MOZ_ASSERT(tableScript); } - *aTableScript = tableScript; + aTableScript.set(tableScript); // tableScript stays in the table until shutdown. To avoid it being // collected and another script getting the same address, we root // tableScript lower down in this function. - mThisObjects.Put(tableScript, obj); + if (mReuseLoaderGlobal && !mThisObjects.put(tableScript, JS::Heap(obj))) { + return NS_ERROR_OUT_OF_MEMORY; + } bool ok = false; { @@ -1021,23 +1063,21 @@ mozJSComponentLoader::ObjectForLocation(nsIFile *aComponentFile, JS_GetPendingException(cx, aException); JS_ClearPendingException(cx); } - *aObject = nullptr; - *aTableScript = nullptr; - mThisObjects.Remove(tableScript); + aObject.set(nullptr); + aTableScript.set(nullptr); + mThisObjects.remove(tableScript); return NS_ERROR_FAILURE; } /* Freed when we remove from the table. */ *aLocation = ToNewCString(nativePath); if (!*aLocation) { - *aObject = nullptr; - *aTableScript = nullptr; - mThisObjects.Remove(tableScript); + aObject.set(nullptr); + aTableScript.set(nullptr); + mThisObjects.remove(tableScript); return NS_ERROR_OUT_OF_MEMORY; } - JS_AddNamedObjectRoot(cx, aObject, *aLocation); - JS_AddNamedScriptRoot(cx, aTableScript, *aLocation); return NS_OK; } @@ -1070,7 +1110,7 @@ mozJSComponentLoader::UnloadModules() mInProgressImports.Clear(); mImports.Clear(); - mThisObjects.Clear(); + mThisObjects.clear(); mModules.Enumerate(ClearModules, nullptr); @@ -1219,7 +1259,7 @@ mozJSComponentLoader::ImportInto(const nsACString &aLocation, ModuleEntry* mod; nsAutoPtr newEntry; if (!mImports.Get(key, &mod) && !mInProgressImports.Get(key, &mod)) { - newEntry = new ModuleEntry; + newEntry = new ModuleEntry(callercx); if (!newEntry) return NS_ERROR_OUT_OF_MEMORY; mInProgressImports.Put(key, newEntry); diff --git a/js/xpconnect/loader/mozJSComponentLoader.h b/js/xpconnect/loader/mozJSComponentLoader.h index f46e81feeb0d..39347723f792 100644 --- a/js/xpconnect/loader/mozJSComponentLoader.h +++ b/js/xpconnect/loader/mozJSComponentLoader.h @@ -17,6 +17,8 @@ #include "nsCxPusher.h" #include "nsDataHashtable.h" #include "jsapi.h" +#include "js/HashTable.h" +#include "js/RootingAPI.h" #include "xpcIJSGetFactory.h" @@ -59,6 +61,8 @@ class mozJSComponentLoader : public mozilla::ModuleLoader, size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf); + void Trace(JSTracer *trc); + protected: static mozJSComponentLoader* sSelf; @@ -73,8 +77,8 @@ class mozJSComponentLoader : public mozilla::ModuleLoader, nsresult ObjectForLocation(nsIFile* aComponentFile, nsIURI *aComponent, - JSObject **aObject, - JSScript **aTableScript, + JS::MutableHandle aObject, + JS::MutableHandle aTableScript, char **location, bool aCatchException, JS::MutableHandleValue aException); @@ -94,7 +98,7 @@ class mozJSComponentLoader : public mozilla::ModuleLoader, class ModuleEntry : public mozilla::Module { public: - ModuleEntry() : mozilla::Module() { + ModuleEntry(JSContext *cx) : mozilla::Module(), obj(cx), thisObjectKey(cx) { mVersion = mozilla::Module::kVersion; mCIDs = nullptr; mContractIDs = nullptr; @@ -120,9 +124,6 @@ class mozJSComponentLoader : public mozilla::ModuleLoader, JSAutoCompartment ac(cx, obj); JS_SetAllNonReservedSlotsToUndefined(cx, obj); - JS_RemoveObjectRoot(cx, &obj); - if (thisObjectKey) - JS_RemoveScriptRoot(cx, &thisObjectKey); } if (location) @@ -139,9 +140,9 @@ class mozJSComponentLoader : public mozilla::ModuleLoader, const mozilla::Module::CIDEntry& entry); nsCOMPtr getfactoryobj; - JSObject *obj; - JSScript *thisObjectKey; - char *location; + JS::PersistentRooted obj; + JS::PersistentRooted thisObjectKey; + char *location; }; friend class ModuleEntry; @@ -158,7 +159,11 @@ class mozJSComponentLoader : public mozilla::ModuleLoader, nsClassHashtable mImports; nsDataHashtable mInProgressImports; - nsDataHashtable, JSObject*> mThisObjects; + typedef js::HashMap, + js::PointerHasher, + js::SystemAllocPolicy> ThisObjectsMap; + ThisObjectsMap mThisObjects; bool mInitialized; bool mReuseLoaderGlobal;