Bug 1134425 - Part 1: move the allocator interface code out of line; r=jonco
authorTerrence Cole <terrence@mozilla.com>
Wed, 04 Mar 2015 09:32:02 -0800
changeset 231927 7c9dfca903cce7a83dae3c780cfdd96701ba0559
parent 231926 57e351862f31bf7282bc22f1cc1146551104410b
child 231928 afad28f235a80d9d5303017fb44449f761acfd83
push id56392
push usertcole@mozilla.com
push dateWed, 04 Mar 2015 22:41:44 +0000
treeherdermozilla-inbound@7c9dfca903cc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjonco
bugs1134425
milestone39.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 1134425 - Part 1: move the allocator interface code out of line; r=jonco
js/public/MemoryMetrics.h
js/src/asmjs/AsmJSModule.cpp
js/src/builtin/AtomicsObject.cpp
js/src/gc/Allocator.cpp
js/src/gc/Allocator.h
js/src/gc/Nursery.cpp
js/src/gc/StoreBuffer.cpp
js/src/jit/BaselineJIT.cpp
js/src/jit/Ion.cpp
js/src/jit/MIRGenerator.h
js/src/jit/MacroAssembler.cpp
js/src/jit/OptimizationTracking.cpp
js/src/jsarray.cpp
js/src/jscompartment.cpp
js/src/jsgcinlines.h
js/src/jsmath.cpp
js/src/jsobjinlines.h
js/src/jspropertytree.cpp
js/src/moz.build
js/src/vm/ArrayObject-inl.h
js/src/vm/ObjectGroup.cpp
js/src/vm/ProxyObject.cpp
js/src/vm/Runtime-inl.h
js/src/vm/Shape-inl.h
js/src/vm/String-inl.h
js/src/vm/Symbol.cpp
js/src/vm/TypeInference.cpp
--- a/js/public/MemoryMetrics.h
+++ b/js/public/MemoryMetrics.h
@@ -14,16 +14,17 @@
 #include "mozilla/PodOperations.h"
 
 #include <string.h>
 
 #include "jsalloc.h"
 #include "jspubtd.h"
 
 #include "js/HashTable.h"
+#include "js/TracingAPI.h"
 #include "js/Utility.h"
 #include "js/Vector.h"
 
 class nsISupports;      // Needed for ObjectPrivateVisitor.
 
 namespace JS {
 
 struct TabSizes
--- a/js/src/asmjs/AsmJSModule.cpp
+++ b/js/src/asmjs/AsmJSModule.cpp
@@ -32,32 +32,34 @@
 #include "jsprf.h"
 #ifdef XP_WIN
 # include "jswin.h"
 #endif
 #include "prmjtime.h"
 
 #include "frontend/Parser.h"
 #include "jit/IonCode.h"
+#include "js/Class.h"
 #include "js/Conversions.h"
 #include "js/MemoryMetrics.h"
 
 #include "jsobjinlines.h"
 
 #include "frontend/ParseNode-inl.h"
 #include "vm/ArrayBufferObject-inl.h"
 #include "vm/Stack-inl.h"
 
 using namespace js;
 using namespace jit;
 using namespace frontend;
 using mozilla::BinarySearch;
+using mozilla::Compression::LZ4;
 using mozilla::PodCopy;
 using mozilla::PodEqual;
-using mozilla::Compression::LZ4;
+using mozilla::PodZero;
 using mozilla::Swap;
 
 static uint8_t *
 AllocateExecutableMemory(ExclusiveContext *cx, size_t bytes)
 {
 #ifdef XP_WIN
     unsigned permissions = PAGE_EXECUTE_READWRITE;
 #else
--- a/js/src/builtin/AtomicsObject.cpp
+++ b/js/src/builtin/AtomicsObject.cpp
@@ -50,16 +50,17 @@
 #include "mozilla/Atomics.h"
 #include "mozilla/FloatingPoint.h"
 
 #include "jsapi.h"
 #include "jsfriendapi.h"
 
 #include "prmjtime.h"
 
+#include "js/Class.h"
 #include "vm/GlobalObject.h"
 #include "vm/SharedTypedArrayObject.h"
 #include "vm/TypedArrayObject.h"
 
 #include "jsobjinlines.h"
 
 using namespace js;
 
new file mode 100644
--- /dev/null
+++ b/js/src/gc/Allocator.cpp
@@ -0,0 +1,355 @@
+/* -*- 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/. */
+
+#include "gc/Allocator.h"
+
+#include "jscntxt.h"
+
+#include "gc/GCTrace.h"
+#include "gc/Nursery.h"
+#include "jit/JitCompartment.h"
+#include "vm/Runtime.h"
+#include "vm/String.h"
+
+#include "jsobjinlines.h"
+
+using namespace js;
+using namespace gc;
+
+static inline bool
+ShouldNurseryAllocateObject(const Nursery &nursery, InitialHeap heap)
+{
+    return nursery.isEnabled() && heap != TenuredHeap;
+}
+
+/*
+ * Attempt to allocate a new GC thing out of the nursery. If there is not enough
+ * room in the nursery or there is an OOM, this method will return nullptr.
+ */
+template <AllowGC allowGC>
+inline JSObject *
+TryNewNurseryObject(JSContext *cx, size_t thingSize, size_t nDynamicSlots, const Class *clasp)
+{
+    MOZ_ASSERT(!IsAtomsCompartment(cx->compartment()));
+    JSRuntime *rt = cx->runtime();
+    Nursery &nursery = rt->gc.nursery;
+    JSObject *obj = nursery.allocateObject(cx, thingSize, nDynamicSlots, clasp);
+    if (obj)
+        return obj;
+    if (allowGC && !rt->mainThread.suppressGC) {
+        cx->minorGC(JS::gcreason::OUT_OF_NURSERY);
+
+        /* Exceeding gcMaxBytes while tenuring can disable the Nursery. */
+        if (nursery.isEnabled()) {
+            JSObject *obj = nursery.allocateObject(cx, thingSize, nDynamicSlots, clasp);
+            MOZ_ASSERT(obj);
+            return obj;
+        }
+    }
+    return nullptr;
+}
+
+static inline bool
+PossiblyFail()
+{
+    JS_OOM_POSSIBLY_FAIL_BOOL();
+    return true;
+}
+
+static inline bool
+GCIfNeeded(ExclusiveContext *cx)
+{
+    if (cx->isJSContext()) {
+        JSContext *ncx = cx->asJSContext();
+        JSRuntime *rt = ncx->runtime();
+
+#ifdef JS_GC_ZEAL
+        if (rt->gc.needZealousGC())
+            rt->gc.runDebugGC();
+#endif
+
+        // Invoking the interrupt callback can fail and we can't usefully
+        // handle that here. Just check in case we need to collect instead.
+        if (rt->hasPendingInterrupt())
+            rt->gc.gcIfRequested(ncx);
+
+        // If we have grown past our GC heap threshold while in the middle of
+        // an incremental GC, we're growing faster than we're GCing, so stop
+        // the world and do a full, non-incremental GC right now, if possible.
+        if (rt->gc.isIncrementalGCInProgress() &&
+            cx->zone()->usage.gcBytes() > cx->zone()->threshold.gcTriggerBytes())
+        {
+            PrepareZoneForGC(cx->zone());
+            AutoKeepAtoms keepAtoms(cx->perThreadData);
+            rt->gc.gc(GC_NORMAL, JS::gcreason::INCREMENTAL_TOO_SLOW);
+        }
+    }
+
+    return true;
+}
+
+template <AllowGC allowGC>
+static inline bool
+CheckAllocatorState(ExclusiveContext *cx, AllocKind kind)
+{
+    if (allowGC) {
+        if (!GCIfNeeded(cx))
+            return false;
+    }
+
+    if (!cx->isJSContext())
+        return true;
+
+    JSContext *ncx = cx->asJSContext();
+    JSRuntime *rt = ncx->runtime();
+#if defined(JS_GC_ZEAL) || defined(DEBUG)
+    MOZ_ASSERT_IF(rt->isAtomsCompartment(ncx->compartment()),
+                  kind == FINALIZE_STRING ||
+                  kind == FINALIZE_FAT_INLINE_STRING ||
+                  kind == FINALIZE_SYMBOL ||
+                  kind == FINALIZE_JITCODE);
+    MOZ_ASSERT(!rt->isHeapBusy());
+    MOZ_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()) {
+        ReportOutOfMemory(ncx);
+        return false;
+    }
+
+    return true;
+}
+
+template <typename T>
+static inline void
+CheckIncrementalZoneState(ExclusiveContext *cx, T *t)
+{
+#ifdef DEBUG
+    if (!cx->isJSContext())
+        return;
+
+    Zone *zone = cx->asJSContext()->zone();
+    MOZ_ASSERT_IF(t && zone->wasGCStarted() && (zone->isGCMarking() || zone->isGCSweeping()),
+                  t->asTenured().arenaHeader()->allocatedDuringIncremental);
+#endif
+}
+
+/*
+ * Allocate a new GC thing. After a successful allocation the caller must
+ * fully initialize the thing before calling any function that can potentially
+ * trigger GC. This will ensure that GC tracing never sees junk values stored
+ * in the partially initialized thing.
+ */
+
+template <AllowGC allowGC>
+inline JSObject *
+AllocateObject(ExclusiveContext *cx, AllocKind kind, size_t nDynamicSlots, InitialHeap heap,
+               const Class *clasp)
+{
+    size_t thingSize = Arena::thingSize(kind);
+
+    MOZ_ASSERT(thingSize == Arena::thingSize(kind));
+    MOZ_ASSERT(thingSize >= sizeof(JSObject_Slots0));
+    static_assert(sizeof(JSObject_Slots0) >= CellSize,
+                  "All allocations must be at least the allocator-imposed minimum size.");
+
+    if (!CheckAllocatorState<allowGC>(cx, kind))
+        return nullptr;
+
+    if (cx->isJSContext() &&
+        ShouldNurseryAllocateObject(cx->asJSContext()->nursery(), heap))
+    {
+        JSObject *obj = TryNewNurseryObject<allowGC>(cx->asJSContext(), thingSize, nDynamicSlots,
+                                                     clasp);
+        if (obj)
+            return obj;
+    }
+
+    HeapSlot *slots = nullptr;
+    if (nDynamicSlots) {
+        slots = cx->zone()->pod_malloc<HeapSlot>(nDynamicSlots);
+        if (MOZ_UNLIKELY(!slots))
+            return nullptr;
+        Debug_SetSlotRangeToCrashOnTouch(slots, nDynamicSlots);
+    }
+
+    JSObject *obj = reinterpret_cast<JSObject *>(cx->arenas()->allocateFromFreeList(kind, thingSize));
+    if (!obj)
+        obj = reinterpret_cast<JSObject *>(GCRuntime::refillFreeListFromAnyThread<allowGC>(cx, kind));
+
+    if (obj)
+        obj->setInitialSlotsMaybeNonNative(slots);
+    else
+        js_free(slots);
+
+    CheckIncrementalZoneState(cx, obj);
+    TraceTenuredAlloc(obj, kind);
+    return obj;
+}
+
+template <typename T, AllowGC allowGC>
+inline T *
+AllocateNonObject(ExclusiveContext *cx)
+{
+    static_assert(sizeof(T) >= CellSize,
+                  "All allocations must be at least the allocator-imposed minimum size.");
+
+    AllocKind kind = MapTypeToFinalizeKind<T>::kind;
+    size_t thingSize = sizeof(T);
+
+    MOZ_ASSERT(thingSize == Arena::thingSize(kind));
+    if (!CheckAllocatorState<allowGC>(cx, kind))
+        return nullptr;
+
+    T *t = static_cast<T *>(cx->arenas()->allocateFromFreeList(kind, thingSize));
+    if (!t)
+        t = static_cast<T *>(GCRuntime::refillFreeListFromAnyThread<allowGC>(cx, kind));
+
+    CheckIncrementalZoneState(cx, t);
+    TraceTenuredAlloc(t, kind);
+    return t;
+}
+
+/*
+ * When allocating for initialization from a cached object copy, we will
+ * potentially destroy the cache entry we want to copy if we allow GC. On the
+ * other hand, since these allocations are extremely common, we don't want to
+ * delay GC from these allocation sites. Instead we allow the GC, but still
+ * fail the allocation, forcing the non-cached path.
+ */
+template <AllowGC allowGC>
+NativeObject *
+js::gc::AllocateObjectForCacheHit(JSContext *cx, AllocKind kind, InitialHeap heap,
+                                  const js::Class *clasp)
+{
+    MOZ_ASSERT(clasp->isNative());
+
+    if (ShouldNurseryAllocateObject(cx->nursery(), heap)) {
+        size_t thingSize = Arena::thingSize(kind);
+
+        MOZ_ASSERT(thingSize == Arena::thingSize(kind));
+        if (!CheckAllocatorState<NoGC>(cx, kind))
+            return nullptr;
+
+        JSObject *obj = TryNewNurseryObject<NoGC>(cx, thingSize, 0, clasp);
+        if (!obj && allowGC) {
+            cx->minorGC(JS::gcreason::OUT_OF_NURSERY);
+            return nullptr;
+        }
+        return reinterpret_cast<NativeObject *>(obj);
+    }
+
+    JSObject *obj = AllocateObject<NoGC>(cx, kind, 0, heap, clasp);
+    if (!obj && allowGC) {
+        cx->runtime()->gc.maybeGC(cx->zone());
+        return nullptr;
+    }
+
+    return reinterpret_cast<NativeObject *>(obj);
+}
+template NativeObject *js::gc::AllocateObjectForCacheHit<CanGC>(JSContext *, AllocKind, InitialHeap,
+                                                                const Class *);
+template NativeObject *js::gc::AllocateObjectForCacheHit<NoGC>(JSContext *, AllocKind, InitialHeap,
+                                                               const Class *);
+
+template <AllowGC allowGC>
+JSObject *
+js::NewGCObject(ExclusiveContext *cx, AllocKind kind, size_t nDynamicSlots,
+            InitialHeap heap, const Class *clasp)
+{
+    MOZ_ASSERT(kind >= FINALIZE_OBJECT0 && kind <= FINALIZE_OBJECT_LAST);
+    return AllocateObject<allowGC>(cx, kind, nDynamicSlots, heap, clasp);
+}
+template JSObject *js::NewGCObject<CanGC>(ExclusiveContext *, AllocKind, size_t, InitialHeap,
+                                          const Class *);
+template JSObject *js::NewGCObject<NoGC>(ExclusiveContext *, AllocKind, size_t, InitialHeap,
+                                         const Class *);
+
+template <AllowGC allowGC>
+jit::JitCode *
+js::NewJitCode(ExclusiveContext *cx)
+{
+    return AllocateNonObject<jit::JitCode, allowGC>(cx);
+}
+template jit::JitCode *js::NewJitCode<CanGC>(ExclusiveContext *cx);
+template jit::JitCode *js::NewJitCode<NoGC>(ExclusiveContext *cx);
+
+ObjectGroup *
+js::NewObjectGroup(ExclusiveContext *cx)
+{
+    return AllocateNonObject<ObjectGroup, CanGC>(cx);
+}
+
+template <AllowGC allowGC>
+JSString *
+js::NewGCString(ExclusiveContext *cx)
+{
+    return AllocateNonObject<JSString, allowGC>(cx);
+}
+template JSString *js::NewGCString<CanGC>(ExclusiveContext *cx);
+template JSString *js::NewGCString<NoGC>(ExclusiveContext *cx);
+
+template <AllowGC allowGC>
+JSFatInlineString *
+js::NewGCFatInlineString(ExclusiveContext *cx)
+{
+    return AllocateNonObject<JSFatInlineString, allowGC>(cx);
+}
+template JSFatInlineString *js::NewGCFatInlineString<CanGC>(ExclusiveContext *cx);
+template JSFatInlineString *js::NewGCFatInlineString<NoGC>(ExclusiveContext *cx);
+
+JSExternalString *
+js::NewGCExternalString(ExclusiveContext *cx)
+{
+    return AllocateNonObject<JSExternalString, CanGC>(cx);
+}
+
+Shape *
+js::NewGCShape(ExclusiveContext *cx)
+{
+    return AllocateNonObject<Shape, CanGC>(cx);
+}
+
+Shape *
+js::NewGCAccessorShape(ExclusiveContext *cx)
+{
+    return AllocateNonObject<AccessorShape, CanGC>(cx);
+}
+
+JSScript *
+js::NewGCScript(ExclusiveContext *cx)
+{
+    return AllocateNonObject<JSScript, CanGC>(cx);
+}
+
+LazyScript *
+js::NewGCLazyScript(ExclusiveContext *cx)
+{
+    return AllocateNonObject<LazyScript, CanGC>(cx);
+}
+
+template <AllowGC allowGC>
+BaseShape *
+js::NewGCBaseShape(ExclusiveContext *cx)
+{
+    return AllocateNonObject<BaseShape, allowGC>(cx);
+}
+template BaseShape *js::NewGCBaseShape<CanGC>(ExclusiveContext *cx);
+template BaseShape *js::NewGCBaseShape<NoGC>(ExclusiveContext *cx);
+
+template <AllowGC allowGC>
+JS::Symbol *
+js::NewGCSymbol(ExclusiveContext *cx)
+{
+    return AllocateNonObject<JS::Symbol, allowGC>(cx);
+}
+template JS::Symbol *js::NewGCSymbol<CanGC>(ExclusiveContext *cx);
+template JS::Symbol *js::NewGCSymbol<NoGC>(ExclusiveContext *cx);
new file mode 100644
--- /dev/null
+++ b/js/src/gc/Allocator.h
@@ -0,0 +1,84 @@
+/* -*- 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/. */
+
+#ifndef gc_Allocator_h
+#define gc_Allocator_h
+
+#include "gc/Heap.h"
+#include "js/RootingAPI.h"
+
+namespace JS {
+class Symbol;
+} // namespace JS
+class JSExternalString;
+class JSFatInlineString;
+class JSObject;
+class JSScript;
+class JSString;
+
+namespace js {
+struct Class;
+class BaseShape;
+class LazyScript;
+class ObjectGroup;
+class Shape;
+namespace jit {
+class JitCode;
+} // namespace jit
+
+template <AllowGC allowGC>
+JSObject *
+NewGCObject(ExclusiveContext *cx, gc::AllocKind kind, size_t nDynamicSlots,
+            gc::InitialHeap heap, const Class *clasp);
+
+template <AllowGC allowGC>
+jit::JitCode *
+NewJitCode(ExclusiveContext *cx);
+
+ObjectGroup *
+NewObjectGroup(ExclusiveContext *cx);
+
+template <AllowGC allowGC>
+JSString *
+NewGCString(ExclusiveContext *cx);
+
+template <AllowGC allowGC>
+JSFatInlineString *
+NewGCFatInlineString(ExclusiveContext *cx);
+
+JSExternalString *
+NewGCExternalString(ExclusiveContext *cx);
+
+Shape *
+NewGCShape(ExclusiveContext *cx);
+
+Shape *
+NewGCAccessorShape(ExclusiveContext *cx);
+
+JSScript *
+NewGCScript(ExclusiveContext *cx);
+
+LazyScript *
+NewGCLazyScript(ExclusiveContext *cx);
+
+template <AllowGC allowGC>
+BaseShape *
+NewGCBaseShape(ExclusiveContext *cx);
+
+template <AllowGC allowGC>
+JS::Symbol *
+NewGCSymbol(ExclusiveContext *cx);
+
+namespace gc {
+
+template <AllowGC allowGC>
+NativeObject *
+AllocateObjectForCacheHit(JSContext *cx, AllocKind kind, InitialHeap heap, const Class *clasp);
+
+} // namespace gc
+} // namespace js
+
+#endif // gc_Allocator_h
--- a/js/src/gc/Nursery.cpp
+++ b/js/src/gc/Nursery.cpp
@@ -21,17 +21,17 @@
 #include "vm/ArrayObject.h"
 #include "vm/Debugger.h"
 #if defined(DEBUG)
 #include "vm/ScopeObject.h"
 #endif
 #include "vm/TypedArrayObject.h"
 #include "vm/TypeInference.h"
 
-#include "jsgcinlines.h"
+#include "jsobjinlines.h"
 
 #include "vm/NativeObject-inl.h"
 
 using namespace js;
 using namespace gc;
 
 using mozilla::ArrayLength;
 using mozilla::PodCopy;
--- a/js/src/gc/StoreBuffer.cpp
+++ b/js/src/gc/StoreBuffer.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "gc/StoreBuffer.h"
 
 #include "mozilla/Assertions.h"
 
 #include "gc/Statistics.h"
 #include "vm/ArgumentsObject.h"
+#include "vm/Runtime.h"
 
 #include "jsgcinlines.h"
 
 using namespace js;
 using namespace js::gc;
 using mozilla::ReentrancyGuard;
 
 /*** Edges ***/
--- a/js/src/jit/BaselineJIT.cpp
+++ b/js/src/jit/BaselineJIT.cpp
@@ -9,20 +9,20 @@
 #include "mozilla/MemoryReporting.h"
 
 #include "asmjs/AsmJSModule.h"
 #include "jit/BaselineCompiler.h"
 #include "jit/BaselineIC.h"
 #include "jit/CompileInfo.h"
 #include "jit/JitCommon.h"
 #include "jit/JitSpewer.h"
+#include "vm/Debugger.h"
 #include "vm/Interpreter.h"
 #include "vm/TraceLogging.h"
 
-#include "jsgcinlines.h"
 #include "jsobjinlines.h"
 #include "jsopcodeinlines.h"
 #include "jsscriptinlines.h"
 
 #include "jit/JitFrames-inl.h"
 #include "vm/Stack-inl.h"
 
 using namespace js;
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -41,17 +41,16 @@
 #include "jit/ScalarReplacement.h"
 #include "jit/Sink.h"
 #include "jit/StupidAllocator.h"
 #include "jit/ValueNumbering.h"
 #include "vm/HelperThreads.h"
 #include "vm/TraceLogging.h"
 
 #include "jscompartmentinlines.h"
-#include "jsgcinlines.h"
 #include "jsobjinlines.h"
 
 using namespace js;
 using namespace js::jit;
 
 using mozilla::ThreadLocal;
 
 // Assert that JitCode is gc::Cell aligned.
--- a/js/src/jit/MIRGenerator.h
+++ b/js/src/jit/MIRGenerator.h
@@ -15,16 +15,17 @@
 #include <stdarg.h>
 
 #include "jscntxt.h"
 #include "jscompartment.h"
 
 #include "jit/CompileInfo.h"
 #include "jit/JitAllocPolicy.h"
 #include "jit/JitCompartment.h"
+#include "jit/MIR.h"
 #ifdef JS_ION_PERF
 # include "jit/PerfSpewer.h"
 #endif
 #include "jit/RegisterSets.h"
 
 namespace js {
 namespace jit {
 
--- a/js/src/jit/MacroAssembler.cpp
+++ b/js/src/jit/MacroAssembler.cpp
@@ -15,17 +15,16 @@
 #include "jit/BaselineFrame.h"
 #include "jit/BaselineIC.h"
 #include "jit/BaselineJIT.h"
 #include "jit/Lowering.h"
 #include "jit/MIR.h"
 #include "js/Conversions.h"
 #include "vm/TraceLogging.h"
 
-#include "jsgcinlines.h"
 #include "jsobjinlines.h"
 #include "vm/Interpreter-inl.h"
 
 using namespace js;
 using namespace js::jit;
 
 using JS::GenericNaN;
 using JS::ToInt32;
--- a/js/src/jit/OptimizationTracking.cpp
+++ b/js/src/jit/OptimizationTracking.cpp
@@ -3,16 +3,18 @@
  * 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/. */
 
 #include "jit/OptimizationTracking.h"
 
 #include "mozilla/SizePrintfMacros.h"
 
+#include "jsprf.h"
+
 #include "ds/Sort.h"
 #include "jit/IonBuilder.h"
 #include "jit/JitcodeMap.h"
 #include "jit/JitSpewer.h"
 #include "js/TrackedOptimizationInfo.h"
 
 using namespace js;
 using namespace js::jit;
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -22,16 +22,17 @@
 #include "jsiter.h"
 #include "jsnum.h"
 #include "jsobj.h"
 #include "jstypes.h"
 #include "jsutil.h"
 
 #include "ds/Sort.h"
 #include "gc/Heap.h"
+#include "js/Class.h"
 #include "js/Conversions.h"
 #include "vm/ArgumentsObject.h"
 #include "vm/Interpreter.h"
 #include "vm/Shape.h"
 #include "vm/StringBuffer.h"
 #include "vm/TypedArrayCommon.h"
 
 #include "jsatominlines.h"
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -30,16 +30,17 @@
 #include "jsgcinlines.h"
 #include "jsobjinlines.h"
 
 using namespace js;
 using namespace js::gc;
 using namespace js::jit;
 
 using mozilla::DebugOnly;
+using mozilla::PodArrayZero;
 
 JSCompartment::JSCompartment(Zone *zone, const JS::CompartmentOptions &options = JS::CompartmentOptions())
   : options_(options),
     zone_(zone),
     runtime_(zone->runtimeFromMainThread()),
     principals(nullptr),
     isSystem(false),
     isSelfHosting(false),
--- a/js/src/jsgcinlines.h
+++ b/js/src/jsgcinlines.h
@@ -24,22 +24,16 @@ GetGCObjectKind(const Class *clasp)
     if (clasp == FunctionClassPtr)
         return JSFunction::FinalizeKind;
     uint32_t nslots = JSCLASS_RESERVED_SLOTS(clasp);
     if (clasp->flags & JSCLASS_HAS_PRIVATE)
         nslots++;
     return GetGCObjectKind(nslots);
 }
 
-inline bool
-ShouldNurseryAllocateObject(const Nursery &nursery, InitialHeap heap)
-{
-    return nursery.isEnabled() && heap != TenuredHeap;
-}
-
 inline JSGCTraceKind
 GetGCThingTraceKind(const void *thing)
 {
     MOZ_ASSERT(thing);
     const Cell *cell = static_cast<const Cell *>(thing);
     if (IsInsideNursery(cell))
         return JSTRACE_OBJECT;
     return MapAllocToTraceKind(cell->asTenured().getAllocKind());
@@ -373,330 +367,12 @@ class GCZoneGroupIter {
     }
 
     operator JS::Zone *() const { return get(); }
     JS::Zone *operator->() const { return get(); }
 };
 
 typedef CompartmentsIterT<GCZoneGroupIter> GCCompartmentGroupIter;
 
-/*
- * Attempt to allocate a new GC thing out of the nursery. If there is not enough
- * room in the nursery or there is an OOM, this method will return nullptr.
- */
-template <AllowGC allowGC>
-inline JSObject *
-TryNewNurseryObject(JSContext *cx, size_t thingSize, size_t nDynamicSlots, const js::Class *clasp)
-{
-    MOZ_ASSERT(!IsAtomsCompartment(cx->compartment()));
-    JSRuntime *rt = cx->runtime();
-    Nursery &nursery = rt->gc.nursery;
-    JSObject *obj = nursery.allocateObject(cx, thingSize, nDynamicSlots, clasp);
-    if (obj)
-        return obj;
-    if (allowGC && !rt->mainThread.suppressGC) {
-        cx->minorGC(JS::gcreason::OUT_OF_NURSERY);
-
-        /* Exceeding gcMaxBytes while tenuring can disable the Nursery. */
-        if (nursery.isEnabled()) {
-            JSObject *obj = nursery.allocateObject(cx, thingSize, nDynamicSlots, clasp);
-            MOZ_ASSERT(obj);
-            return obj;
-        }
-    }
-    return nullptr;
-}
-
-static inline bool
-PossiblyFail()
-{
-    JS_OOM_POSSIBLY_FAIL_BOOL();
-    return true;
-}
-
-static inline bool
-GCIfNeeded(ExclusiveContext *cx)
-{
-    if (cx->isJSContext()) {
-        JSContext *ncx = cx->asJSContext();
-        JSRuntime *rt = ncx->runtime();
-
-#ifdef JS_GC_ZEAL
-        if (rt->gc.needZealousGC())
-            rt->gc.runDebugGC();
-#endif
-
-        // Invoking the interrupt callback can fail and we can't usefully
-        // handle that here. Just check in case we need to collect instead.
-        if (rt->hasPendingInterrupt())
-            rt->gc.gcIfRequested(ncx);
-
-        // If we have grown past our GC heap threshold while in the middle of
-        // an incremental GC, we're growing faster than we're GCing, so stop
-        // the world and do a full, non-incremental GC right now, if possible.
-        if (rt->gc.isIncrementalGCInProgress() &&
-            cx->zone()->usage.gcBytes() > cx->zone()->threshold.gcTriggerBytes())
-        {
-            PrepareZoneForGC(cx->zone());
-            AutoKeepAtoms keepAtoms(cx->perThreadData);
-            rt->gc.gc(GC_NORMAL, JS::gcreason::INCREMENTAL_TOO_SLOW);
-        }
-    }
-
-    return true;
-}
-
-template <AllowGC allowGC>
-static inline bool
-CheckAllocatorState(ExclusiveContext *cx, AllocKind kind)
-{
-    if (allowGC) {
-        if (!GCIfNeeded(cx))
-            return false;
-    }
-
-    if (!cx->isJSContext())
-        return true;
-
-    JSContext *ncx = cx->asJSContext();
-    JSRuntime *rt = ncx->runtime();
-#if defined(JS_GC_ZEAL) || defined(DEBUG)
-    MOZ_ASSERT_IF(rt->isAtomsCompartment(ncx->compartment()),
-                  kind == FINALIZE_STRING ||
-                  kind == FINALIZE_FAT_INLINE_STRING ||
-                  kind == FINALIZE_SYMBOL ||
-                  kind == FINALIZE_JITCODE);
-    MOZ_ASSERT(!rt->isHeapBusy());
-    MOZ_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()) {
-        ReportOutOfMemory(ncx);
-        return false;
-    }
-
-    return true;
-}
-
-template <typename T>
-static inline void
-CheckIncrementalZoneState(ExclusiveContext *cx, T *t)
-{
-#ifdef DEBUG
-    if (!cx->isJSContext())
-        return;
-
-    Zone *zone = cx->asJSContext()->zone();
-    MOZ_ASSERT_IF(t && zone->wasGCStarted() && (zone->isGCMarking() || zone->isGCSweeping()),
-                  t->asTenured().arenaHeader()->allocatedDuringIncremental);
-#endif
-}
-
-/*
- * Allocate a new GC thing. After a successful allocation the caller must
- * fully initialize the thing before calling any function that can potentially
- * trigger GC. This will ensure that GC tracing never sees junk values stored
- * in the partially initialized thing.
- */
-
-template <AllowGC allowGC>
-inline JSObject *
-AllocateObject(ExclusiveContext *cx, AllocKind kind, size_t nDynamicSlots, InitialHeap heap,
-               const js::Class *clasp)
-{
-    size_t thingSize = Arena::thingSize(kind);
-
-    MOZ_ASSERT(thingSize == Arena::thingSize(kind));
-    MOZ_ASSERT(thingSize >= sizeof(JSObject_Slots0));
-    static_assert(sizeof(JSObject_Slots0) >= CellSize,
-                  "All allocations must be at least the allocator-imposed minimum size.");
-
-    if (!CheckAllocatorState<allowGC>(cx, kind))
-        return nullptr;
-
-    if (cx->isJSContext() &&
-        ShouldNurseryAllocateObject(cx->asJSContext()->nursery(), heap))
-    {
-        JSObject *obj = TryNewNurseryObject<allowGC>(cx->asJSContext(), thingSize, nDynamicSlots,
-                                                     clasp);
-        if (obj)
-            return obj;
-    }
-
-    HeapSlot *slots = nullptr;
-    if (nDynamicSlots) {
-        slots = cx->zone()->pod_malloc<HeapSlot>(nDynamicSlots);
-        if (MOZ_UNLIKELY(!slots))
-            return nullptr;
-        js::Debug_SetSlotRangeToCrashOnTouch(slots, nDynamicSlots);
-    }
-
-    JSObject *obj = reinterpret_cast<JSObject *>(cx->arenas()->allocateFromFreeList(kind, thingSize));
-    if (!obj)
-        obj = reinterpret_cast<JSObject *>(GCRuntime::refillFreeListFromAnyThread<allowGC>(cx, kind));
-
-    if (obj)
-        obj->setInitialSlotsMaybeNonNative(slots);
-    else
-        js_free(slots);
-
-    CheckIncrementalZoneState(cx, obj);
-    js::gc::TraceTenuredAlloc(obj, kind);
-    return obj;
-}
-
-template <typename T, AllowGC allowGC>
-inline T *
-AllocateNonObject(ExclusiveContext *cx)
-{
-    static_assert(sizeof(T) >= CellSize,
-                  "All allocations must be at least the allocator-imposed minimum size.");
-
-    AllocKind kind = MapTypeToFinalizeKind<T>::kind;
-    size_t thingSize = sizeof(T);
-
-    MOZ_ASSERT(thingSize == Arena::thingSize(kind));
-    if (!CheckAllocatorState<allowGC>(cx, kind))
-        return nullptr;
-
-    T *t = static_cast<T *>(cx->arenas()->allocateFromFreeList(kind, thingSize));
-    if (!t)
-        t = static_cast<T *>(GCRuntime::refillFreeListFromAnyThread<allowGC>(cx, kind));
-
-    CheckIncrementalZoneState(cx, t);
-    js::gc::TraceTenuredAlloc(t, kind);
-    return t;
-}
-
-/*
- * When allocating for initialization from a cached object copy, we will
- * potentially destroy the cache entry we want to copy if we allow GC. On the
- * other hand, since these allocations are extremely common, we don't want to
- * delay GC from these allocation sites. Instead we allow the GC, but still
- * fail the allocation, forcing the non-cached path.
- */
-template <AllowGC allowGC>
-inline NativeObject *
-AllocateObjectForCacheHit(JSContext *cx, AllocKind kind, InitialHeap heap, const js::Class *clasp)
-{
-    MOZ_ASSERT(clasp->isNative());
-
-    if (ShouldNurseryAllocateObject(cx->nursery(), heap)) {
-        size_t thingSize = Arena::thingSize(kind);
-
-        MOZ_ASSERT(thingSize == Arena::thingSize(kind));
-        if (!CheckAllocatorState<NoGC>(cx, kind))
-            return nullptr;
-
-        JSObject *obj = TryNewNurseryObject<NoGC>(cx, thingSize, 0, clasp);
-        if (!obj && allowGC) {
-            cx->minorGC(JS::gcreason::OUT_OF_NURSERY);
-            return nullptr;
-        }
-        return reinterpret_cast<NativeObject *>(obj);
-    }
-
-    JSObject *obj = AllocateObject<NoGC>(cx, kind, 0, heap, clasp);
-    if (!obj && allowGC) {
-        cx->runtime()->gc.maybeGC(cx->zone());
-        return nullptr;
-    }
-
-    return reinterpret_cast<NativeObject *>(obj);
-}
-
-inline bool
-IsInsideGGCNursery(const js::gc::Cell *cell)
-{
-    if (!cell)
-        return false;
-    uintptr_t addr = uintptr_t(cell);
-    addr &= ~js::gc::ChunkMask;
-    addr |= js::gc::ChunkLocationOffset;
-    uint32_t location = *reinterpret_cast<uint32_t *>(addr);
-    MOZ_ASSERT(location != 0);
-    return location & js::gc::ChunkLocationBitNursery;
-}
-
 } /* namespace gc */
-
-template <js::AllowGC allowGC>
-inline JSObject *
-NewGCObject(js::ExclusiveContext *cx, js::gc::AllocKind kind, size_t nDynamicSlots,
-            js::gc::InitialHeap heap, const js::Class *clasp)
-{
-    MOZ_ASSERT(kind >= js::gc::FINALIZE_OBJECT0 && kind <= js::gc::FINALIZE_OBJECT_LAST);
-    return js::gc::AllocateObject<allowGC>(cx, kind, nDynamicSlots, heap, clasp);
-}
-
-template <js::AllowGC allowGC>
-inline jit::JitCode *
-NewJitCode(js::ExclusiveContext *cx)
-{
-    return gc::AllocateNonObject<jit::JitCode, allowGC>(cx);
-}
-
-inline
-ObjectGroup *
-NewObjectGroup(js::ExclusiveContext *cx)
-{
-    return gc::AllocateNonObject<ObjectGroup, js::CanGC>(cx);
-}
-
-template <js::AllowGC allowGC>
-inline JSString *
-NewGCString(js::ExclusiveContext *cx)
-{
-    return js::gc::AllocateNonObject<JSString, allowGC>(cx);
-}
-
-template <js::AllowGC allowGC>
-inline JSFatInlineString *
-NewGCFatInlineString(js::ExclusiveContext *cx)
-{
-    return js::gc::AllocateNonObject<JSFatInlineString, allowGC>(cx);
-}
-
-inline JSExternalString *
-NewGCExternalString(js::ExclusiveContext *cx)
-{
-    return js::gc::AllocateNonObject<JSExternalString, js::CanGC>(cx);
-}
-
-inline Shape *
-NewGCShape(ExclusiveContext *cx)
-{
-    return gc::AllocateNonObject<Shape, CanGC>(cx);
-}
-
-inline Shape *
-NewGCAccessorShape(ExclusiveContext *cx)
-{
-    return gc::AllocateNonObject<AccessorShape, CanGC>(cx);
-}
-
-inline JSScript *
-NewGCScript(ExclusiveContext *cx)
-{
-    return gc::AllocateNonObject<JSScript, CanGC>(cx);
-}
-
-inline LazyScript *
-NewGCLazyScript(ExclusiveContext *cx)
-{
-    return gc::AllocateNonObject<LazyScript, CanGC>(cx);
-}
-
-template <AllowGC allowGC>
-inline BaseShape *
-NewGCBaseShape(ExclusiveContext *cx)
-{
-    return gc::AllocateNonObject<BaseShape, allowGC>(cx);
-}
-
 } /* namespace js */
 
 #endif /* jsgcinlines_h */
--- a/js/src/jsmath.cpp
+++ b/js/src/jsmath.cpp
@@ -26,16 +26,18 @@
 #include "jsapi.h"
 #include "jsatom.h"
 #include "jscntxt.h"
 #include "jscompartment.h"
 #include "jslibmath.h"
 #include "jstypes.h"
 #include "prmjtime.h"
 
+#include "js/Class.h"
+
 #include "jsobjinlines.h"
 
 using namespace js;
 
 using mozilla::Abs;
 using mozilla::NumberEqualsInt32;
 using mozilla::NumberIsInt32;
 using mozilla::ExponentComponent;
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -6,16 +6,17 @@
 
 #ifndef jsobjinlines_h
 #define jsobjinlines_h
 
 #include "jsobj.h"
 
 #include "builtin/MapObject.h"
 #include "builtin/TypedObject.h"
+#include "gc/Allocator.h"
 #include "vm/ArrayObject.h"
 #include "vm/DateObject.h"
 #include "vm/NumberObject.h"
 #include "vm/Probes.h"
 #include "vm/ScopeObject.h"
 #include "vm/StringObject.h"
 #include "vm/TypedArrayCommon.h"
 
--- a/js/src/jspropertytree.cpp
+++ b/js/src/jspropertytree.cpp
@@ -9,18 +9,16 @@
 #include "mozilla/DebugOnly.h"
 
 #include "jscntxt.h"
 #include "jsgc.h"
 #include "jstypes.h"
 
 #include "vm/Shape.h"
 
-#include "jsgcinlines.h"
-
 #include "vm/Shape-inl.h"
 
 using namespace js;
 using namespace js::gc;
 
 using mozilla::DebugOnly;
 
 inline HashNumber
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -115,16 +115,17 @@ UNIFIED_SOURCES += [
     'ds/LifoAlloc.cpp',
     'frontend/BytecodeCompiler.cpp',
     'frontend/BytecodeEmitter.cpp',
     'frontend/FoldConstants.cpp',
     'frontend/NameFunctions.cpp',
     'frontend/ParseMaps.cpp',
     'frontend/ParseNode.cpp',
     'frontend/TokenStream.cpp',
+    'gc/Allocator.cpp',
     'gc/Barrier.cpp',
     'gc/GCTrace.cpp',
     'gc/Iteration.cpp',
     'gc/Marking.cpp',
     'gc/Memory.cpp',
     'gc/Nursery.cpp',
     'gc/RootMarking.cpp',
     'gc/Statistics.cpp',
--- a/js/src/vm/ArrayObject-inl.h
+++ b/js/src/vm/ArrayObject-inl.h
@@ -4,16 +4,17 @@
  * 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/. */
 
 #ifndef vm_ArrayObject_inl_h
 #define vm_ArrayObject_inl_h
 
 #include "vm/ArrayObject.h"
 
+#include "gc/GCTrace.h"
 #include "vm/String.h"
 
 #include "vm/TypeInference-inl.h"
 
 namespace js {
 
 inline void
 ArrayObject::setLength(ExclusiveContext *cx, uint32_t length)
--- a/js/src/vm/ObjectGroup.cpp
+++ b/js/src/vm/ObjectGroup.cpp
@@ -9,17 +9,16 @@
 #include "jshashutil.h"
 #include "jsobj.h"
 
 #include "gc/StoreBuffer.h"
 #include "gc/Zone.h"
 #include "vm/ArrayObject.h"
 #include "vm/UnboxedObject.h"
 
-#include "jsgcinlines.h"
 #include "jsobjinlines.h"
 
 using namespace js;
 
 using mozilla::PodZero;
 
 /////////////////////////////////////////////////////////////////////
 // ObjectGroup
--- a/js/src/vm/ProxyObject.cpp
+++ b/js/src/vm/ProxyObject.cpp
@@ -2,17 +2,16 @@
  * 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/. */
 
 #include "vm/ProxyObject.h"
 
 #include "jscompartment.h"
-#include "jsgcinlines.h"
 #include "jsobjinlines.h"
 
 using namespace js;
 
 /* static */ ProxyObject *
 ProxyObject::New(JSContext *cx, const BaseProxyHandler *handler, HandleValue priv, TaggedProto proto_,
                  const ProxyOptions &options)
 {
--- a/js/src/vm/Runtime-inl.h
+++ b/js/src/vm/Runtime-inl.h
@@ -6,45 +6,45 @@
 
 #ifndef vm_Runtime_inl_h
 #define vm_Runtime_inl_h
 
 #include "vm/Runtime.h"
 
 #include "jscompartment.h"
 
+#include "gc/Allocator.h"
+#include "gc/GCTrace.h"
 #include "vm/Probes.h"
 
-#include "jsgcinlines.h"
-
 namespace js {
 
 inline bool
 NewObjectCache::lookupProto(const Class *clasp, JSObject *proto, gc::AllocKind kind, EntryIndex *pentry)
 {
     MOZ_ASSERT(!proto->is<GlobalObject>());
     return lookup(clasp, proto, kind, pentry);
 }
 
 inline bool
-NewObjectCache::lookupGlobal(const Class *clasp, js::GlobalObject *global, gc::AllocKind kind, EntryIndex *pentry)
+NewObjectCache::lookupGlobal(const Class *clasp, GlobalObject *global, gc::AllocKind kind, EntryIndex *pentry)
 {
     return lookup(clasp, global, kind, pentry);
 }
 
 inline void
-NewObjectCache::fillGlobal(EntryIndex entry, const Class *clasp, js::GlobalObject *global,
+NewObjectCache::fillGlobal(EntryIndex entry, const Class *clasp, GlobalObject *global,
                            gc::AllocKind kind, NativeObject *obj)
 {
     //MOZ_ASSERT(global == obj->getGlobal());
     return fill(entry, clasp, global, kind, obj);
 }
 
 inline NativeObject *
-NewObjectCache::newObjectFromHit(JSContext *cx, EntryIndex entryIndex, js::gc::InitialHeap heap)
+NewObjectCache::newObjectFromHit(JSContext *cx, EntryIndex entryIndex, gc::InitialHeap heap)
 {
     // The new object cache does not account for metadata attached via callbacks.
     MOZ_ASSERT(!cx->compartment()->hasObjectMetadataCallback());
 
     MOZ_ASSERT(unsigned(entryIndex) < mozilla::ArrayLength(entries));
     Entry *entry = &entries[entryIndex];
 
     NativeObject *templateObj = reinterpret_cast<NativeObject *>(&entry->templateObject);
@@ -54,33 +54,33 @@ NewObjectCache::newObjectFromHit(JSConte
     ObjectGroup *group = templateObj->group_;
 
     if (group->shouldPreTenure())
         heap = gc::TenuredHeap;
 
     if (cx->runtime()->gc.upcomingZealousGC())
         return nullptr;
 
-    NativeObject *obj = js::gc::AllocateObjectForCacheHit<NoGC>(cx, entry->kind, heap, group->clasp());
+    NativeObject *obj = gc::AllocateObjectForCacheHit<NoGC>(cx, entry->kind, heap, group->clasp());
     if (obj) {
         copyCachedToObject(obj, templateObj, entry->kind);
         probes::CreateObject(cx, obj);
-        js::gc::TraceCreateObject(obj);
+        gc::TraceCreateObject(obj);
         return obj;
     }
 
     // Trigger an identical allocation to the one that notified us of OOM so
     // that we trigger the right kind of GC automatically; note that even
     // though we are passing CanGC to AllocateObjectForCacheHit it will never
     // allow GC during the allocation itself. The reason is that this would
     // clobber our cache and make us unable to initialize from it. Instead we
     // do an independent non-allocation GC, then return nullptr so that we'll
     // take the slow allocation path. The callee is responsible for ensuring
     // that the index it uses to fill the cache is still correct after this GC.
     mozilla::DebugOnly<JSObject *> obj2 =
-        js::gc::AllocateObjectForCacheHit<CanGC>(cx, entry->kind, heap, group->clasp());
+        gc::AllocateObjectForCacheHit<CanGC>(cx, entry->kind, heap, group->clasp());
     MOZ_ASSERT(!obj2);
     return nullptr;
 }
 
 }  /* namespace js */
 
 #endif /* vm_Runtime_inl_h */
--- a/js/src/vm/Shape-inl.h
+++ b/js/src/vm/Shape-inl.h
@@ -8,23 +8,23 @@
 #define vm_Shape_inl_h
 
 #include "vm/Shape.h"
 
 #include "mozilla/TypeTraits.h"
 
 #include "jsobj.h"
 
+#include "gc/Allocator.h"
 #include "vm/Interpreter.h"
 #include "vm/ScopeObject.h"
 #include "vm/TypedArrayCommon.h"
 
 #include "jsatominlines.h"
 #include "jscntxtinlines.h"
-#include "jsgcinlines.h"
 
 namespace js {
 
 inline
 StackBaseShape::StackBaseShape(ExclusiveContext *cx, const Class *clasp,
                                JSObject *parent, JSObject *metadata, uint32_t objectFlags)
   : flags(objectFlags),
     clasp(clasp),
--- a/js/src/vm/String-inl.h
+++ b/js/src/vm/String-inl.h
@@ -9,20 +9,19 @@
 
 #include "vm/String.h"
 
 #include "mozilla/PodOperations.h"
 #include "mozilla/Range.h"
 
 #include "jscntxt.h"
 
+#include "gc/Allocator.h"
 #include "gc/Marking.h"
 
-#include "jsgcinlines.h"
-
 namespace js {
 
 // Allocate a thin inline string if possible, and a fat inline string if not.
 template <AllowGC allowGC, typename CharT>
 static MOZ_ALWAYS_INLINE JSInlineString *
 AllocateInlineString(ExclusiveContext *cx, size_t len, CharT **chars)
 {
     MOZ_ASSERT(JSInlineString::lengthFits<CharT>(len));
--- a/js/src/vm/Symbol.cpp
+++ b/js/src/vm/Symbol.cpp
@@ -5,33 +5,33 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "vm/Symbol.h"
 
 #include "jscntxt.h"
 #include "jscompartment.h"
 
 #include "builtin/SymbolObject.h"
+#include "gc/Allocator.h"
 #include "gc/Rooting.h"
 #include "vm/StringBuffer.h"
 
 #include "jscompartmentinlines.h"
-#include "jsgcinlines.h"
 
 using JS::Symbol;
 using namespace js;
 
 Symbol *
 Symbol::newInternal(ExclusiveContext *cx, JS::SymbolCode code, JSAtom *description)
 {
     MOZ_ASSERT(cx->compartment() == cx->atomsCompartment());
     MOZ_ASSERT(cx->atomsCompartment()->runtimeFromAnyThread()->currentThreadHasExclusiveAccess());
 
     // Following js::AtomizeString, we grudgingly forgo last-ditch GC here.
-    Symbol *p = gc::AllocateNonObject<Symbol, NoGC>(cx);
+    Symbol *p = NewGCSymbol<NoGC>(cx);
     if (!p) {
         ReportOutOfMemory(cx);
         return nullptr;
     }
     return new (p) Symbol(code, description);
 }
 
 Symbol *
--- a/js/src/vm/TypeInference.cpp
+++ b/js/src/vm/TypeInference.cpp
@@ -29,17 +29,16 @@
 #include "jit/JitCompartment.h"
 #include "js/MemoryMetrics.h"
 #include "vm/HelperThreads.h"
 #include "vm/Opcodes.h"
 #include "vm/Shape.h"
 #include "vm/UnboxedObject.h"
 
 #include "jsatominlines.h"
-#include "jsgcinlines.h"
 #include "jsscriptinlines.h"
 
 #include "vm/NativeObject-inl.h"
 
 using namespace js;
 using namespace js::gc;
 
 using mozilla::DebugOnly;