Bug 767938 part 11. Move the "safe JS context" to where it belongs: the CycleCollectedJSRuntime. r=bholley
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 24 Jun 2016 14:19:51 -0400
changeset 302608 1a0cd542e1e9309f807c6c0b91099c6130ac509e
parent 302607 44ad8744579ed1430e998657a6b5a437e01f1287
child 302609 62e09fa91591ba648466a06a7b47f61c2caac4e9
push id30367
push userphilringnalda@gmail.com
push dateSat, 25 Jun 2016 23:24:01 +0000
treeherdermozilla-central@c2da34d96746 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley
bugs767938
milestone50.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 767938 part 11. Move the "safe JS context" to where it belongs: the CycleCollectedJSRuntime. r=bholley
js/xpconnect/src/XPCJSContextStack.cpp
js/xpconnect/src/XPCJSRuntime.cpp
js/xpconnect/src/moz.build
js/xpconnect/src/nsXPConnect.cpp
js/xpconnect/src/xpcprivate.h
xpcom/base/CycleCollectedJSRuntime.cpp
xpcom/base/CycleCollectedJSRuntime.h
deleted file mode 100644
--- a/js/xpconnect/src/XPCJSContextStack.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* vim: set ts=8 sts=4 et sw=4 tw=99: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/* Implement global service to track stack of JSContext. */
-
-#include "xpcprivate.h"
-#include "XPCWrapper.h"
-#include "nsDOMJSUtils.h"
-#include "nsNullPrincipal.h"
-#include "mozilla/dom/BindingUtils.h"
-
-using namespace mozilla;
-using namespace JS;
-using namespace xpc;
-
-/***************************************************************************/
-
-XPCJSContextStack::~XPCJSContextStack()
-{
-    if (mSafeJSContext) {
-        mSafeJSContext = nullptr;
-    }
-}
-
-JSContext*
-XPCJSContextStack::GetSafeJSContext()
-{
-    MOZ_ASSERT(mSafeJSContext);
-    return mSafeJSContext;
-}
-
-void
-XPCJSContextStack::InitSafeJSContext()
-{
-    MOZ_ASSERT(!mSafeJSContext);
-
-    mSafeJSContext = JS_GetContext(mRuntime->Runtime());
-    if (!JS::InitSelfHostedCode(mSafeJSContext))
-        MOZ_CRASH("InitSelfHostedCode failed");
-
-    if (!mRuntime->JSContextInitialized(mSafeJSContext))
-        MOZ_CRASH("JSContextCreated failed");
-}
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -1541,22 +1541,16 @@ CompartmentPrivate::SizeOfIncludingThis(
     size_t n = mallocSizeOf(this);
     n += mWrappedJSMap->SizeOfIncludingThis(mallocSizeOf);
     n += mWrappedJSMap->SizeOfWrappedJS(mallocSizeOf);
     return n;
 }
 
 /***************************************************************************/
 
-void XPCJSRuntime::DestroyJSContextStack()
-{
-    delete mJSContextStack;
-    mJSContextStack = nullptr;
-}
-
 void XPCJSRuntime::SystemIsBeingShutDown()
 {
     for (auto i = mDetachedWrappedNativeProtoMap->Iter(); !i.Done(); i.Next()) {
         auto entry = static_cast<XPCWrappedNativeProtoMap::Entry*>(i.Get());
         auto proto = const_cast<XPCWrappedNativeProto*>(static_cast<const XPCWrappedNativeProto*>(entry->key));
         proto->SystemIsBeingShutDown();
     }
 }
@@ -3381,18 +3375,17 @@ class XPCJSSourceHook: public js::Source
 };
 
 static const JSWrapObjectCallbacks WrapObjectCallbacks = {
     xpc::WrapperFactory::Rewrap,
     xpc::WrapperFactory::PrepareForWrapping
 };
 
 XPCJSRuntime::XPCJSRuntime()
- : mJSContextStack(new XPCJSContextStack(this)),
-   mCallContext(nullptr),
+ : mCallContext(nullptr),
    mAutoRoots(nullptr),
    mResolveName(JSID_VOID),
    mResolvingWrapper(nullptr),
    mWrappedJSMap(JSObject2WrappedJSMap::newMap(XPC_JS_MAP_LENGTH)),
    mWrappedJSClassMap(IID2WrappedJSClassMap::newMap(XPC_JS_CLASS_MAP_LENGTH)),
    mIID2NativeInterfaceMap(IID2NativeInterfaceMap::newMap(XPC_NATIVE_INTERFACE_MAP_LENGTH)),
    mClassInfo2NativeSetMap(ClassInfo2NativeSetMap::newMap(XPC_NATIVE_SET_MAP_LENGTH)),
    mNativeSetMap(NativeSetMap::newMap(XPC_NATIVE_SET_MAP_LENGTH)),
@@ -3772,16 +3765,17 @@ XPCJSRuntime::AfterProcessTask(uint32_t 
 void
 XPCJSRuntime::DebugDump(int16_t depth)
 {
 #ifdef DEBUG
     depth--;
     XPC_LOG_ALWAYS(("XPCJSRuntime @ %x", this));
         XPC_LOG_INDENT();
         XPC_LOG_ALWAYS(("mJSRuntime @ %x", Runtime()));
+        XPC_LOG_ALWAYS(("mJSContext @ %x", Context()));
 
         XPC_LOG_ALWAYS(("mWrappedJSClassMap @ %x with %d wrapperclasses(s)",
                         mWrappedJSClassMap, mWrappedJSClassMap->Count()));
         // iterate wrappersclasses...
         if (depth && mWrappedJSClassMap->Count()) {
             XPC_LOG_INDENT();
             for (auto i = mWrappedJSClassMap->Iter(); !i.Done(); i.Next()) {
                 auto entry = static_cast<IID2WrappedJSClassMap::Entry*>(i.Get());
@@ -3879,17 +3873,17 @@ XPCJSRuntime::RemoveGCCallback(xpcGCCall
         NS_ERROR("Removing a callback which was never added.");
     }
 }
 
 void
 XPCJSRuntime::InitSingletonScopes()
 {
     // This all happens very early, so we don't bother with cx pushing.
-    JSContext* cx = GetJSContextStack()->GetSafeJSContext();
+    JSContext* cx = Context();
     JSAutoRequest ar(cx);
     RootedValue v(cx);
     nsresult rv;
 
     // Create the Unprivileged Junk Scope.
     SandboxOptions unprivilegedJunkScopeOptions;
     unprivilegedJunkScopeOptions.sandboxName.AssignLiteral("XPConnect Junk Compartment");
     unprivilegedJunkScopeOptions.invisibleToDebugger = true;
--- a/js/xpconnect/src/moz.build
+++ b/js/xpconnect/src/moz.build
@@ -17,17 +17,16 @@ UNIFIED_SOURCES += [
     'nsScriptError.cpp',
     'nsScriptErrorWithStack.cpp',
     'nsXPConnect.cpp',
     'Sandbox.cpp',
     'XPCCallContext.cpp',
     'XPCConvert.cpp',
     'XPCDebug.cpp',
     'XPCException.cpp',
-    'XPCJSContextStack.cpp',
     'XPCJSID.cpp',
     'XPCJSRuntime.cpp',
     'XPCJSWeakReference.cpp',
     'XPCLocale.cpp',
     'XPCLog.cpp',
     'XPCMaps.cpp',
     'XPCModule.cpp',
     'XPCRuntimeService.cpp',
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -67,17 +67,16 @@ nsXPConnect::nsXPConnect()
     if (!mRuntime) {
         NS_RUNTIMEABORT("Couldn't create XPCJSRuntime.");
     }
 }
 
 nsXPConnect::~nsXPConnect()
 {
     mRuntime->DeleteSingletonScopes();
-    mRuntime->DestroyJSContextStack();
 
     // In order to clean up everything properly, we need to GC twice: once now,
     // to clean anything that can go away on its own (like the Junk Scope, which
     // we unrooted above), and once after forcing a bunch of shutdown in
     // XPConnect, to clean the stuff we forcibly disconnected. The forced
     // shutdown code defaults to leaking in a number of situations, so we can't
     // get by with only the second GC. :-(
     mRuntime->GarbageCollect(JS::gcreason::XPCONNECT_SHUTDOWN);
@@ -119,18 +118,20 @@ nsXPConnect::InitStatics()
     NS_ADDREF(gSelf);
 
     // Fire up the SSM.
     nsScriptSecurityManager::InitStatics();
     gScriptSecurityManager = nsScriptSecurityManager::GetScriptSecurityManager();
     gScriptSecurityManager->GetSystemPrincipal(&gSystemPrincipal);
     MOZ_RELEASE_ASSERT(gSystemPrincipal);
 
-    // Initialize the SafeJSContext.
-    gSelf->mRuntime->GetJSContextStack()->InitSafeJSContext();
+    if (!JS::InitSelfHostedCode(gSelf->mRuntime->Context()))
+        MOZ_CRASH("InitSelfHostedCode failed");
+    if (!gSelf->mRuntime->JSContextInitialized(gSelf->mRuntime->Context()))
+        MOZ_CRASH("JSContextInitialized failed");
 
     // Initialize our singleton scopes.
     gSelf->mRuntime->InitSingletonScopes();
 }
 
 nsXPConnect*
 nsXPConnect::GetSingleton()
 {
@@ -977,17 +978,17 @@ nsXPConnect::JSToVariant(JSContext* ctx,
 
     return NS_OK;
 }
 
 /* virtual */
 JSContext*
 nsXPConnect::GetSafeJSContext()
 {
-    return GetRuntime()->GetJSContextStack()->GetSafeJSContext();
+    return GetRuntime()->Context();
 }
 
 nsIPrincipal*
 nsXPConnect::GetPrincipal(JSObject* obj, bool allowShortCircuit) const
 {
     MOZ_ASSERT(IS_WN_REFLECTOR(obj), "What kind of wrapper is this?");
 
     XPCWrappedNative* xpcWrapper = XPCWrappedNative::Get(obj);
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -349,17 +349,16 @@ private:
     XPCRootSetElem** mSelfp;
 };
 
 /***************************************************************************/
 
 // In the current xpconnect system there can only be one XPCJSRuntime.
 // So, xpconnect can only be used on one JSRuntime within the process.
 
-class XPCJSContextStack;
 class WatchdogManager;
 
 enum WatchdogTimestampCategory
 {
     TimestampRuntimeStateChange = 0,
     TimestampWatchdogWakeup,
     TimestampWatchdogHibernateStart,
     TimestampWatchdogHibernateStop,
@@ -415,19 +414,16 @@ private:
 };
 
 class XPCJSRuntime : public mozilla::CycleCollectedJSRuntime
 {
 public:
     static XPCJSRuntime* newXPCJSRuntime();
     static XPCJSRuntime* Get() { return nsXPConnect::XPConnect()->GetRuntime(); }
 
-    XPCJSContextStack* GetJSContextStack() {return mJSContextStack;}
-    void DestroyJSContextStack();
-
     void RemoveWrappedJS(nsXPCWrappedJS* wrapper);
     void AssertInvalidWrappedJSNotInTable(nsXPCWrappedJS* wrapper) const;
 
     XPCCallContext*  GetCallContext() const {return mCallContext;}
     XPCCallContext*  SetCallContext(XPCCallContext* ccx)
         {XPCCallContext* old = mCallContext; mCallContext = ccx; return old;}
 
     jsid GetResolveName() const {return mResolveName;}
@@ -609,17 +605,16 @@ private:
     nsresult Initialize();
 
     void ReleaseIncrementally(nsTArray<nsISupports*>& array);
 
     static const char* const mStrings[IDX_TOTAL_COUNT];
     jsid mStrIDs[IDX_TOTAL_COUNT];
     JS::Value mStrJSVals[IDX_TOTAL_COUNT];
 
-    XPCJSContextStack*       mJSContextStack;
     XPCCallContext*          mCallContext;
     AutoMarkingPtr*          mAutoRoots;
     jsid                     mResolveName;
     XPCWrappedNative*        mResolvingWrapper;
     JSObject2WrappedJSMap*   mWrappedJSMap;
     IID2WrappedJSClassMap*   mWrappedJSClassMap;
     IID2NativeInterfaceMap*  mIID2NativeInterfaceMap;
     ClassInfo2NativeSetMap*  mClassInfo2NativeSetMap;
@@ -2662,37 +2657,16 @@ private:
     void ResolveName();
 
 private:
     RefPtr<nsJSID> mDetails;
 };
 
 
 /***************************************************************************/
-// XPCJSContextStack is not actually an xpcom object, but xpcom calls are
-// delegated to it as an implementation detail.
-class XPCJSContextStack
-{
-public:
-    explicit XPCJSContextStack(XPCJSRuntime* aRuntime)
-      : mRuntime(aRuntime)
-      , mSafeJSContext(nullptr)
-    { }
-
-    virtual ~XPCJSContextStack();
-
-    void InitSafeJSContext();
-    JSContext* GetSafeJSContext();
-
-private:
-    XPCJSRuntime* mRuntime;
-    JSContext*  mSafeJSContext;
-};
-
-/***************************************************************************/
 // 'Components' object implementations. nsXPCComponentsBase has the
 // less-privileged stuff that we're willing to expose to XBL.
 
 class nsXPCComponentsBase : public nsIXPCComponentsBase
 {
 public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSIXPCCOMPONENTSBASE
@@ -3167,17 +3141,17 @@ inline void*
 xpc_GetJSPrivate(JSObject* obj)
 {
     return js::GetObjectPrivate(obj);
 }
 
 inline JSContext*
 xpc_GetSafeJSContext()
 {
-    return XPCJSRuntime::Get()->GetJSContextStack()->GetSafeJSContext();
+    return XPCJSRuntime::Get()->Context();
 }
 
 namespace xpc {
 
 JSAddonId*
 NewAddonId(JSContext* cx, const nsACString& id);
 
 // JSNatives to expose atob and btoa in various non-DOM XPConnect scopes.
--- a/xpcom/base/CycleCollectedJSRuntime.cpp
+++ b/xpcom/base/CycleCollectedJSRuntime.cpp
@@ -433,16 +433,17 @@ mozilla::GetBuildId(JS::BuildIdCharVecto
 
   return true;
 }
 
 CycleCollectedJSRuntime::CycleCollectedJSRuntime()
   : mGCThingCycleCollectorGlobal(sGCThingCycleCollectorGlobal)
   , mJSZoneCycleCollectorGlobal(sJSZoneCycleCollectorGlobal)
   , mJSRuntime(nullptr)
+  , mJSContext(nullptr)
   , mPrevGCSliceCallback(nullptr)
   , mPrevGCNurseryCollectionCallback(nullptr)
   , mJSHolders(256)
   , mDoingStableStates(false)
   , mOutOfMemoryState(OOMState::OK)
   , mLargeAllocationFailureState(OOMState::OK)
 {
   nsCOMPtr<nsIThread> thread = do_GetCurrentThread();
@@ -474,16 +475,17 @@ CycleCollectedJSRuntime::~CycleCollected
 
 #ifdef SPIDERMONKEY_PROMISE
   mUncaughtRejections.reset();
   mConsumedRejections.reset();
 #endif // SPIDERMONKEY_PROMISE
 
   JS_DestroyRuntime(mJSRuntime);
   mJSRuntime = nullptr;
+  mJSContext = nullptr;
   nsCycleCollector_forgetJSRuntime();
 
   mozilla::dom::DestroyScriptSettings();
 
   mOwningThread->SetScriptObserver(nullptr);
   NS_RELEASE(mOwningThread);
 }
 
@@ -504,16 +506,17 @@ CycleCollectedJSRuntime::Initialize(JSRu
   // The main thread has a base recursion depth of 0, workers of 1.
   mBaseRecursionDepth = RecursionDepth();
 
   mozilla::dom::InitScriptSettings();
   mJSRuntime = JS_NewRuntime(aMaxBytes, aMaxNurseryBytes, aParentRuntime);
   if (!mJSRuntime) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
+  mJSContext = JS_GetContext(mJSRuntime);
 
   if (!JS_AddExtraGCRootsTracer(mJSRuntime, TraceBlackJS, this)) {
     MOZ_CRASH("JS_AddExtraGCRootsTracer failed");
   }
   JS_SetGrayGCRootsTracer(mJSRuntime, TraceGrayJS, this);
   JS_SetGCCallback(mJSRuntime, GCCallback, this);
   mPrevGCSliceCallback = JS::SetGCSliceCallback(mJSRuntime, GCSliceCallback);
 
--- a/xpcom/base/CycleCollectedJSRuntime.h
+++ b/xpcom/base/CycleCollectedJSRuntime.h
@@ -323,16 +323,22 @@ public:
   virtual void DispatchDeferredDeletion(bool aContinuation, bool aPurge = false) = 0;
 
   JSRuntime* Runtime() const
   {
     MOZ_ASSERT(mJSRuntime);
     return mJSRuntime;
   }
 
+  JSContext* Context() const
+  {
+    MOZ_ASSERT(mJSContext);
+    return mJSContext;
+  }
+
 protected:
   JSRuntime* MaybeRuntime() const { return mJSRuntime; }
 
 public:
   // nsThread entrypoints
   virtual void BeforeProcessTask(bool aMightBlock) { };
   virtual void AfterProcessTask(uint32_t aRecursionDepth);
 
@@ -389,16 +395,17 @@ public:
   nsTArray<nsCOMPtr<nsISupports /* UncaughtRejectionObserver */ >> mUncaughtRejectionObservers;
 
 private:
   JSGCThingParticipant mGCThingCycleCollectorGlobal;
 
   JSZoneParticipant mJSZoneCycleCollectorGlobal;
 
   JSRuntime* mJSRuntime;
+  JSContext* mJSContext;
 
   JS::GCSliceCallback mPrevGCSliceCallback;
   JS::GCNurseryCollectionCallback mPrevGCNurseryCollectionCallback;
 
   nsDataHashtable<nsPtrHashKey<void>, nsScriptObjectTracer*> mJSHolders;
 
   typedef nsDataHashtable<nsFuncPtrHashKey<DeferredFinalizeFunction>, void*>
     DeferredFinalizerTable;