Bug 1398396 - Initialize the locale stuff on runtimes instead of contexts. r=billm
authorBlake Kaplan <mrbkap@gmail.com>
Mon, 11 Sep 2017 15:46:14 -0700
changeset 433781 ffddadd962f2abdefb81b2252cc49911b33a8e89
parent 433780 9980c7c2f2314036dcf4b95b8f7ea8070dd9d9cf
child 433782 3e84d38ad0b4c7dd46b73663094895fe76f088fe
push id1567
push userjlorenzo@mozilla.com
push dateThu, 02 Nov 2017 12:36:05 +0000
treeherdermozilla-release@e512c14a0406 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs1398396
milestone57.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 1398396 - Initialize the locale stuff on runtimes instead of contexts. r=billm MozReview-Commit-ID: Il9HAqYdTzK
dom/workers/RuntimeService.cpp
js/xpconnect/src/XPCJSContext.cpp
js/xpconnect/src/XPCJSRuntime.cpp
js/xpconnect/src/XPCLocale.cpp
js/xpconnect/src/xpcprivate.h
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -861,28 +861,16 @@ bool
 InitJSContextForWorker(WorkerPrivate* aWorkerPrivate, JSContext* aWorkerCx)
 {
   aWorkerPrivate->AssertIsOnWorkerThread();
   NS_ASSERTION(!aWorkerPrivate->GetJSContext(), "Already has a context!");
 
   JSSettings settings;
   aWorkerPrivate->CopyJSSettings(settings);
 
-  {
-    JS::UniqueChars defaultLocale = aWorkerPrivate->AdoptDefaultLocale();
-    MOZ_ASSERT(defaultLocale,
-               "failure of a WorkerPrivate to have a default locale should "
-               "have made the worker fail to spawn");
-
-    if (!JS_SetDefaultLocale(aWorkerCx, defaultLocale.get())) {
-      NS_WARNING("failed to set workerCx's default locale");
-      return false;
-    }
-  }
-
   JS::ContextOptionsRef(aWorkerCx) = settings.contextOptions;
 
   JSSettings::JSGCSettingsArray& gcSettings = settings.gcSettings;
 
   // This is the real place where we set the max memory for the runtime.
   for (uint32_t index = 0; index < ArrayLength(gcSettings); index++) {
     const JSSettings::JSGCSetting& setting = gcSettings[index];
     if (setting.key.isSome()) {
@@ -972,16 +960,27 @@ public:
   // The heap size passed here doesn't matter, we will change it later in the
   // call to JS_SetGCParameter inside InitJSContextForWorker.
   explicit WorkerJSRuntime(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
     : CycleCollectedJSRuntime(aCx)
     , mWorkerPrivate(aWorkerPrivate)
   {
     MOZ_COUNT_CTOR_INHERITED(WorkerJSRuntime, CycleCollectedJSRuntime);
     MOZ_ASSERT(aWorkerPrivate);
+
+    {
+      JS::UniqueChars defaultLocale = aWorkerPrivate->AdoptDefaultLocale();
+      MOZ_ASSERT(defaultLocale,
+                 "failure of a WorkerPrivate to have a default locale should "
+                 "have made the worker fail to spawn");
+
+      if (!JS_SetDefaultLocale(Runtime(), defaultLocale.get())) {
+        NS_WARNING("failed to set workerCx's default locale");
+      }
+    }
   }
 
   void Shutdown(JSContext* cx) override
   {
     // The CC is shut down, and the superclass destructor will GC, so make sure
     // we don't try to CC again.
     mWorkerPrivate = nullptr;
   }
--- a/js/xpconnect/src/XPCJSContext.cpp
+++ b/js/xpconnect/src/XPCJSContext.cpp
@@ -869,18 +869,16 @@ XPCJSContext::~XPCJSContext()
 #endif
 
     js::SetActivityCallback(Context(), nullptr, nullptr);
 
     // Clear any pending exception.  It might be an XPCWrappedJS, and if we try
     // to destroy it later we will crash.
     SetPendingException(nullptr);
 
-    xpc_DelocalizeContext(Context());
-
     // If we're the last XPCJSContext around, clean up the watchdog manager.
     mWatchdogManager->UnregisterContext(this);
     if (--sInstanceCount == 0) {
         if (mWatchdogManager->GetWatchdog()) {
             mWatchdogManager->StopWatchdog();
         }
         mWatchdogManager->Shutdown();
         sWatchdogInstance = nullptr;
@@ -1076,22 +1074,16 @@ XPCJSContext::Initialize(XPCJSContext* a
                            kStackQuota - kSystemCodeBuffer,
                            kStackQuota - kSystemCodeBuffer - kTrustedScriptBuffer);
 
     profiler_set_js_context(cx);
 
     js::SetActivityCallback(cx, ActivityCallback, this);
     JS_AddInterruptCallback(cx, InterruptCallback);
 
-    // Set up locale information and callbacks for the newly-created context so
-    // that the various toLocaleString() methods, localeCompare(), and other
-    // internationalization APIs work as desired.
-    if (!xpc_LocalizeContext(cx))
-        NS_RUNTIMEABORT("xpc_LocalizeContext failed.");
-
     if (!aPrimaryContext) {
         Runtime()->Initialize(cx);
     }
 
     // Watch for the JS boolean options.
     ReloadPrefsCallback(nullptr, this);
     Preferences::RegisterPrefixCallback(ReloadPrefsCallback,
                                         JS_OPTIONS_DOT_STR,
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -1061,16 +1061,17 @@ XPCJSRuntime::Shutdown(JSContext* cx)
 {
     // This destructor runs before ~CycleCollectedJSContext, which does the
     // actual JS_DestroyContext() call. But destroying the context triggers
     // one final GC, which can call back into the context with various
     // callbacks if we aren't careful. Null out the relevant callbacks.
     JS_RemoveFinalizeCallback(cx, FinalizeCallback);
     JS_RemoveWeakPointerZonesCallback(cx, WeakPointerZonesCallback);
     JS_RemoveWeakPointerCompartmentCallback(cx, WeakPointerCompartmentCallback);
+    xpc_DelocalizeRuntime(JS_GetRuntime(cx));
 
     JS::SetGCSliceCallback(cx, mPrevGCSliceCallback);
 
     // We don't want to track wrapped JS roots after this point since we're
     // making them !IsValid anyway through SystemIsBeingShutDown.
     mWrappedJSRoots = nullptr;
 
     // clean up and destroy maps...
@@ -2935,16 +2936,18 @@ XPCJSRuntime::Initialize(JSContext* cx)
     // Register memory reporters and distinguished amount functions.
     RegisterStrongMemoryReporter(new JSMainRuntimeCompartmentsReporter());
     RegisterStrongMemoryReporter(new JSMainRuntimeTemporaryPeakReporter());
     RegisterJSMainRuntimeGCHeapDistinguishedAmount(JSMainRuntimeGCHeapDistinguishedAmount);
     RegisterJSMainRuntimeTemporaryPeakDistinguishedAmount(JSMainRuntimeTemporaryPeakDistinguishedAmount);
     RegisterJSMainRuntimeCompartmentsSystemDistinguishedAmount(JSMainRuntimeCompartmentsSystemDistinguishedAmount);
     RegisterJSMainRuntimeCompartmentsUserDistinguishedAmount(JSMainRuntimeCompartmentsUserDistinguishedAmount);
     mozilla::RegisterJSSizeOfTab(JSSizeOfTab);
+
+    xpc_LocalizeRuntime(JS_GetRuntime(cx));
 }
 
 bool
 XPCJSRuntime::InitializeStrings(JSContext* cx)
 {
     JSAutoRequest ar(cx);
 
     // if it is our first context then we need to generate our string ids
--- a/js/xpconnect/src/XPCLocale.cpp
+++ b/js/xpconnect/src/XPCLocale.cpp
@@ -47,18 +47,18 @@ XPCLocaleObserver::Init()
 
   observerService->AddObserver(this, "intl:app-locales-changed", false);
 }
 
 NS_IMETHODIMP
 XPCLocaleObserver::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData)
 {
   if (!strcmp(aTopic, "intl:app-locales-changed")) {
-    JSContext* cx = CycleCollectedJSContext::Get()->Context();
-    if (!xpc_LocalizeContext(cx)) {
+    JSRuntime* rt = CycleCollectedJSRuntime::Get()->Runtime();
+    if (!xpc_LocalizeRuntime(rt)) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
     return NS_OK;
   }
 
   return NS_ERROR_UNEXPECTED;
 }
 
@@ -89,25 +89,34 @@ struct XPCLocaleCallbacks : public JSLoc
 
   ~XPCLocaleCallbacks()
   {
     AssertThreadSafety();
     MOZ_COUNT_DTOR(XPCLocaleCallbacks);
   }
 
   /**
-   * Return the XPCLocaleCallbacks that's hidden away in |cx|. (This impl uses
-   * the locale callbacks struct to store away its per-context data.)
+   * Return the XPCLocaleCallbacks from |cx|'s runtime (see below).
    */
   static XPCLocaleCallbacks*
   This(JSContext* cx)
   {
+    return This(JS_GetRuntime(cx));
+  }
+
+  /**
+   * Return the XPCLocaleCallbacks that's hidden away in |rt|. (This impl uses
+   * the locale callbacks struct to store away its per-context data.)
+   */
+  static XPCLocaleCallbacks*
+  This(JSRuntime* rt)
+  {
     // Locale information for |cx| was associated using xpc_LocalizeContext;
     // assert and double-check this.
-    const JSLocaleCallbacks* lc = JS_GetLocaleCallbacks(cx);
+    const JSLocaleCallbacks* lc = JS_GetLocaleCallbacks(rt);
     MOZ_ASSERT(lc);
     MOZ_ASSERT(lc->localeToUpperCase == nullptr);
     MOZ_ASSERT(lc->localeToLowerCase == nullptr);
     MOZ_ASSERT(lc->localeCompare == LocaleCompare);
     MOZ_ASSERT(lc->localeToUnicode == LocaleToUnicode);
 
     const XPCLocaleCallbacks* ths = static_cast<const XPCLocaleCallbacks*>(lc);
     ths->AssertThreadSafety();
@@ -192,42 +201,42 @@ private:
   }
 
   nsCOMPtr<nsICollation> mCollation;
 
   NS_DECL_OWNINGTHREAD
 };
 
 bool
-xpc_LocalizeContext(JSContext* cx)
+xpc_LocalizeRuntime(JSRuntime* rt)
 {
   // We want to assign the locale callbacks only the first time we
   // localize the context.
   // All consequent calls to this function are result of language changes
   // and should not assign it again.
-  const JSLocaleCallbacks* lc = JS_GetLocaleCallbacks(cx);
+  const JSLocaleCallbacks* lc = JS_GetLocaleCallbacks(rt);
   if (!lc) {
-    JS_SetLocaleCallbacks(cx, new XPCLocaleCallbacks());
+    JS_SetLocaleCallbacks(rt, new XPCLocaleCallbacks());
   }
 
   // Set the default locale.
 
   // Check a pref to see if we should use US English locale regardless
   // of the system locale.
   if (Preferences::GetBool("javascript.use_us_english_locale", false)) {
-    return JS_SetDefaultLocale(cx, "en-US");
+    return JS_SetDefaultLocale(rt, "en-US");
   }
 
   // No pref has been found, so get the default locale from the
   // application's locale.
   nsAutoCString appLocaleStr;
   LocaleService::GetInstance()->GetAppLocaleAsBCP47(appLocaleStr);
 
-  return JS_SetDefaultLocale(cx, appLocaleStr.get());
+  return JS_SetDefaultLocale(rt, appLocaleStr.get());
 }
 
 void
-xpc_DelocalizeContext(JSContext* cx)
+xpc_DelocalizeRuntime(JSRuntime* rt)
 {
-  const XPCLocaleCallbacks* lc = XPCLocaleCallbacks::This(cx);
-  JS_SetLocaleCallbacks(cx, nullptr);
+  const XPCLocaleCallbacks* lc = XPCLocaleCallbacks::This(rt);
+  JS_SetLocaleCallbacks(rt, nullptr);
   delete lc;
 }
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -3264,19 +3264,19 @@ nsIPrincipal* GetObjectPrincipal(JSObjec
 namespace mozilla {
 namespace dom {
 extern bool
 DefineStaticJSVals(JSContext* cx);
 } // namespace dom
 } // namespace mozilla
 
 bool
-xpc_LocalizeContext(JSContext* cx);
+xpc_LocalizeRuntime(JSRuntime* rt);
 void
-xpc_DelocalizeContext(JSContext* cx);
+xpc_DelocalizeRuntime(JSRuntime* rt);
 
 /***************************************************************************/
 // Inlines use the above - include last.
 
 #include "XPCInlines.h"
 
 /***************************************************************************/
 // Maps have inlines that use the above - include last.