Bug 1330661 - Baldr: make the BuildIdOp a process global (r=lth,mccr8)
authorLuke Wagner <luke@mozilla.com>
Tue, 04 Sep 2018 14:25:57 -0500
changeset 482964 0dd32db49222b18a9c8e6fef0305bce9b32d9a17
parent 482963 603f0c6003b3ec81be847304b71124fcda216c20
child 482965 f4400f4e6b8500d2a7ebaacbaa1a361f18c9feac
push id232
push userfmarier@mozilla.com
push dateWed, 05 Sep 2018 20:45:54 +0000
reviewerslth, mccr8
bugs1330661
milestone63.0a1
Bug 1330661 - Baldr: make the BuildIdOp a process global (r=lth,mccr8)
js/src/jsapi-tests/testXDR.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/shell/js.cpp
js/src/vm/JSContext.h
js/src/vm/Runtime.cpp
js/src/vm/Runtime.h
js/src/vm/Xdr.cpp
js/src/wasm/AsmJS.cpp
js/xpconnect/src/XPCJSRuntime.cpp
js/xpconnect/src/xpcpublic.h
xpcom/base/CycleCollectedJSContext.cpp
xpcom/base/CycleCollectedJSRuntime.cpp
xpcom/base/CycleCollectedJSRuntime.h
--- a/js/src/jsapi-tests/testXDR.cpp
+++ b/js/src/jsapi-tests/testXDR.cpp
@@ -19,17 +19,17 @@ GetBuildId(JS::BuildIdCharVector* buildI
 {
     const char buildid[] = "testXDR";
     return buildId->append(buildid, sizeof(buildid));
 }
 
 static JSScript*
 FreezeThaw(JSContext* cx, JS::HandleScript script)
 {
-    JS::SetBuildIdOp(cx, GetBuildId);
+    JS::SetProcessBuildIdOp(::GetBuildId);
 
     // freeze
     JS::TranscodeBuffer buffer;
     JS::TranscodeResult rs = JS::EncodeScript(cx, buffer, script);
     if (rs != JS::TranscodeResult_Ok)
         return nullptr;
 
     // thaw
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -7621,19 +7621,19 @@ JS::FinishIncrementalEncoding(JSContext*
     if (!script)
         return false;
     if (!script->scriptSource()->xdrFinalizeEncoder(buffer))
         return false;
     return true;
 }
 
 JS_PUBLIC_API(void)
-JS::SetBuildIdOp(JSContext* cx, JS::BuildIdOp buildIdOp)
-{
-    cx->runtime()->buildIdOp = buildIdOp;
+JS::SetProcessBuildIdOp(JS::BuildIdOp buildIdOp)
+{
+    GetBuildId = buildIdOp;
 }
 
 JS_PUBLIC_API(void)
 JS::SetAsmJSCacheOps(JSContext* cx, const JS::AsmJSCacheOps* ops)
 {
     cx->runtime()->asmJSCacheOps = *ops;
 }
 
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -4649,23 +4649,24 @@ SetAsmJSCacheOps(JSContext* cx, const As
 
 /**
  * Return the buildId (represented as a sequence of characters) associated with
  * the currently-executing build. If the JS engine is embedded such that a
  * single cache entry can be observed by different compiled versions of the JS
  * engine, it is critical that the buildId shall change for each new build of
  * the JS engine.
  */
+
 typedef js::Vector<char, 0, js::SystemAllocPolicy> BuildIdCharVector;
 
 typedef bool
 (* BuildIdOp)(BuildIdCharVector* buildId);
 
 extern JS_PUBLIC_API(void)
-SetBuildIdOp(JSContext* cx, BuildIdOp buildIdOp);
+SetProcessBuildIdOp(BuildIdOp buildIdOp);
 
 /**
  * The WasmModule interface allows the embedding to hold a reference to the
  * underying C++ implementation of a JS WebAssembly.Module object for purposes
  * of efficient postMessage() and (de)serialization from a random thread.
  *
  * In particular, this allows postMessage() of a WebAssembly.Module:
  * GetWasmModule() is called when making a structured clone of a payload
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -3629,17 +3629,16 @@ WorkerMain(WorkerInput* input)
         js_delete(sc);
         js_delete(input);
     });
 
     sc->isWorker = true;
     JS_SetContextPrivate(cx, sc);
     JS_SetGrayGCRootsTracer(cx, TraceGrayRoots, nullptr);
     SetWorkerContextOptions(cx);
-    JS::SetBuildIdOp(cx, ShellBuildId);
 
     JS_SetFutexCanWait(cx);
     JS::SetWarningReporter(cx, WarningReporter);
     js::SetPreserveWrapperCallback(cx, DummyPreserveWrapperCallback);
     JS_InitDestroyPrincipalsCallback(cx, ShellPrincipals::destroy);
     JS_SetDestroyCompartmentCallback(cx, DestroyShellCompartmentPrivate);
 
     js::UseInternalJobQueues(cx);
@@ -9879,16 +9878,18 @@ main(int argc, char** argv, char** envp)
     }
 
     if (op.getBoolOption("suppress-minidump"))
         js::NoteIntentionalCrash();
 
     if (!InitSharedObjectMailbox())
         return 1;
 
+    JS::SetProcessBuildIdOp(ShellBuildId);
+
     // The fake CPU count must be set before initializing the Runtime,
     // which spins up the thread pool.
     int32_t cpuCount = op.getIntOption("cpu-count"); // What we're really setting
     if (cpuCount < 0)
         cpuCount = op.getIntOption("thread-count");  // Legacy name
     if (cpuCount >= 0)
         SetFakeCPUCount(cpuCount);
 
@@ -9919,17 +9920,16 @@ main(int argc, char** argv, char** envp)
         JS_SetGCParametersBasedOnAvailableMemory(cx, availMem);
 
     JS_SetTrustedPrincipals(cx, &ShellPrincipals::fullyTrusted);
     JS_SetSecurityCallbacks(cx, &ShellPrincipals::securityCallbacks);
     JS_InitDestroyPrincipalsCallback(cx, ShellPrincipals::destroy);
     JS_SetDestroyCompartmentCallback(cx, DestroyShellCompartmentPrivate);
 
     JS_AddInterruptCallback(cx, ShellInterruptCallback);
-    JS::SetBuildIdOp(cx, ShellBuildId);
     JS::SetAsmJSCacheOps(cx, &asmJSCacheOps);
 
     bufferStreamState =
         js_new<ExclusiveWaitableData<BufferStreamState>>(mutexid::BufferStreamState);
     if (!bufferStreamState)
         return 1;
     auto shutdownBufferStreams = MakeScopeExit([] {
         ShutdownBufferStreams();
--- a/js/src/vm/JSContext.h
+++ b/js/src/vm/JSContext.h
@@ -221,17 +221,16 @@ struct JSContext : public JS::RootingCon
     JSAtomState& names() { return *runtime_->commonNames; }
     js::StaticStrings& staticStrings() { return *runtime_->staticStrings; }
     js::SharedImmutableStringsCache& sharedImmutableStrings() {
         return runtime_->sharedImmutableStrings();
     }
     bool permanentAtomsPopulated() { return runtime_->permanentAtomsPopulated(); }
     const js::FrozenAtomSet& permanentAtoms() { return *runtime_->permanentAtoms(); }
     js::WellKnownSymbols& wellKnownSymbols() { return *runtime_->wellKnownSymbols; }
-    JS::BuildIdOp buildIdOp() { return runtime_->buildIdOp; }
     const JS::AsmJSCacheOps& asmJSCacheOps() { return runtime_->asmJSCacheOps; }
     js::PropertyName* emptyString() { return runtime_->emptyString; }
     js::FreeOp* defaultFreeOp() { return runtime_->defaultFreeOp(); }
     void* stackLimitAddress(JS::StackKind kind) { return &nativeStackLimit[kind]; }
     void* stackLimitAddressForJitCode(JS::StackKind kind);
     uintptr_t stackLimit(JS::StackKind kind) { return nativeStackLimit[kind]; }
     uintptr_t stackLimitForJitCode(JS::StackKind kind);
     size_t gcSystemPageSize() { return js::gc::SystemPageSize(); }
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -61,16 +61,17 @@ using mozilla::NegativeInfinity;
 using mozilla::PodZero;
 using mozilla::PositiveInfinity;
 using JS::AutoStableStringChars;
 using JS::DoubleNaNValue;
 
 /* static */ MOZ_THREAD_LOCAL(JSContext*) js::TlsContext;
 /* static */ Atomic<size_t> JSRuntime::liveRuntimesCount;
 Atomic<JS::LargeAllocationFailureCallback> js::OnLargeAllocationFailure;
+Atomic<JS::BuildIdOp> js::GetBuildId;
 
 namespace js {
     bool gCanUseExtraThreads = true;
 } // namespace js
 
 void
 js::DisableExtraThreads()
 {
@@ -114,17 +115,16 @@ JSRuntime::JSRuntime(JSRuntime* parentRu
     realmNameCallback(nullptr),
     externalStringSizeofCallback(nullptr),
     securityCallbacks(&NullSecurityCallbacks),
     DOMcallbacks(nullptr),
     destroyPrincipals(nullptr),
     readPrincipals(nullptr),
     warningReporter(nullptr),
     geckoProfiler_(thisFromCtor()),
-    buildIdOp(nullptr),
     trustedPrincipals_(nullptr),
     wrapObjectCallbacks(&DefaultWrapObjectCallbacks),
     preserveWrapperCallback(nullptr),
     scriptEnvironmentPreparer(nullptr),
     ctypesActivityCallback(nullptr),
     windowProxyClass_(nullptr),
     scriptDataLock(mutexid::RuntimeScriptData),
 #ifdef DEBUG
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -395,18 +395,16 @@ struct JSRuntime : public js::MallocProv
                                                  mozilla::LinkedList<JS::PersistentRooted<void*>>>> heapRoots;
 
     void tracePersistentRoots(JSTracer* trc);
     void finishPersistentRoots();
 
     void finishRoots();
 
   public:
-    js::UnprotectedData<JS::BuildIdOp> buildIdOp;
-
     /* AsmJSCache callbacks are runtime-wide. */
     js::UnprotectedData<JS::AsmJSCacheOps> asmJSCacheOps;
 
   private:
     js::UnprotectedData<const JSPrincipals*> trustedPrincipals_;
   public:
     void setTrustedPrincipals(const JSPrincipals* p) { trustedPrincipals_ = p; }
     const JSPrincipals* trustedPrincipals() const { return trustedPrincipals_; }
@@ -1188,11 +1186,14 @@ SetValueRangeToNull(Value* vec, size_t l
 }
 
 extern const JSSecurityCallbacks NullSecurityCallbacks;
 
 // This callback is set by JS::SetProcessLargeAllocationFailureCallback
 // and may be null. See comment in jsapi.h.
 extern mozilla::Atomic<JS::LargeAllocationFailureCallback> OnLargeAllocationFailure;
 
+// This callback is set by JS::SetBuildIdOp and may be null. See comment in jsapi.h.
+extern mozilla::Atomic<JS::BuildIdOp> GetBuildId;
+
 } /* namespace js */
 
 #endif /* vm_Runtime_h */
--- a/js/src/vm/Xdr.cpp
+++ b/js/src/vm/Xdr.cpp
@@ -81,18 +81,18 @@ XDRState<mode>::codeChars(char16_t* char
     return Ok();
 }
 
 template<XDRMode mode>
 static XDRResult
 VersionCheck(XDRState<mode>* xdr)
 {
     JS::BuildIdCharVector buildId;
-    MOZ_ASSERT(xdr->cx()->buildIdOp());
-    if (!xdr->cx()->buildIdOp()(&buildId)) {
+    MOZ_ASSERT(GetBuildId);
+    if (!GetBuildId(&buildId)) {
         ReportOutOfMemory(xdr->cx());
         return xdr->fail(JS::TranscodeResult_Throw);
     }
     MOZ_ASSERT(!buildId.empty());
 
     uint32_t buildIdLength;
     if (mode == XDR_ENCODE)
         buildIdLength = buildId.length();
--- a/js/src/wasm/AsmJS.cpp
+++ b/js/src/wasm/AsmJS.cpp
@@ -6331,35 +6331,35 @@ namespace {
 // the module must be recompiled from scratch.
 
 struct Assumptions
 {
     uint32_t              cpuId;
     JS::BuildIdCharVector buildId;
 
     Assumptions();
-    bool init(JSContext* cx);
+    bool init();
 
     bool operator==(const Assumptions& rhs) const;
     bool operator!=(const Assumptions& rhs) const { return !(*this == rhs); }
 
     size_t serializedSize() const;
     uint8_t* serialize(uint8_t* cursor) const;
     const uint8_t* deserialize(const uint8_t* cursor, size_t remain);
 };
 
 Assumptions::Assumptions()
   : cpuId(ObservedCPUFeatures()),
     buildId()
 {}
 
 bool
-Assumptions::init(JSContext* cx)
-{
-    return cx->buildIdOp() && cx->buildIdOp()(&buildId);
+Assumptions::init()
+{
+    return GetBuildId && GetBuildId(&buildId);
 }
 
 bool
 Assumptions::operator==(const Assumptions& rhs) const
 {
     return cpuId == rhs.cpuId &&
            buildId.length() == rhs.buildId.length() &&
            ArrayEqual(buildId.begin(), rhs.buildId.begin(), buildId.length());
@@ -6590,17 +6590,17 @@ StoreAsmJSModuleInCache(AsmJSParser& par
         return JS::AsmJSCache_InternalError;
 
     MOZ_RELEASE_ASSERT(module.bytecode().length() == 0);
 
     size_t compiledSize = module.compiledSerializedSize();
     MOZ_RELEASE_ASSERT(compiledSize <= UINT32_MAX);
 
     Assumptions assumptions;
-    if (!assumptions.init(cx))
+    if (!assumptions.init())
         return JS::AsmJSCache_InternalError;
 
     size_t serializedSize = assumptions.serializedSize() +
                             sizeof(uint32_t) +
                             compiledSize +
                             moduleChars.serializedSize();
 
     JS::OpenAsmJSCacheEntryForWriteOp open = cx->asmJSCacheOps().openEntryForWrite;
@@ -6654,17 +6654,17 @@ LookupAsmJSModuleInCache(JSContext* cx, 
     const uint8_t* cursor = entry.memory;
 
     Assumptions deserializedAssumptions;
     cursor = deserializedAssumptions.deserialize(cursor, entry.serializedSize);
     if (!cursor)
         return true;
 
     Assumptions currentAssumptions;
-    if (!currentAssumptions.init(cx) || currentAssumptions != deserializedAssumptions)
+    if (!currentAssumptions.init() || currentAssumptions != deserializedAssumptions)
         return true;
 
     uint32_t compiledSize;
     cursor = ReadScalar<uint32_t>(cursor, &compiledSize);
     if (!cursor)
         return true;
 
     MutableAsmJSMetadata asmJSMetadata = cx->new_<AsmJSMetadata>();
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -22,16 +22,17 @@
 #include "nsExceptionHandler.h"
 #include "nsIMemoryInfoDumper.h"
 #include "nsIMemoryReporter.h"
 #include "nsIObserverService.h"
 #include "nsIDebug2.h"
 #include "nsIDocShell.h"
 #include "nsIDocument.h"
 #include "nsIRunnable.h"
+#include "nsIPlatformInfo.h"
 #include "nsPIDOMWindow.h"
 #include "nsPrintfCString.h"
 #include "nsWindowSizes.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/Services.h"
 #include "mozilla/dom/ScriptLoader.h"
 #include "mozilla/dom/ScriptSettings.h"
@@ -1039,16 +1040,39 @@ OnLargeAllocationFailureCallback()
     RefPtr<LargeAllocationFailureRunnable> r = new LargeAllocationFailureRunnable;
     if (NS_WARN_IF(NS_FAILED(NS_DispatchToMainThread(r)))) {
         return;
     }
 
     r->BlockUntilDone();
 }
 
+bool
+mozilla::GetBuildId(JS::BuildIdCharVector* aBuildID)
+{
+    nsCOMPtr<nsIPlatformInfo> info = do_GetService("@mozilla.org/xre/app-info;1");
+    if (!info) {
+        return false;
+    }
+
+    nsCString buildID;
+    nsresult rv = info->GetPlatformBuildID(buildID);
+    NS_ENSURE_SUCCESS(rv, false);
+
+    if (!aBuildID->resize(buildID.Length())) {
+        return false;
+    }
+
+    for (size_t i = 0; i < buildID.Length(); i++) {
+        (*aBuildID)[i] = buildID[i];
+    }
+
+    return true;
+}
+
 size_t
 XPCJSRuntime::SizeOfIncludingThis(MallocSizeOf mallocSizeOf)
 {
     size_t n = 0;
     n += mallocSizeOf(this);
     n += mWrappedJSMap->SizeOfIncludingThis(mallocSizeOf);
     n += mIID2NativeInterfaceMap->SizeOfIncludingThis(mallocSizeOf);
     n += mClassInfo2NativeSetMap->ShallowSizeOfIncludingThis(mallocSizeOf);
@@ -2946,16 +2970,17 @@ XPCJSRuntime::Initialize(JSContext* cx)
     JS_SetWrapObjectCallbacks(cx, &WrapObjectCallbacks);
     js::SetPreserveWrapperCallback(cx, PreserveWrapper);
     JS_InitReadPrincipalsCallback(cx, nsJSPrincipals::ReadPrincipals);
     JS_SetAccumulateTelemetryCallback(cx, AccumulateTelemetryCallback);
     JS_SetSetUseCounterCallback(cx, SetUseCounterCallback);
     js::SetWindowProxyClass(cx, &OuterWindowProxyClass);
     js::SetXrayJitInfo(&gXrayJitInfo);
     JS::SetProcessLargeAllocationFailureCallback(OnLargeAllocationFailureCallback);
+    JS::SetProcessBuildIdOp(GetBuildId);
 
     // The JS engine needs to keep the source code around in order to implement
     // Function.prototype.toSource(). It'd be nice to not have to do this for
     // chrome code and simply stub out requests for source on it. Life is not so
     // easy, unfortunately. Nobody relies on chrome toSource() working in core
     // browser code, but chrome tests use it. The worst offenders are addons,
     // which like to monkeypatch chrome functions by calling toSource() on them
     // and using regular expressions to modify them. We avoid keeping most browser
--- a/js/xpconnect/src/xpcpublic.h
+++ b/js/xpconnect/src/xpcpublic.h
@@ -746,11 +746,18 @@ bool IsNotUAWidget(JSContext* cx, JSObje
 bool IsChromeOrXBLOrUAWidget(JSContext* cx, JSObject* /* unused */);
 
 /**
  * Same as IsChromeOrXBLOrUAWidget but can be used in worker threads as well.
  */
 bool ThreadSafeIsChromeOrXBLOrUAWidget(JSContext* cx, JSObject* obj);
 
 } // namespace dom
+
+/**
+ * Fill the given vector with the buildid.
+ */
+bool
+GetBuildId(JS::BuildIdCharVector* aBuildID);
+
 } // namespace mozilla
 
 #endif
--- a/xpcom/base/CycleCollectedJSContext.cpp
+++ b/xpcom/base/CycleCollectedJSContext.cpp
@@ -33,17 +33,16 @@
 #include "nsCycleCollectionParticipant.h"
 #include "nsCycleCollector.h"
 #include "nsDOMJSUtils.h"
 #include "nsDOMMutationObserver.h"
 #include "nsJSUtils.h"
 #include "nsWrapperCache.h"
 #include "nsStringBuffer.h"
 
-#include "nsIPlatformInfo.h"
 #include "nsThread.h"
 #include "nsThreadUtils.h"
 #include "xpcpublic.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 namespace mozilla {
--- a/xpcom/base/CycleCollectedJSRuntime.cpp
+++ b/xpcom/base/CycleCollectedJSRuntime.cpp
@@ -86,17 +86,16 @@
 #include "nsStringBuffer.h"
 #include "GeckoProfiler.h"
 
 #ifdef MOZ_GECKO_PROFILER
 #include "ProfilerMarkerPayload.h"
 #endif
 
 #include "nsIException.h"
-#include "nsIPlatformInfo.h"
 #include "nsThread.h"
 #include "nsThreadUtils.h"
 #include "xpcpublic.h"
 
 #ifdef NIGHTLY_BUILD
 // For performance reasons, we make the JS Dev Error Interceptor a Nightly-only feature.
 #define MOZ_JS_DEV_ERROR_INTERCEPTOR = 1
 #endif // NIGHTLY_BUILD
@@ -481,39 +480,16 @@ NoteJSChildGrayWrapperShim(void* aData, 
 static const JSZoneParticipant sJSZoneCycleCollectorGlobal;
 
 static
 void JSObjectsTenuredCb(JSContext* aContext, void* aData)
 {
   static_cast<CycleCollectedJSRuntime*>(aData)->JSObjectsTenured();
 }
 
-bool
-mozilla::GetBuildId(JS::BuildIdCharVector* aBuildID)
-{
-  nsCOMPtr<nsIPlatformInfo> info = do_GetService("@mozilla.org/xre/app-info;1");
-  if (!info) {
-    return false;
-  }
-
-  nsCString buildID;
-  nsresult rv = info->GetPlatformBuildID(buildID);
-  NS_ENSURE_SUCCESS(rv, false);
-
-  if (!aBuildID->resize(buildID.Length())) {
-    return false;
-  }
-
-  for (size_t i = 0; i < buildID.Length(); i++) {
-    (*aBuildID)[i] = buildID[i];
-  }
-
-  return true;
-}
-
 static void
 MozCrashWarningReporter(JSContext*, JSErrorReport*)
 {
   MOZ_CRASH("Why is someone touching JSAPI without an AutoJSAPI?");
 }
 
 CycleCollectedJSRuntime::CycleCollectedJSRuntime(JSContext* aCx)
   : mGCThingCycleCollectorGlobal(sGCThingCycleCollectorGlobal)
@@ -550,17 +526,16 @@ CycleCollectedJSRuntime::CycleCollectedJ
     // relevant to the main-thread.
     mPrevGCNurseryCollectionCallback = JS::SetGCNurseryCollectionCallback(
       aCx, GCNurseryCollectionCallback);
   }
 
   JS_SetObjectsTenuredCallback(aCx, JSObjectsTenuredCb, this);
   JS::SetOutOfMemoryCallback(aCx, OutOfMemoryCallback, this);
   JS_SetExternalStringSizeofCallback(aCx, SizeofExternalStringCallback);
-  JS::SetBuildIdOp(aCx, GetBuildId);
   JS::SetWarningReporter(aCx, MozCrashWarningReporter);
 
   js::AutoEnterOOMUnsafeRegion::setAnnotateOOMAllocationSizeCallback(
     CrashReporter::AnnotateOOMAllocationSize);
 
   static js::DOMCallbacks DOMcallbacks = {
     InstanceClassHasProtoAtDepth
   };
--- a/xpcom/base/CycleCollectedJSRuntime.h
+++ b/xpcom/base/CycleCollectedJSRuntime.h
@@ -422,14 +422,11 @@ inline bool AddToCCKind(JS::TraceKind aK
 {
   return aKind == JS::TraceKind::Object ||
          aKind == JS::TraceKind::Script ||
          aKind == JS::TraceKind::LazyScript ||
          aKind == JS::TraceKind::Scope ||
          aKind == JS::TraceKind::RegExpShared;
 }
 
-bool
-GetBuildId(JS::BuildIdCharVector* aBuildID);
-
 } // namespace mozilla
 
 #endif // mozilla_CycleCollectedJSRuntime_h