Backed out changeset 0d61bcf08362 (bug 1013531) for bustage.
authorRyan VanderMeulen <ryanvm@gmail.com>
Thu, 29 May 2014 13:26:55 -0400
changeset 185642 29ca8bc78484630eb38ed9e159552b73e34b9bf5
parent 185641 ea7edac9664adc9bdb819cfa1a50353b8348a200
child 185643 ea48287c48a70325bab4928e9c38b0fad1e9a0a3
push id44134
push userryanvm@gmail.com
push dateThu, 29 May 2014 17:27:01 +0000
treeherdermozilla-inbound@29ca8bc78484 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1013531
milestone32.0a1
backs out0d61bcf083620018a023b1da9f735f18b621601c
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
Backed out changeset 0d61bcf08362 (bug 1013531) for bustage. CLOSED TREE
dom/bindings/CallbackObject.cpp
js/public/GCAPI.h
js/src/devtools/rootAnalysis/annotations.js
js/src/devtools/rootAnalysis/computeGCTypes.js
js/src/gc/GCRuntime.h
js/src/jsapi-tests/testGCExactRooting.cpp
js/src/jsgc.cpp
js/src/jsgcinlines.h
js/src/jsobj.h
js/src/jsweakmap.cpp
js/src/jsworkers.cpp
js/src/vm/ForkJoin.cpp
js/src/vm/ForkJoin.h
js/src/vm/SPSProfiler.cpp
js/src/vm/Stack.cpp
js/src/vm/StructuredClone.cpp
js/xpconnect/src/nsCxPusher.cpp
--- a/dom/bindings/CallbackObject.cpp
+++ b/dom/bindings/CallbackObject.cpp
@@ -76,20 +76,17 @@ CallbackObject::CallSetup::CallSetup(Cal
   // callable.
 
   // First, find the real underlying callback.
   JSObject* realCallback = js::UncheckedUnwrap(aCallback->CallbackPreserveColor());
   JSContext* cx = nullptr;
   nsIGlobalObject* globalObject = nullptr;
 
   {
-    // Bug 955660: we cannot do "proper" rooting here because we need the
-    // global to get a context. Everything here is simple getters that cannot
-    // GC, so just paper over the necessary dataflow inversion.
-    JS::AutoSuppressGCAnalysis nogc;
+    JS::AutoAssertNoGC nogc;
     if (mIsMainThread) {
       // Now get the global and JSContext for this callback.
       nsGlobalWindow* win = xpc::WindowGlobalOrNull(realCallback);
       if (win) {
         // Make sure that if this is a window it's the current inner, since the
         // nsIScriptContext and hence JSContext are associated with the outer
         // window.  Which means that if someone holds on to a function from a
         // now-unloaded document we'd have the new document as the script entry
--- a/js/public/GCAPI.h
+++ b/js/public/GCAPI.h
@@ -364,68 +364,44 @@ GetGCNumber();
  * The GC does not immediately return the unused memory freed by a collection
  * back to the system incase it is needed soon afterwards. This call forces the
  * GC to return this memory immediately.
  */
 extern JS_FRIEND_API(void)
 ShrinkGCBuffers(JSRuntime *rt);
 
 /*
- * Assert if a GC occurs while this class is live. This class does not disable
- * the static rooting hazard analysis.
- */
-class JS_PUBLIC_API(AutoAssertOnGC)
-{
-    JSRuntime *runtime;
-    size_t gcNumber;
-
-  public:
-    AutoAssertOnGC();
-    explicit AutoAssertOnGC(JSRuntime *rt);
-    ~AutoAssertOnGC();
-
-    static void VerifyIsSafeToGC(JSRuntime *rt);
-};
-
-/*
- * Disable the static rooting hazard analysis in the live region, but assert if
- * any GC occurs while this guard object is live. This is most useful to help
- * the exact rooting hazard analysis in complex regions, since it cannot
- * understand dataflow.
+ * Assert if any GC occured while this guard object was live. This is most
+ * useful to help the exact rooting hazard analysis in complex regions, since
+ * it cannot understand dataflow.
  *
  * Note: GC behavior is unpredictable even when deterministice and is generally
  *       non-deterministic in practice. The fact that this guard has not
  *       asserted is not a guarantee that a GC cannot happen in the guarded
  *       region. As a rule, anyone performing a GC unsafe action should
  *       understand the GC properties of all code in that region and ensure
  *       that the hazard analysis is correct for that code, rather than relying
  *       on this class.
  */
-class JS_PUBLIC_API(AutoSuppressGCAnalysis) : public AutoAssertOnGC
+class JS_PUBLIC_API(AutoAssertNoGC)
 {
-  public:
-    AutoSuppressGCAnalysis() : AutoAssertOnGC() {}
-    explicit AutoSuppressGCAnalysis(JSRuntime *rt) : AutoAssertOnGC(rt) {}
-};
+#ifdef JS_DEBUG
+    JSRuntime *runtime;
+    size_t gcNumber;
 
-/*
- * Place AutoCheckCannotGC in scopes that you believe can never GC. These
- * annotations will be verified both dynamically via AutoAssertOnGC, and
- * statically with the rooting hazard analysis (implemented by making the
- * analysis consider AutoCheckCannotGC to be a GC pointer, and therefore
- * complain if it is live across a GC call.) It is useful when dealing with
- * internal pointers to GC things where the GC thing itself may not be present
- * for the static analysis: e.g. acquiring inline chars from a JSString* on the
- * heap.
- */
-class JS_PUBLIC_API(AutoCheckCannotGC) : public AutoAssertOnGC
-{
   public:
-    AutoCheckCannotGC() : AutoAssertOnGC() {}
-    explicit AutoCheckCannotGC(JSRuntime *rt) : AutoAssertOnGC(rt) {}
+    AutoAssertNoGC();
+    AutoAssertNoGC(JSRuntime *rt);
+    ~AutoAssertNoGC();
+#else
+  public:
+    /* Prevent unreferenced local warnings in opt builds. */
+    AutoAssertNoGC() {}
+    explicit AutoAssertNoGC(JSRuntime *) {}
+#endif
 };
 
 class JS_PUBLIC_API(ObjectPtr)
 {
     Heap<JSObject *> value;
 
   public:
     ObjectPtr() : value(nullptr) {}
--- a/js/src/devtools/rootAnalysis/annotations.js
+++ b/js/src/devtools/rootAnalysis/annotations.js
@@ -133,17 +133,17 @@ function ignoreEdgeAddressTaken(edge)
 
 // Ignore calls of these functions (so ignore any stack containing these)
 var ignoreFunctions = {
     "ptio.c:pt_MapError" : true,
     "je_malloc_printf" : true,
     "PR_ExplodeTime" : true,
     "PR_ErrorInstallTable" : true,
     "PR_SetThreadPrivate" : true,
-    "JSObject* js::GetWeakmapKeyDelegate(JSObject*)" : true, // FIXME: mark with AutoSuppressGCAnalysis instead
+    "JSObject* js::GetWeakmapKeyDelegate(JSObject*)" : true, // FIXME: mark with AutoAssertNoGC instead
     "uint8 NS_IsMainThread()" : true,
 
     // FIXME!
     "NS_LogInit": true,
     "NS_LogTerm": true,
     "NS_LogAddRef": true,
     "NS_LogRelease": true,
     "NS_LogCtor": true,
@@ -156,17 +156,17 @@ var ignoreFunctions = {
 
     // These are a little overzealous -- these destructors *can* GC if they end
     // up wrapping a pending exception. See bug 898815 for the heavyweight fix.
     "void js::AutoCompartment::~AutoCompartment(int32)" : true,
     "void JSAutoCompartment::~JSAutoCompartment(int32)" : true,
 
     // Bug 948646 - the only thing AutoJSContext's constructor calls
     // is an Init() routine whose entire body is covered with an
-    // AutoSuppressGCAnalysis. AutoSafeJSContext is the same thing, just with
+    // AutoAssertNoGC. AutoSafeJSContext is the same thing, just with
     // a different value for the 'aSafe' parameter.
     "void mozilla::AutoJSContext::AutoJSContext(mozilla::detail::GuardObjectNotifier*)" : true,
     "void mozilla::AutoSafeJSContext::~AutoSafeJSContext(int32)" : true,
 
     // And these are workarounds to avoid even more analysis work,
     // which would sadly still be needed even with bug 898815.
     "void js::AutoCompartment::AutoCompartment(js::ExclusiveContext*, JSCompartment*)": true,
 };
@@ -225,17 +225,17 @@ function isRootedPointerTypeName(name)
 
     return name.startsWith('Rooted') || name.startsWith('PersistentRooted');
 }
 
 function isSuppressConstructor(name)
 {
     return name.indexOf("::AutoSuppressGC") != -1
         || name.indexOf("::AutoEnterAnalysis") != -1
-        || name.indexOf("::AutoSuppressGCAnalysis") != -1
+        || name.indexOf("::AutoAssertNoGC") != -1
         || name.indexOf("::AutoIgnoreRootingHazards") != -1;
 }
 
 // nsISupports subclasses' methods may be scriptable (or overridden
 // via binary XPCOM), and so may GC. But some fields just aren't going
 // to get overridden with something that can GC.
 function isOverridableField(initialCSU, csu, field)
 {
--- a/js/src/devtools/rootAnalysis/computeGCTypes.js
+++ b/js/src/devtools/rootAnalysis/computeGCTypes.js
@@ -128,17 +128,16 @@ addGCType('js::ObjectImpl');
 addGCType('JSString');
 addGCType('js::Shape');
 addGCType('js::BaseShape');
 addGCType('JSScript');
 addGCType('js::LazyScript');
 addGCType('js::ion::IonCode');
 addGCPointer('JS::Value');
 addGCPointer('jsid');
-addGCPointer('JS::AutoCheckCannotGC');
 
 function explain(csu, indent, seen) {
     if (!seen)
         seen = Set();
     seen.add(csu);
     if (!(csu in gcFields))
         return;
     if (gcFields[csu].has('<annotation>')) {
--- a/js/src/gc/GCRuntime.h
+++ b/js/src/gc/GCRuntime.h
@@ -532,24 +532,16 @@ class GCRuntime
     size_t                systemPageSize;
 
     /* The OS allocation granularity may not match the page size. */
     size_t                systemAllocGranularity;
 
     /* Strong references on scripts held for PCCount profiling API. */
     js::ScriptAndCountsVector *scriptAndCountsVector;
 
-    /*
-     * Some regions of code are hard for the static rooting hazard analysis to
-     * understand. In those cases, we trade the static analysis for a dynamic
-     * analysis. When this is non-zero, we should assert if we trigger, or
-     * might trigger, a GC.
-     */
-    int inUnsafeRegion;
-
   private:
     /* Always preserve JIT code during GCs, for testing. */
     bool                  alwaysPreserveCode;
 
 #ifdef DEBUG
     size_t                noGCOrAllocationCheck;
 #endif
 
--- a/js/src/jsapi-tests/testGCExactRooting.cpp
+++ b/js/src/jsapi-tests/testGCExactRooting.cpp
@@ -16,22 +16,8 @@ BEGIN_TEST(testGCExactRooting)
 
     /* Use the objects we just created to ensure that they are still alive. */
     JS_DefineProperty(cx, rootCx, "foo", JS::UndefinedHandleValue, 0);
     JS_DefineProperty(cx, rootRt, "foo", JS::UndefinedHandleValue, 0);
 
     return true;
 }
 END_TEST(testGCExactRooting)
-
-BEGIN_TEST(testGCSuppressions)
-{
-    JS::AutoAssertOnGC nogc;
-    JS::AutoCheckCannotGC checkgc;
-    JS::AutoSuppressGCAnalysis noanalysis;
-
-    JS::AutoAssertOnGC nogcRt(cx->runtime());
-    JS::AutoCheckCannotGC checkgcRt(cx->runtime());
-    JS::AutoSuppressGCAnalysis noanalysisRt(cx->runtime());
-
-    return true;
-}
-END_TEST(testGCSuppressions)
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -183,17 +183,16 @@
 # include <unistd.h>
 #endif
 
 #include "jsapi.h"
 #include "jsatom.h"
 #include "jscntxt.h"
 #include "jscompartment.h"
 #include "jsobj.h"
-#include "jsprf.h"
 #include "jsscript.h"
 #include "jstypes.h"
 #include "jsutil.h"
 #include "jswatchpoint.h"
 #include "jsweakmap.h"
 #ifdef XP_WIN
 # include "jswin.h"
 #endif
@@ -1110,24 +1109,23 @@ GCRuntime::GCRuntime(JSRuntime *rt) :
 #endif
     validate(true),
     fullCompartmentChecks(false),
     gcCallback(nullptr),
     sliceCallback(nullptr),
     mallocBytes(0),
     mallocGCTriggered(false),
     scriptAndCountsVector(nullptr),
-    helperState(rt),
     alwaysPreserveCode(false),
 #ifdef DEBUG
     noGCOrAllocationCheck(0),
 #endif
     lock(nullptr),
     lockOwner(nullptr),
-    inUnsafeRegion(0)
+    helperState(rt)
 {
 }
 
 #ifdef JS_GC_ZEAL
 
 extern void
 js::SetGCZeal(JSRuntime *rt, uint8_t zeal, uint32_t frequency)
 {
@@ -4329,19 +4327,16 @@ AutoGCSession::AutoGCSession(GCRuntime *
     gc->isNeeded = false;
     gc->interFrameGC = true;
 
     gc->number++;
 
     // It's ok if threads other than the main thread have suppressGC set, as
     // they are operating on zones which will not be collected from here.
     JS_ASSERT(!gc->rt->mainThread.suppressGC);
-
-    // Assert if this is a GC unsafe region.
-    JS::AutoAssertOnGC::VerifyIsSafeToGC(gc->rt);
 }
 
 AutoGCSession::~AutoGCSession()
 {
     if (canceled)
         return;
 
 #ifndef JS_MORE_DETERMINISTIC
@@ -5621,55 +5616,37 @@ js::gc::AssertGCThingHasType(js::gc::Cel
 JS_FRIEND_API(size_t)
 JS::GetGCNumber()
 {
     JSRuntime *rt = js::TlsPerThreadData.get()->runtimeFromMainThread();
     if (!rt)
         return 0;
     return rt->gc.number;
 }
-#endif
-
-JS::AutoAssertOnGC::AutoAssertOnGC()
+
+JS::AutoAssertNoGC::AutoAssertNoGC()
   : runtime(nullptr), gcNumber(0)
 {
     js::PerThreadData *data = js::TlsPerThreadData.get();
     if (data) {
         /*
          * GC's from off-thread will always assert, so off-thread is implicitly
-         * AutoAssertOnGC. We still need to allow AutoAssertOnGC to be used in
+         * AutoAssertNoGC. We still need to allow AutoAssertNoGC to be used in
          * code that works from both threads, however. We also use this to
          * annotate the off thread run loops.
          */
         runtime = data->runtimeIfOnOwnerThread();
-        if (runtime) {
+        if (runtime)
             gcNumber = runtime->gc.number;
-            ++runtime->gc.inUnsafeRegion;
-        }
     }
 }
 
-JS::AutoAssertOnGC::AutoAssertOnGC(JSRuntime *rt)
+JS::AutoAssertNoGC::AutoAssertNoGC(JSRuntime *rt)
   : runtime(rt), gcNumber(rt->gc.number)
 {
-    ++rt->gc.inUnsafeRegion;
-}
-
-JS::AutoAssertOnGC::~AutoAssertOnGC()
-{
-    if (runtime) {
-        --runtime->gc.inUnsafeRegion;
-        MOZ_ASSERT(runtime->gc.inUnsafeRegion >= 0);
-
-        /*
-         * The following backstop assertion should never fire: if we bumped the
-         * gcNumber, we should have asserted because inUnsafeRegion was true.
-         */
-        MOZ_ASSERT(gcNumber == runtime->gc.number, "GC ran inside an AutoAssertOnGC scope.");
-    }
-}
-
-/* static */ void
-JS::AutoAssertOnGC::VerifyIsSafeToGC(JSRuntime *rt)
-{
-    if (rt->gc.inUnsafeRegion > 0)
-        MOZ_CRASH("[AutoAssertOnGC] possible GC in GC-unsafe region");
-}
+}
+
+JS::AutoAssertNoGC::~AutoAssertNoGC()
+{
+    if (runtime)
+        MOZ_ASSERT(gcNumber == runtime->gc.number, "GC ran inside an AutoAssertNoGC scope.");
+}
+#endif
--- a/js/src/jsgcinlines.h
+++ b/js/src/jsgcinlines.h
@@ -499,20 +499,16 @@ CheckAllocatorState(ThreadSafeContext *c
     JS_ASSERT_IF(rt->isAtomsCompartment(ncx->compartment()),
                  kind == FINALIZE_STRING ||
                  kind == FINALIZE_FAT_INLINE_STRING ||
                  kind == FINALIZE_JITCODE);
     JS_ASSERT(!rt->isHeapBusy());
     JS_ASSERT(rt->gc.isAllocAllowed());
 #endif
 
-    // Crash if we perform a GC action when it is not safe.
-    if (allowGC && !rt->mainThread.suppressGC)
-        JS::AutoAssertOnGC::VerifyIsSafeToGC(rt);
-
     // For testing out of memory conditions
     if (!PossiblyFail()) {
         js_ReportOutOfMemory(cx);
         return false;
     }
 
     if (allowGC) {
 #ifdef JS_GC_ZEAL
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -1198,17 +1198,17 @@ js_IsCallable(const js::Value &v)
 {
     return v.isObject() && v.toObject().isCallable();
 }
 
 inline JSObject *
 GetInnerObject(JSObject *obj)
 {
     if (js::InnerObjectOp op = obj->getClass()->ext.innerObject) {
-        JS::AutoSuppressGCAnalysis nogc;
+        JS::AutoAssertNoGC nogc;
         return op(obj);
     }
     return obj;
 }
 
 inline JSObject *
 GetOuterObject(JSContext *cx, js::HandleObject obj)
 {
--- a/js/src/jsweakmap.cpp
+++ b/js/src/jsweakmap.cpp
@@ -160,17 +160,17 @@ WeakMapBase::removeWeakMapFromList(WeakM
 bool
 ObjectValueMap::findZoneEdges()
 {
     /*
      * For unmarked weakmap keys with delegates in a different zone, add a zone
      * edge to ensure that the delegate zone does finish marking after the key
      * zone.
      */
-    JS::AutoSuppressGCAnalysis nogc;
+    JS::AutoAssertNoGC nogc;
     Zone *mapZone = compartment->zone();
     for (Range r = all(); !r.empty(); r.popFront()) {
         JSObject *key = r.front().key();
         if (key->isMarked(BLACK) && !key->isMarked(GRAY))
             continue;
         JSWeakmapKeyDelegateOp op = key->getClass()->ext.weakmapKeyDelegateOp;
         if (!op)
             continue;
--- a/js/src/jsworkers.cpp
+++ b/js/src/jsworkers.cpp
@@ -1042,17 +1042,17 @@ WorkerThread::handleGCHelperWorkload()
     }
 
     gcHelperState = nullptr;
 }
 
 void
 WorkerThread::threadLoop()
 {
-    JS::AutoSuppressGCAnalysis nogc;
+    JS::AutoAssertNoGC nogc;
     AutoLockWorkerThreadState lock;
 
     js::TlsPerThreadData.set(threadData.addr());
 
     // Compute the thread's stack limit, for over-recursed checks.
     uintptr_t stackLimit = GetNativeStackBase();
 #if JS_STACK_GROWTH_DIRECTION > 0
     stackLimit += WORKER_STACK_QUOTA;
--- a/js/src/vm/ForkJoin.cpp
+++ b/js/src/vm/ForkJoin.cpp
@@ -1498,25 +1498,25 @@ ForkJoinShared::executeFromMainThread(Th
 }
 
 void
 ForkJoinShared::executePortion(PerThreadData *perThread, ThreadPoolWorker *worker)
 {
     // WARNING: This code runs ON THE PARALLEL WORKER THREAD.
     // Be careful when accessing cx_.
 
+    // ForkJoinContext already contains an AutoAssertNoGC; however, the analysis
+    // does not propagate this type information. We duplicate the assertion
+    // here for maximum clarity.
+    JS::AutoAssertNoGC nogc(runtime());
+
     Allocator *allocator = allocators_[worker->id()];
     ForkJoinContext cx(perThread, worker, allocator, this, &records_[worker->id()]);
     AutoSetForkJoinContext autoContext(&cx);
 
-    // ForkJoinContext already contains an AutoSuppressGCAnalysis; however, the
-    // analysis does not propagate this type information. We duplicate the
-    // assertion here for maximum clarity.
-    JS::AutoSuppressGCAnalysis nogc;
-
 #ifdef DEBUG
     // Set the maximum worker and slice number for prettier spewing.
     cx.maxWorkerId = threadPool_->numWorkers();
 #endif
 
     Spew(SpewOps, "Up");
 
     // Make a new IonContext for the slice, which is needed if we need to
@@ -1617,17 +1617,17 @@ ForkJoinContext::ForkJoinContext(PerThre
                                  ParallelBailoutRecord *bailoutRecord)
   : ThreadSafeContext(shared->runtime(), perThreadData, Context_ForkJoin),
     bailoutRecord(bailoutRecord),
     targetRegionStart(nullptr),
     targetRegionEnd(nullptr),
     shared_(shared),
     worker_(worker),
     acquiredJSContext_(false),
-    nogc_()
+    nogc_(shared->runtime())
 {
     /*
      * Unsafely set the zone. This is used to track malloc counters and to
      * trigger GCs and is otherwise not thread-safe to access.
      */
     zone_ = shared->zone();
 
     /*
--- a/js/src/vm/ForkJoin.h
+++ b/js/src/vm/ForkJoin.h
@@ -421,17 +421,17 @@ class ForkJoinContext : public ThreadSaf
     ForkJoinShared *const shared_;
 
     ThreadPoolWorker *worker_;
 
     bool acquiredJSContext_;
 
     // ForkJoinContext is allocated on the stack. It would be dangerous to GC
     // with it live because of the GC pointer fields stored in the context.
-    JS::AutoSuppressGCAnalysis nogc_;
+    JS::AutoAssertNoGC nogc_;
 };
 
 // Locks a JSContext for its scope. Be very careful, because locking a
 // JSContext does *not* allow you to safely mutate the data in the
 // JSContext unless you can guarantee that any of the other threads
 // that want to access that data will also acquire the lock, which is
 // generally not the case. For example, the lock is used in the IC
 // code to allow us to atomically patch up the dispatch table, but we
--- a/js/src/vm/SPSProfiler.cpp
+++ b/js/src/vm/SPSProfiler.cpp
@@ -138,17 +138,17 @@ SPSProfiler::onScriptFinalized(JSScript 
     }
 }
 
 void
 SPSProfiler::markEvent(const char *event)
 {
     JS_ASSERT(enabled());
     if (eventMarker_) {
-        JS::AutoSuppressGCAnalysis nogc;
+        JS::AutoAssertNoGC nogc;
         eventMarker_(event);
     }
 }
 
 bool
 SPSProfiler::enter(JSScript *script, JSFunction *maybeFun)
 {
     const char *str = profileString(script, maybeFun);
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -554,17 +554,17 @@ FrameIter::settleOnActivation()
             continue;
         }
 
         // If the caller supplied principals, only show activations which are subsumed (of the same
         // origin or of an origin accessible) by these principals.
         if (data_.principals_) {
             JSContext *cx = data_.cx_->asJSContext();
             if (JSSubsumesOp subsumes = cx->runtime()->securityCallbacks->subsumes) {
-                JS::AutoSuppressGCAnalysis nogc;
+                JS::AutoAssertNoGC nogc;
                 if (!subsumes(data_.principals_, activation->compartment()->principals)) {
                     ++data_.activations_;
                     continue;
                 }
             }
         }
 
 #ifdef JS_ION
--- a/js/src/vm/StructuredClone.cpp
+++ b/js/src/vm/StructuredClone.cpp
@@ -365,17 +365,17 @@ Discard(uint64_t *buffer, size_t nbytes,
     SCInput::getPair(point++, &tag, &data);
     if (tag != SCTAG_TRANSFER_MAP_HEADER)
         return;
 
     if (TransferableMapHeader(data) == SCTAG_TM_TRANSFERRED)
         return;
 
     // freeTransfer should not GC
-    JS::AutoSuppressGCAnalysis nogc;
+    JS::AutoAssertNoGC nogc;
 
     uint64_t numTransferables = LittleEndian::readUint64(point++);
     while (numTransferables--) {
         uint32_t ownership;
         SCInput::getPair(point++, &tag, &ownership);
         JS_ASSERT(tag >= SCTAG_TRANSFER_MAP_PENDING_ENTRY);
 
         void *content;
--- a/js/xpconnect/src/nsCxPusher.cpp
+++ b/js/xpconnect/src/nsCxPusher.cpp
@@ -178,17 +178,17 @@ AutoJSContext::AutoJSContext(bool aSafe 
   : mCx(nullptr)
 {
   Init(aSafe MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT);
 }
 
 void
 AutoJSContext::Init(bool aSafe MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
 {
-  JS::AutoSuppressGCAnalysis nogc;
+  JS::AutoAssertNoGC nogc;
   MOZ_ASSERT(!mCx, "mCx should not be initialized!");
 
   MOZ_GUARD_OBJECT_NOTIFIER_INIT;
 
   nsXPConnect *xpc = nsXPConnect::XPConnect();
   if (!aSafe) {
     mCx = xpc->GetCurrentJSContext();
   }