Bug 1234862 - Part 5: Rename DefaultGCPolicy to GCPolicy; r=sfink
authorTerrence Cole <terrence@mozilla.com>
Tue, 26 Jan 2016 12:53:35 -0800
changeset 281975 b001a1c7c38242c22673649b62de197c07bf67e7
parent 281974 d47be60aad9990ca2e55d0588110e2ae72863d55
child 281976 9eb479c864986d2a48b1090a5f2409989b96de20
push id29950
push usercbook@mozilla.com
push dateThu, 28 Jan 2016 11:14:03 +0000
treeherderautoland@2b73b0a4d52b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink
bugs1234862
milestone47.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 1234862 - Part 5: Rename DefaultGCPolicy to GCPolicy; r=sfink
dom/plugins/base/nsJSNPRuntime.cpp
js/public/GCHashTable.h
js/public/GCPolicyAPI.h
js/public/GCVector.h
js/public/Id.h
js/public/RootingAPI.h
js/public/TracingAPI.h
js/public/Value.h
js/src/asmjs/AsmJS.cpp
js/src/builtin/ModuleObject.cpp
js/src/ctypes/CTypes.cpp
js/src/ds/TraceableFifo.h
js/src/gc/Barrier.cpp
js/src/gc/Marking.cpp
js/src/gc/Marking.h
js/src/gc/Policy.h
js/src/jit/BaselineIC.cpp
js/src/jit/SharedIC.cpp
js/src/jsapi-tests/testGCExactRooting.cpp
js/src/jsapi.cpp
js/src/jscompartment.cpp
js/src/jsfun.cpp
js/src/jsgc.h
js/src/jsobj.cpp
js/src/moz.build
js/src/vm/Debugger.h
js/src/vm/ObjectGroup.cpp
js/src/vm/SavedStacks.cpp
js/src/vm/ScopeObject.cpp
js/src/vm/SelfHosting.cpp
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -56,17 +56,17 @@ struct JSObjWrapperHasher
   static bool match(const Key& k, const Lookup &l) {
       return js::MovableCellHasher<JS::Heap<JSObject*>>::match(k.mJSObj, l.mJSObj) &&
              k.mNpp == l.mNpp;
   }
 };
 
 namespace js {
 template <>
-struct DefaultGCPolicy<nsJSObjWrapper*> {
+struct GCPolicy<nsJSObjWrapper*> {
     static void trace(JSTracer* trc, nsJSObjWrapper** wrapper, const char* name) {
         MOZ_ASSERT(wrapper);
         MOZ_ASSERT(*wrapper);
         (*wrapper)->trace(trc);
     }
 };
 } // namespace js
 
--- a/js/public/GCHashTable.h
+++ b/js/public/GCHashTable.h
@@ -2,45 +2,46 @@
  * 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 GCHashTable_h
 #define GCHashTable_h
 
+#include "js/GCPolicyAPI.h"
 #include "js/HashTable.h"
 #include "js/RootingAPI.h"
 #include "js/TracingAPI.h"
 
 namespace js {
 
 // Define a reasonable default GC policy for GC-aware Maps.
 template <typename Key, typename Value>
 struct DefaultMapSweepPolicy {
     static bool needsSweep(Key* key, Value* value) {
-        return DefaultGCPolicy<Key>::needsSweep(key) || DefaultGCPolicy<Value>::needsSweep(value);
+        return GCPolicy<Key>::needsSweep(key) || GCPolicy<Value>::needsSweep(value);
     }
 };
 
 // A GCHashMap is a GC-aware HashMap, meaning that it has additional trace and
 // sweep methods that know how to visit all keys and values in the table.
 // HashMaps that contain GC pointers will generally want to use this GCHashMap
 // specialization in lieu of HashMap, either because those pointers must be
 // traced to be kept alive -- in which case, KeyPolicy and/or ValuePolicy
 // should do the appropriate tracing -- or because those pointers are weak and
 // must be swept during a GC -- in which case needsSweep should be set
 // appropriately.
 //
 // Most types of GC pointers as keys and values can be traced with no extra
-// infrastructure. For structs, the DefaultGCPolicy<T> will call a trace()
-// method on the struct. For other structs and non-gc-pointer members, ensure
-// that there is a specialization of DefaultGCPolicy<T> with an appropriate
-// trace() static method available to handle the custom type. Generic helpers
-// can be found in js/public/TracingAPI.h.
+// infrastructure. For structs, the GCPolicy<T> will call a trace() method on
+// the struct. For other structs and non-gc-pointer members, ensure that there
+// is a specialization of GCPolicy<T> with an appropriate trace() static method
+// available to handle the custom type. Generic helpers can be found in
+// js/public/TracingAPI.h.
 //
 // Note that this HashMap only knows *how* to trace and sweep (and the tracing
 // can handle keys that move), but it does not itself cause tracing or sweeping
 // to be invoked. For tracing, it must be used with Rooted or PersistentRooted,
 // or barriered and traced manually. For sweeping, currently it requires an
 // explicit call to <map>.sweep().
 //
 template <typename Key,
@@ -56,18 +57,18 @@ class GCHashMap : public HashMap<Key, Va
   public:
     explicit GCHashMap(AllocPolicy a = AllocPolicy()) : Base(a)  {}
 
     static void trace(GCHashMap* map, JSTracer* trc) { map->trace(trc); }
     void trace(JSTracer* trc) {
         if (!this->initialized())
             return;
         for (typename Base::Enum e(*this); !e.empty(); e.popFront()) {
-            DefaultGCPolicy<Value>::trace(trc, &e.front().value(), "hashmap value");
-            DefaultGCPolicy<Key>::trace(trc, &e.front().mutableKey(), "hashmap key");
+            GCPolicy<Value>::trace(trc, &e.front().value(), "hashmap value");
+            GCPolicy<Key>::trace(trc, &e.front().mutableKey(), "hashmap key");
         }
     }
 
     void sweep() {
         if (!this->initialized())
             return;
 
         for (typename Base::Enum e(*this); !e.empty(); e.popFront()) {
@@ -210,18 +211,18 @@ class HandleBase<GCHashMap<A,B,C,D,E>>
 {};
 
 // A GCHashSet is a HashSet with an additional trace method that knows
 // be traced to be kept alive will generally want to use this GCHashSet
 // specializeation in lieu of HashSet.
 //
 // Most types of GC pointers can be traced with no extra infrastructure. For
 // structs and non-gc-pointer members, ensure that there is a specialization of
-// DefaultGCPolicy<T> with an appropriate trace method available to handle the
-// custom type. Generic helpers can be found in js/public/TracingAPI.h.
+// GCPolicy<T> with an appropriate trace method available to handle the custom
+// type. Generic helpers can be found in js/public/TracingAPI.h.
 //
 // Note that although this HashSet's trace will deal correctly with moved
 // elements, it does not itself know when to barrier or trace elements. To
 // function properly it must either be used with Rooted or barriered and traced
 // manually.
 template <typename T,
           typename HashPolicy = DefaultHasher<T>,
           typename AllocPolicy = TempAllocPolicy>
@@ -233,24 +234,24 @@ class GCHashSet : public HashSet<T, Hash
   public:
     explicit GCHashSet(AllocPolicy a = AllocPolicy()) : Base(a)  {}
 
     static void trace(GCHashSet* set, JSTracer* trc) { set->trace(trc); }
     void trace(JSTracer* trc) {
         if (!this->initialized())
             return;
         for (typename Base::Enum e(*this); !e.empty(); e.popFront())
-            DefaultGCPolicy<T>::trace(trc, &e.mutableFront(), "hashset element");
+            GCPolicy<T>::trace(trc, &e.mutableFront(), "hashset element");
     }
 
     void sweep() {
         if (!this->initialized())
             return;
         for (typename Base::Enum e(*this); !e.empty(); e.popFront()) {
-            if (DefaultGCPolicy<T>::needsSweep(&e.mutableFront()))
+            if (GCPolicy<T>::needsSweep(&e.mutableFront()))
                 e.removeFront();
         }
     }
 
     // GCHashSet is movable
     GCHashSet(GCHashSet&& rhs) : Base(mozilla::Forward<GCHashSet>(rhs)) {}
     void operator=(GCHashSet&& rhs) {
         MOZ_ASSERT(this != &rhs, "self-move assignment is prohibited");
new file mode 100644
--- /dev/null
+++ b/js/public/GCPolicyAPI.h
@@ -0,0 +1,114 @@
+/* -*- 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/. */
+
+// GC Policy Mechanism
+
+// A GCPolicy controls how the GC interacts with both direct pointers to GC
+// things (e.g. JSObject* or JSString*), tagged and/or optional pointers to GC
+// things (e.g.  Value or jsid), and C++ aggregate types (e.g.
+// JSPropertyDescriptor or GCHashMap).
+//
+// The GCPolicy provides at a minimum:
+//
+//   static T initial()
+//       - Tells the GC how to construct an empty T.
+//
+//   static void trace(JSTracer, T* tp, const char* name)
+//       - Tells the GC how to traverse the edge itself or its children in the
+//         case of an aggregate.
+//
+//   static bool needsSweep(T* tp)
+//       - Tells the GC how to tell if an edge is about to be finalized. For
+//         aggregates, the meaning is less clear. When the aggregate is used in
+//         a weak container, the return value will determine the semantcs of
+//         that container's weakness. This is the primary reason that GC-
+//         supporting containers can override the policy on a per-container
+//         basis.
+
+#ifndef GCPolicyAPI_h
+#define GCPolicyAPI_h
+
+#include "js/TraceKind.h"
+#include "js/TracingAPI.h"
+
+class JSAtom;
+class JSFunction;
+class JSObject;
+class JSScript;
+class JSString;
+namespace JS {
+class Symbol;
+}
+
+namespace js {
+
+// Defines a policy for aggregate types with non-GC, i.e. C storage. This
+// policy dispatches to the underlying aggregate for GC interactions.
+template <typename T>
+struct StructGCPolicy
+{
+    static T initial() {
+        return T();
+    }
+
+    static void trace(JSTracer* trc, T* tp, const char* name) {
+        tp->trace(trc);
+    }
+
+    static bool needsSweep(T* tp) {
+        return tp->needsSweep();
+    }
+};
+
+// The default GC policy attempts to defer to methods on the underlying type.
+// Most C++ structures that contain a default constructor, a trace function and
+// a sweep function will work out of the box with Rooted, GCHash{Set,Map}, and
+// GCVector.
+template <typename T> struct GCPolicy : public StructGCPolicy<T> {};
+
+// This policy ignores any GC interaction, e.g. for non-GC types.
+template <typename T>
+struct IgnoreGCPolicy {
+    static T initial() { return T(); }
+    static void trace(JSTracer* trc, T* t, const char* name) {}
+    static bool needsSweep(T* v) { return false; }
+};
+template <> struct GCPolicy<uint32_t> : public IgnoreGCPolicy<uint32_t> {};
+template <> struct GCPolicy<uint64_t> : public IgnoreGCPolicy<uint64_t> {};
+
+template <typename T>
+struct GCPointerPolicy
+{
+    static T initial() { return nullptr; }
+    static void trace(JSTracer* trc, T* vp, const char* name) {
+        if (*vp)
+            js::UnsafeTraceManuallyBarrieredEdge(trc, vp, name);
+    }
+    static void needsSweep(T* vp) {
+        return js::gc::EdgeNeedsSweep(vp);
+    }
+};
+template <> struct GCPolicy<JS::Symbol*> : public GCPointerPolicy<JS::Symbol*> {};
+template <> struct GCPolicy<JSAtom*> : public GCPointerPolicy<JSAtom*> {};
+template <> struct GCPolicy<JSFunction*> : public GCPointerPolicy<JSFunction*> {};
+template <> struct GCPolicy<JSObject*> : public GCPointerPolicy<JSObject*> {};
+template <> struct GCPolicy<JSScript*> : public GCPointerPolicy<JSScript*> {};
+template <> struct GCPolicy<JSString*> : public GCPointerPolicy<JSString*> {};
+
+template <typename T>
+struct GCPolicy<JS::Heap<T>>
+{
+    static void trace(JSTracer* trc, JS::Heap<T>* thingp, const char* name) {
+        JS::TraceEdge(trc, thingp, name);
+    }
+    static bool needsSweep(JS::Heap<T>* thingp) {
+        return gc::EdgeNeedsSweep(thingp);
+    }
+};
+
+} // namespace js
+
+#endif // GCPolicyAPI_h
--- a/js/public/GCVector.h
+++ b/js/public/GCVector.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 js_GCVector_h
 #define js_GCVector_h
 
 #include "mozilla/Vector.h"
 
+#include "js/GCPolicyAPI.h"
 #include "js/RootingAPI.h"
 #include "js/TracingAPI.h"
 #include "js/Vector.h"
 
 namespace js {
 
 // A GCVector is a Vector with an additional trace method that knows how
 // to visit all of the items stored in the Vector. For vectors that contain GC
@@ -116,17 +117,17 @@ class GCVector : public JS::Traceable
     size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
         return vector.sizeOfIncludingThis(mallocSizeOf);
     }
 
     static void trace(GCVector* vec, JSTracer* trc) { vec->trace(trc); }
 
     void trace(JSTracer* trc) {
         for (auto& elem : vector)
-            DefaultGCPolicy<T>::trace(trc, &elem, "vector element");
+            GCPolicy<T>::trace(trc, &elem, "vector element");
     }
 };
 
 template <typename Outer, typename T, size_t Capacity, typename AllocPolicy>
 class GCVectorOperations
 {
     using Vec = GCVector<T, Capacity, AllocPolicy>;
     const Vec& vec() const { return static_cast<const Outer*>(this)->get(); }
--- a/js/public/Id.h
+++ b/js/public/Id.h
@@ -167,16 +167,19 @@ extern JS_PUBLIC_DATA(const JS::HandleId
 extern JS_PUBLIC_DATA(const JS::HandleId) JSID_EMPTYHANDLE;
 
 namespace js {
 
 template <>
 struct GCPolicy<jsid>
 {
     static jsid initial() { return JSID_VOID; }
+    static void trace(JSTracer* trc, jsid* idp, const char* name) {
+        js::UnsafeTraceManuallyBarrieredEdge(trc, idp, name);
+    }
 };
 
 template <>
 struct BarrierMethods<jsid>
 {
     static void postBarrier(jsid* idp, jsid prev, jsid next) {}
 };
 
--- a/js/public/RootingAPI.h
+++ b/js/public/RootingAPI.h
@@ -12,16 +12,17 @@
 #include "mozilla/GuardObjects.h"
 #include "mozilla/LinkedList.h"
 #include "mozilla/Move.h"
 #include "mozilla/TypeTraits.h"
 
 #include "jspubtd.h"
 
 #include "js/GCAPI.h"
+#include "js/GCPolicyAPI.h"
 #include "js/HeapAPI.h"
 #include "js/TypeDecls.h"
 #include "js/Utility.h"
 
 /*
  * Moving GC Stack Rooting
  *
  * A moving GC may change the physical location of GC allocated things, even
@@ -104,21 +105,16 @@
 
 namespace js {
 
 template <typename T>
 struct BarrierMethods {
 };
 
 template <typename T>
-struct GCPolicy {
-    static T initial() { return T(); }
-};
-
-template <typename T>
 class RootedBase {};
 
 template <typename T>
 class HandleBase {};
 
 template <typename T>
 class MutableHandleBase {};
 
--- a/js/public/TracingAPI.h
+++ b/js/public/TracingAPI.h
@@ -342,76 +342,11 @@ template <typename T>
 extern JS_PUBLIC_API(void)
 UnsafeTraceManuallyBarrieredEdge(JSTracer* trc, T* edgep, const char* name);
 
 namespace gc {
 template <typename T>
 extern JS_PUBLIC_API(bool)
 EdgeNeedsSweep(JS::Heap<T>* edgep);
 } // namespace gc
-
-// Automates static dispatch for GC interaction with TraceableContainers.
-template <typename>
-struct DefaultGCPolicy;
-
-// This policy dispatches GC methods to a method on the type.
-template <typename T>
-struct StructGCPolicy {
-    static void trace(JSTracer* trc, T* t, const char* name) {
-        // This is the default GC policy for storing GC things in containers.
-        // If your build is failing here, it means you either need an
-        // implementation of DefaultGCPolicy<T> for your type or, if this is
-        // the right policy for you, your struct or container is missing a
-        // trace method.
-        t->trace(trc);
-    }
-
-    static bool needsSweep(T* t) {
-        return t->needsSweep();
-    }
-};
-
-// This policy ignores any GC interaction, e.g. for non-GC types.
-template <typename T>
-struct IgnoreGCPolicy {
-    static void trace(JSTracer* trc, T* t, const char* name) {}
-    static bool needsSweep(T* v) { return false; }
-};
-
-// The default policy when no other more specific policy fits (e.g. for a
-// direct GC pointer), is to assume a struct type that implements the needed
-// methods.
-template <typename T>
-struct DefaultGCPolicy : public StructGCPolicy<T> {};
-
-template <>
-struct DefaultGCPolicy<jsid>
-{
-    static void trace(JSTracer* trc, jsid* idp, const char* name) {
-        js::UnsafeTraceManuallyBarrieredEdge(trc, idp, name);
-    }
-};
-
-template <>
-struct DefaultGCPolicy<JS::Value>
-{
-    static void trace(JSTracer* trc, JS::Value* v, const char* name) {
-        js::UnsafeTraceManuallyBarrieredEdge(trc, v, name);
-    }
-};
-
-template <> struct DefaultGCPolicy<uint32_t> : public IgnoreGCPolicy<uint32_t> {};
-template <> struct DefaultGCPolicy<uint64_t> : public IgnoreGCPolicy<uint64_t> {};
-
-template <typename T>
-struct DefaultGCPolicy<JS::Heap<T>>
-{
-    static void trace(JSTracer* trc, JS::Heap<T>* thingp, const char* name) {
-        JS::TraceEdge(trc, thingp, name);
-    }
-    static bool needsSweep(JS::Heap<T>* thingp) {
-        return gc::EdgeNeedsSweep(thingp);
-    }
-};
-
 } // namespace js
 
 #endif /* js_TracingAPI_h */
--- a/js/public/Value.h
+++ b/js/public/Value.h
@@ -1698,16 +1698,19 @@ JS_PUBLIC_API(void) HeapValuePostBarrier
 } // namespace JS
 
 namespace js {
 
 template <>
 struct GCPolicy<JS::Value>
 {
     static JS::Value initial() { return JS::UndefinedValue(); }
+    static void trace(JSTracer* trc, JS::Value* v, const char* name) {
+        js::UnsafeTraceManuallyBarrieredEdge(trc, v, name);
+    }
 };
 
 template <>
 struct BarrierMethods<JS::Value>
 {
     static gc::Cell* asGCThingOrNull(const JS::Value& v) {
         return v.isMarkable() ? v.toGCThing() : nullptr;
     }
--- a/js/src/asmjs/AsmJS.cpp
+++ b/js/src/asmjs/AsmJS.cpp
@@ -28,16 +28,17 @@
 #include "jsutil.h"
 
 #include "jswrapper.h"
 
 #include "asmjs/WasmGenerator.h"
 #include "asmjs/WasmSerialize.h"
 #include "builtin/SIMD.h"
 #include "frontend/Parser.h"
+#include "gc/Policy.h"
 #include "jit/AtomicOperations.h"
 #include "jit/MIR.h"
 #include "js/Class.h"
 #include "js/MemoryMetrics.h"
 #include "vm/StringBuffer.h"
 #include "vm/Time.h"
 #include "vm/TypedArrayObject.h"
 
--- a/js/src/builtin/ModuleObject.cpp
+++ b/js/src/builtin/ModuleObject.cpp
@@ -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/. */
 
 #include "builtin/ModuleObject.h"
 
 #include "builtin/SelfHostingDefines.h"
 #include "frontend/ParseNode.h"
 #include "frontend/SharedContext.h"
+#include "gc/Policy.h"
 #include "gc/Tracer.h"
 
 #include "jsobjinlines.h"
 
 using namespace js;
 using namespace js::frontend;
 
 template<typename T, Value ValueGetter(const T* obj)>
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -35,16 +35,17 @@
 #include "jscntxt.h"
 #include "jsexn.h"
 #include "jsfun.h"
 #include "jsnum.h"
 #include "jsprf.h"
 
 #include "builtin/TypedObject.h"
 #include "ctypes/Library.h"
+#include "gc/Policy.h"
 #include "gc/Zone.h"
 #include "js/Vector.h"
 
 #include "jsatominlines.h"
 #include "jsobjinlines.h"
 
 using namespace std;
 using mozilla::NumericLimits;
--- a/js/src/ds/TraceableFifo.h
+++ b/js/src/ds/TraceableFifo.h
@@ -15,18 +15,18 @@ namespace js {
 
 // A TraceableFifo is a Fifo with an additional trace method that knows how to
 // visit all of the items stored in the Fifo. For Fifos that contain GC things,
 // this is usually more convenient than manually iterating and marking the
 // contents.
 //
 // Most types of GC pointers as keys and values can be traced with no extra
 // infrastructure. For structs and non-gc-pointer members, ensure that there is
-// a specialization of DefaultGCPolicy<T> with an appropriate trace method
-// available to handle the custom type. Generic helpers can be found in
+// a specialization of GCPolicy<T> with an appropriate trace method available
+// to handle the custom type. Generic helpers can be found in
 // js/public/TracingAPI.h. Generic helpers can be found in
 // js/public/TracingAPI.h.
 //
 // Note that although this Fifo's trace will deal correctly with moved items, it
 // does not itself know when to barrier or trace items. To function properly it
 // must either be used with Rooted, or barriered and traced manually.
 template <typename T,
           size_t MinInlineCapacity = 0,
@@ -43,19 +43,19 @@ class TraceableFifo
     TraceableFifo(TraceableFifo&& rhs) : Base(mozilla::Move(rhs)) { }
     TraceableFifo& operator=(TraceableFifo&& rhs) { return Base::operator=(mozilla::Move(rhs)); }
 
     TraceableFifo(const TraceableFifo&) = delete;
     TraceableFifo& operator=(const TraceableFifo&) = delete;
 
     static void trace(TraceableFifo* tf, JSTracer* trc) {
         for (size_t i = 0; i < tf->front_.length(); ++i)
-            DefaultGCPolicy<T>::trace(trc, &tf->front_[i], "fifo element");
+            GCPolicy<T>::trace(trc, &tf->front_[i], "fifo element");
         for (size_t i = 0; i < tf->rear_.length(); ++i)
-            DefaultGCPolicy<T>::trace(trc, &tf->rear_[i], "fifo element");
+            GCPolicy<T>::trace(trc, &tf->rear_[i], "fifo element");
     }
 };
 
 template <typename Outer, typename T, size_t Capacity, typename AllocPolicy>
 class TraceableFifoOperations
 {
     using TF = TraceableFifo<T, Capacity, AllocPolicy>;
     const TF& fifo() const { return static_cast<const Outer*>(this)->extract(); }
--- a/js/src/gc/Barrier.cpp
+++ b/js/src/gc/Barrier.cpp
@@ -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/. */
 
 #include "gc/Barrier.h"
 
 #include "jscompartment.h"
 #include "jsobj.h"
 
+#include "gc/Policy.h"
 #include "gc/Zone.h"
 #include "js/HashTable.h"
 #include "js/Value.h"
 #include "vm/ScopeObject.h"
 #include "vm/SharedArrayObject.h"
 #include "vm/Symbol.h"
 
 namespace js {
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -12,16 +12,17 @@
 #include "mozilla/ScopeExit.h"
 #include "mozilla/TypeTraits.h"
 
 #include "jsgc.h"
 #include "jsprf.h"
 
 #include "builtin/ModuleObject.h"
 #include "gc/GCInternals.h"
+#include "gc/Policy.h"
 #include "jit/IonCode.h"
 #include "js/SliceBudget.h"
 #include "vm/ArgumentsObject.h"
 #include "vm/ArrayObject.h"
 #include "vm/ScopeObject.h"
 #include "vm/Shape.h"
 #include "vm/Symbol.h"
 #include "vm/TypedArrayObject.h"
@@ -522,16 +523,17 @@ FOR_EACH_GC_POINTER_TYPE(INSTANTIATE_ALL
 #undef INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS
 
 #define INSTANTIATE_PUBLIC_TRACE_FUNCTIONS(type) \
     template JS_PUBLIC_API(void) JS::TraceEdge<type>(JSTracer*, JS::Heap<type>*, const char*); \
     template JS_PUBLIC_API(void) JS::UnsafeTraceRoot<type>(JSTracer*, type*, const char*); \
     template JS_PUBLIC_API(void) js::UnsafeTraceManuallyBarrieredEdge<type>(JSTracer*, type*, \
                                                                             const char*);
 FOR_EACH_PUBLIC_GC_POINTER_TYPE(INSTANTIATE_PUBLIC_TRACE_FUNCTIONS)
+FOR_EACH_PUBLIC_TAGGED_GC_POINTER_TYPE(INSTANTIATE_PUBLIC_TRACE_FUNCTIONS)
 #undef INSTANTIATE_PUBLIC_TRACE_FUNCTIONS
 
 template <typename T>
 void
 js::TraceManuallyBarrieredCrossCompartmentEdge(JSTracer* trc, JSObject* src, T* dst,
                                                const char* name)
 {
     if (ShouldMarkCrossCompartment(trc, src, *dst))
--- a/js/src/gc/Marking.h
+++ b/js/src/gc/Marking.h
@@ -436,55 +436,11 @@ UnmarkGrayShapeRecursively(Shape* shape)
 template<typename T>
 void
 CheckTracedThing(JSTracer* trc, T* thing);
 
 template<typename T>
 void
 CheckTracedThing(JSTracer* trc, T thing);
 
-// Define a default Policy for all pointer types. This may fail to link if this
-// policy gets used on a non-GC typed pointer by accident. There is a separate
-// default policy for Value and jsid.
-template <typename T>
-struct DefaultGCPolicy<T*>
-{
-    static void trace(JSTracer* trc, T** thingp, const char* name) {
-        // If linking is failing here, it likely means that you need to define
-        // or use a non-default GC policy for your non-gc-pointer type.
-        if (*thingp)
-            TraceManuallyBarrieredEdge(trc, thingp, name);
-    }
-
-    static bool needsSweep(T** thingp) {
-        // If linking is failing here, it likely means that you need to define
-        // or use a non-default GC policy for your non-gc-pointer type.
-        return *thingp && gc::IsAboutToBeFinalizedUnbarriered(thingp);
-    }
-};
-
-// RelocatablePtr is only defined for GC pointer types, so this default policy
-// should work in all cases.
-template <typename T>
-struct DefaultGCPolicy<RelocatablePtr<T>>
-{
-    static void trace(JSTracer* trc, RelocatablePtr<T>* thingp, const char* name) {
-        TraceEdge(trc, thingp, name);
-    }
-    static bool needsSweep(RelocatablePtr<T>* thingp) {
-        return gc::IsAboutToBeFinalizedUnbarriered(thingp);
-    }
-};
-
-template <typename T>
-struct DefaultGCPolicy<ReadBarriered<T>>
-{
-    static void trace(JSTracer* trc, ReadBarriered<T>* thingp, const char* name) {
-        TraceEdge(trc, thingp, name);
-    }
-    static bool needsSweep(ReadBarriered<T>* thingp) {
-        return gc::IsAboutToBeFinalized(thingp);
-    }
-};
-
 } /* namespace js */
 
 #endif /* gc_Marking_h */
new file mode 100644
--- /dev/null
+++ b/js/src/gc/Policy.h
@@ -0,0 +1,161 @@
+/* -*- 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/. */
+
+/* JS Garbage Collector. */
+
+#ifndef gc_Policy_h
+#define gc_Policy_h
+
+#include "mozilla/TypeTraits.h"
+#include "js/GCPolicyAPI.h"
+
+// Forward declare the types we're defining policies for. This file is
+// included in all places that define GC things, so the real definitions
+// will be available when we do template expansion, allowing for use of
+// static members in the underlying types. We cannot, however, user
+// static_assert to verify relations between types.
+namespace js {
+class AccessorShape;
+class ArgumentsObject;
+class ArrayBufferObject;
+class ArrayBufferObjectMaybeShared;
+class ArrayBufferViewObject;
+class ArrayObject;
+class BaseShape;
+class ClonedBlockObject;
+class DebugScopeObject;
+class ExportEntryObject;
+class GlobalObject;
+class ImportEntryObject;
+class LazyScript;
+class ModuleEnvironmentObject;
+class ModuleNamespaceObject;
+class ModuleObject;
+class NativeObject;
+class NestedScopeObject;
+class ObjectGroup;
+class PlainObject;
+class PropertyName;
+class RegExpObject;
+class SavedFrame;
+class ScopeObject;
+class ScriptSourceObject;
+class Shape;
+class SharedArrayBufferObject;
+class StructTypeDescr;
+class UnownedBaseShape;
+namespace jit {
+class JitCode;
+} // namespace jit
+} // namespace js
+
+// Expand the given macro D for each public GC pointer.
+#define FOR_EACH_PUBLIC_GC_POINTER_TYPE(D) \
+    D(JS::Symbol*) \
+    D(JSAtom*) \
+    D(JSFunction*) \
+    D(JSObject*) \
+    D(JSScript*) \
+    D(JSString*)
+
+// Expand the given macro D for each public tagged GC pointer type.
+#define FOR_EACH_PUBLIC_TAGGED_GC_POINTER_TYPE(D) \
+    D(JS::Value) \
+    D(jsid)
+
+#define FOR_EACH_PUBLIC_AGGREGATE_GC_POINTER_TYPE(D) \
+    D(JSPropertyDescriptor)
+
+// Expand the given macro D for each valid GC reference type.
+#define FOR_EACH_INTERNAL_GC_POINTER_TYPE(D) \
+    D(JSFlatString*) \
+    D(JSLinearString*) \
+    D(js::AccessorShape*) \
+    D(js::ArgumentsObject*) \
+    D(js::ArrayBufferObject*) \
+    D(js::ArrayBufferObjectMaybeShared*) \
+    D(js::ArrayBufferViewObject*) \
+    D(js::ArrayObject*) \
+    D(js::BaseShape*) \
+    D(js::ClonedBlockObject*) \
+    D(js::DebugScopeObject*) \
+    D(js::ExportEntryObject*) \
+    D(js::GlobalObject*) \
+    D(js::ImportEntryObject*) \
+    D(js::LazyScript*) \
+    D(js::ModuleEnvironmentObject*) \
+    D(js::ModuleNamespaceObject*) \
+    D(js::ModuleObject*) \
+    D(js::NativeObject*) \
+    D(js::NestedScopeObject*) \
+    D(js::ObjectGroup*) \
+    D(js::PlainObject*) \
+    D(js::PropertyName*) \
+    D(js::RegExpObject*) \
+    D(js::SavedFrame*) \
+    D(js::ScopeObject*) \
+    D(js::ScriptSourceObject*) \
+    D(js::Shape*) \
+    D(js::SharedArrayBufferObject*) \
+    D(js::StructTypeDescr*) \
+    D(js::UnownedBaseShape*) \
+    D(js::jit::JitCode*)
+
+// Expand the given macro D for each internal tagged GC pointer type.
+#define FOR_EACH_INTERNAL_TAGGED_GC_POINTER_TYPE(D) \
+    D(js::TaggedProto)
+
+// Expand the macro D for every GC reference type that we know about.
+#define FOR_EACH_GC_POINTER_TYPE(D) \
+    FOR_EACH_PUBLIC_GC_POINTER_TYPE(D) \
+    FOR_EACH_PUBLIC_TAGGED_GC_POINTER_TYPE(D) \
+    FOR_EACH_INTERNAL_GC_POINTER_TYPE(D) \
+    FOR_EACH_INTERNAL_TAGGED_GC_POINTER_TYPE(D)
+
+namespace js {
+
+// Define the GCPolicy for all internal pointers.
+template <typename T>
+struct InternalGCPointerPolicy {
+    using Type = typename mozilla::RemovePointer<T>::Type;
+    static T initial() { return nullptr; }
+    static void preBarrier(T v) { Type::writeBarrierPre(v); }
+    static void postBarrier(T* vp, T prev, T next) { Type::writeBarrierPost(vp, prev, next); }
+    static void readBarrier(T v) { Type::readBarrier(v); }
+    static void trace(JSTracer* trc, T* vp, const char* name) {
+        TraceManuallyBarrieredEdge(trc, vp, name);
+    }
+};
+#define DEFINE_INTERNAL_GC_POLICY(type) \
+    template <> struct GCPolicy<type> : public InternalGCPointerPolicy<type> {};
+FOR_EACH_INTERNAL_GC_POINTER_TYPE(DEFINE_INTERNAL_GC_POLICY)
+#undef DEFINE_INTERNAL_GC_POLICY
+
+template <typename T>
+struct GCPolicy<RelocatablePtr<T>>
+{
+    static void trace(JSTracer* trc, RelocatablePtr<T>* thingp, const char* name) {
+        TraceEdge(trc, thingp, name);
+    }
+    static bool needsSweep(RelocatablePtr<T>* thingp) {
+        return gc::IsAboutToBeFinalized(thingp);
+    }
+};
+
+template <typename T>
+struct GCPolicy<ReadBarriered<T>>
+{
+    static void trace(JSTracer* trc, ReadBarriered<T>* thingp, const char* name) {
+        TraceEdge(trc, thingp, name);
+    }
+    static bool needsSweep(ReadBarriered<T>* thingp) {
+        return gc::IsAboutToBeFinalized(thingp);
+    }
+};
+
+} // namespace js
+
+#endif // gc_Policy_h
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -10,16 +10,17 @@
 #include "mozilla/SizePrintfMacros.h"
 #include "mozilla/TemplateLib.h"
 
 #include "jslibmath.h"
 #include "jstypes.h"
 
 #include "builtin/Eval.h"
 #include "builtin/SIMD.h"
+#include "gc/Policy.h"
 #include "jit/BaselineDebugModeOSR.h"
 #include "jit/BaselineJIT.h"
 #include "jit/JitSpewer.h"
 #include "jit/Linker.h"
 #include "jit/Lowering.h"
 #ifdef JS_ION_PERF
 # include "jit/PerfSpewer.h"
 #endif
--- a/js/src/jit/SharedIC.cpp
+++ b/js/src/jit/SharedIC.cpp
@@ -8,16 +8,17 @@
 
 #include "mozilla/Casting.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/SizePrintfMacros.h"
 
 #include "jslibmath.h"
 #include "jstypes.h"
 
+#include "gc/Policy.h"
 #include "jit/BaselineDebugModeOSR.h"
 #include "jit/BaselineIC.h"
 #include "jit/JitSpewer.h"
 #include "jit/Linker.h"
 #include "jit/SharedICHelpers.h"
 #ifdef JS_ION_PERF
 # include "jit/PerfSpewer.h"
 #endif
--- a/js/src/jsapi-tests/testGCExactRooting.cpp
+++ b/js/src/jsapi-tests/testGCExactRooting.cpp
@@ -1,16 +1,17 @@
 /* -*- 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 "ds/TraceableFifo.h"
+#include "gc/Policy.h"
 #include "js/GCHashTable.h"
 #include "js/GCVector.h"
 #include "js/RootingAPI.h"
 
 #include "jsapi-tests/tests.h"
 
 using namespace js;
 
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -54,16 +54,17 @@
 #endif
 #ifdef ENABLE_BINARYDATA
 # include "builtin/TypedObject.h"
 #endif
 #include "frontend/BytecodeCompiler.h"
 #include "frontend/FullParseHandler.h"  // for JS_BufferIsCompileableUnit
 #include "frontend/Parser.h" // for JS_BufferIsCompileableUnit
 #include "gc/Marking.h"
+#include "gc/Policy.h"
 #include "jit/JitCommon.h"
 #include "js/CharacterEncoding.h"
 #include "js/Conversions.h"
 #include "js/Date.h"
 #include "js/Initialization.h"
 #include "js/Proxy.h"
 #include "js/SliceBudget.h"
 #include "js/StructuredClone.h"
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -12,16 +12,17 @@
 #include "jscntxt.h"
 #include "jsfriendapi.h"
 #include "jsgc.h"
 #include "jsiter.h"
 #include "jswatchpoint.h"
 #include "jswrapper.h"
 
 #include "gc/Marking.h"
+#include "gc/Policy.h"
 #include "jit/JitCompartment.h"
 #include "jit/JitOptions.h"
 #include "js/Date.h"
 #include "js/Proxy.h"
 #include "js/RootingAPI.h"
 #include "proxy/DeadObjectProxy.h"
 #include "vm/Debugger.h"
 #include "vm/StopIterationObject.h"
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -28,16 +28,17 @@
 #include "jswrapper.h"
 
 #include "builtin/Eval.h"
 #include "builtin/Object.h"
 #include "builtin/SelfHostingDefines.h"
 #include "frontend/BytecodeCompiler.h"
 #include "frontend/TokenStream.h"
 #include "gc/Marking.h"
+#include "gc/Policy.h"
 #include "jit/InlinableNatives.h"
 #include "jit/Ion.h"
 #include "jit/JitFrameIterator.h"
 #include "js/CallNonGenericMethod.h"
 #include "js/Proxy.h"
 #include "vm/Debugger.h"
 #include "vm/GlobalObject.h"
 #include "vm/Interpreter.h"
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -46,61 +46,16 @@ struct FinalizePhase;
 enum State {
     NO_INCREMENTAL,
     MARK_ROOTS,
     MARK,
     SWEEP,
     COMPACT
 };
 
-// Expand the given macro D for each publicly exposed GC reference type.
-#define FOR_EACH_PUBLIC_GC_POINTER_TYPE(D) \
-    D(JS::Symbol*) \
-    D(JSAtom*) \
-    D(JSFunction*) \
-    D(JSObject*) \
-    D(JSScript*) \
-    D(JSString*) \
-    D(JS::Value) \
-    D(jsid)
-
-// Expand the given macro D for each valid GC reference type.
-#define FOR_EACH_GC_POINTER_TYPE(D) \
-    FOR_EACH_PUBLIC_GC_POINTER_TYPE(D) \
-    D(AccessorShape*) \
-    D(BaseShape*) \
-    D(UnownedBaseShape*) \
-    D(jit::JitCode*) \
-    D(NativeObject*) \
-    D(ArrayObject*) \
-    D(ArgumentsObject*) \
-    D(ArrayBufferObject*) \
-    D(ArrayBufferObjectMaybeShared*) \
-    D(ArrayBufferViewObject*) \
-    D(DebugScopeObject*) \
-    D(GlobalObject*) \
-    D(ModuleObject*) \
-    D(ModuleEnvironmentObject*) \
-    D(ModuleNamespaceObject*) \
-    D(NestedScopeObject*) \
-    D(PlainObject*) \
-    D(SavedFrame*) \
-    D(ScopeObject*) \
-    D(ScriptSourceObject*) \
-    D(SharedArrayBufferObject*) \
-    D(ImportEntryObject*) \
-    D(ExportEntryObject*) \
-    D(LazyScript*) \
-    D(Shape*) \
-    D(JSFlatString*) \
-    D(JSLinearString*) \
-    D(PropertyName*) \
-    D(js::ObjectGroup*) \
-    D(TaggedProto)
-
 /* Map from C++ type to alloc kind. JSObject does not have a 1:1 mapping, so must use Arena::thingSize. */
 template <typename T> struct MapTypeToFinalizeKind {};
 template <> struct MapTypeToFinalizeKind<JSScript>          { static const AllocKind kind = AllocKind::SCRIPT; };
 template <> struct MapTypeToFinalizeKind<LazyScript>        { static const AllocKind kind = AllocKind::LAZY_SCRIPT; };
 template <> struct MapTypeToFinalizeKind<Shape>             { static const AllocKind kind = AllocKind::SHAPE; };
 template <> struct MapTypeToFinalizeKind<AccessorShape>     { static const AllocKind kind = AllocKind::ACCESSOR_SHAPE; };
 template <> struct MapTypeToFinalizeKind<BaseShape>         { static const AllocKind kind = AllocKind::BASE_SHAPE; };
 template <> struct MapTypeToFinalizeKind<ObjectGroup>       { static const AllocKind kind = AllocKind::OBJECT_GROUP; };
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -38,16 +38,17 @@
 #include "jswrapper.h"
 
 #include "asmjs/WasmModule.h"
 #include "builtin/Eval.h"
 #include "builtin/Object.h"
 #include "builtin/SymbolObject.h"
 #include "frontend/BytecodeCompiler.h"
 #include "gc/Marking.h"
+#include "gc/Policy.h"
 #include "jit/BaselineJIT.h"
 #include "js/MemoryMetrics.h"
 #include "js/Proxy.h"
 #include "js/UbiNode.h"
 #include "js/UniquePtr.h"
 #include "vm/ArgumentsObject.h"
 #include "vm/Interpreter.h"
 #include "vm/ProxyObject.h"
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -106,16 +106,17 @@ EXPORTS.js += [
     '../public/CallNonGenericMethod.h',
     '../public/CharacterEncoding.h',
     '../public/Class.h',
     '../public/Conversions.h',
     '../public/Date.h',
     '../public/Debug.h',
     '../public/GCAPI.h',
     '../public/GCHashTable.h',
+    '../public/GCPolicyAPI.h',
     '../public/GCVector.h',
     '../public/HashTable.h',
     '../public/HeapAPI.h',
     '../public/Id.h',
     '../public/Initialization.h',
     '../public/LegacyIntTypes.h',
     '../public/MemoryMetrics.h',
     '../public/Principals.h',
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -286,19 +286,20 @@ class Debugger : private mozilla::Linked
     {
         TenurePromotionsLogEntry(JSRuntime* rt, JSObject& obj, double when);
 
         const char* className;
         double when;
         RelocatablePtrObject frame;
         size_t size;
 
-        static void trace(TenurePromotionsLogEntry* e, JSTracer* trc) {
-            if (e->frame)
-                TraceEdge(trc, &e->frame, "Debugger::TenurePromotionsLogEntry::frame");
+        static void trace(TenurePromotionsLogEntry* e, JSTracer* trc) { e->trace(trc); }
+        void trace(JSTracer* trc) {
+            if (frame)
+                TraceEdge(trc, &frame, "Debugger::TenurePromotionsLogEntry::frame");
         }
     };
 
     struct AllocationsLogEntry : public JS::Traceable
     {
         AllocationsLogEntry(HandleObject frame, double when, const char* className,
                             HandleAtom ctorName, size_t size, bool inNursery)
             : frame(frame),
@@ -313,21 +314,22 @@ class Debugger : private mozilla::Linked
 
         RelocatablePtrObject frame;
         double when;
         const char* className;
         RelocatablePtrAtom ctorName;
         size_t size;
         bool inNursery;
 
-        static void trace(AllocationsLogEntry* e, JSTracer* trc) {
-            if (e->frame)
-                TraceEdge(trc, &e->frame, "Debugger::AllocationsLogEntry::frame");
-            if (e->ctorName)
-                TraceEdge(trc, &e->ctorName, "Debugger::AllocationsLogEntry::ctorName");
+        static void trace(AllocationsLogEntry* e, JSTracer* trc) { e->trace(trc); }
+        void trace(JSTracer* trc) {
+            if (frame)
+                TraceEdge(trc, &frame, "Debugger::AllocationsLogEntry::frame");
+            if (ctorName)
+                TraceEdge(trc, &ctorName, "Debugger::AllocationsLogEntry::ctorName");
         }
     };
 
   private:
     HeapPtrNativeObject object;         /* The Debugger object. Strong reference. */
     WeakGlobalObjectSet debuggees;      /* Debuggee globals. Cross-compartment weak references. */
     JS::ZoneSet debuggeeZones; /* Set of zones that we have debuggees in. */
     js::HeapPtrObject uncaughtExceptionHook; /* Strong reference. */
@@ -936,30 +938,16 @@ class Debugger : private mozilla::Linked
      */
     JSObject* wrapSource(JSContext* cx, js::HandleScriptSource source);
 
   private:
     Debugger(const Debugger&) = delete;
     Debugger & operator=(const Debugger&) = delete;
 };
 
-template<>
-struct DefaultGCPolicy<Debugger::TenurePromotionsLogEntry> {
-    static void trace(JSTracer* trc, Debugger::TenurePromotionsLogEntry* e, const char*) {
-        Debugger::TenurePromotionsLogEntry::trace(e, trc);
-    }
-};
-
-template<>
-struct DefaultGCPolicy<Debugger::AllocationsLogEntry> {
-    static void trace(JSTracer* trc, Debugger::AllocationsLogEntry* e, const char*) {
-        Debugger::AllocationsLogEntry::trace(e, trc);
-    }
-};
-
 class BreakpointSite {
     friend class Breakpoint;
     friend struct ::JSCompartment;
     friend class ::JSScript;
     friend class Debugger;
 
   public:
     JSScript* script;
--- a/js/src/vm/ObjectGroup.cpp
+++ b/js/src/vm/ObjectGroup.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "vm/ObjectGroup.h"
 
 #include "jshashutil.h"
 #include "jsobj.h"
 
 #include "gc/Marking.h"
+#include "gc/Policy.h"
 #include "gc/StoreBuffer.h"
 #include "gc/Zone.h"
 #include "vm/ArrayObject.h"
 #include "vm/UnboxedObject.h"
 
 #include "jsobjinlines.h"
 
 #include "vm/UnboxedObject-inl.h"
@@ -1770,17 +1771,17 @@ ObjectGroupCompartment::clearTables()
     if (lazyTable && lazyTable->initialized())
         lazyTable->clear();
 }
 
 /* static */ bool
 ObjectGroupCompartment::PlainObjectTableSweepPolicy::needsSweep(PlainObjectKey* key,
                                                                 PlainObjectEntry* entry)
 {
-    if (!(DefaultGCPolicy<PlainObjectKey>::needsSweep(key) || entry->needsSweep(key->nproperties)))
+    if (!(GCPolicy<PlainObjectKey>::needsSweep(key) || entry->needsSweep(key->nproperties)))
         return false;
     js_free(key->properties);
     js_free(entry->types);
     return true;
 }
 
 void
 ObjectGroupCompartment::sweep(FreeOp* fop)
--- a/js/src/vm/SavedStacks.cpp
+++ b/js/src/vm/SavedStacks.cpp
@@ -18,16 +18,17 @@
 #include "jscompartment.h"
 #include "jsfriendapi.h"
 #include "jshashutil.h"
 #include "jsmath.h"
 #include "jsnum.h"
 #include "jsscript.h"
 
 #include "gc/Marking.h"
+#include "gc/Policy.h"
 #include "gc/Rooting.h"
 #include "js/Vector.h"
 #include "vm/Debugger.h"
 #include "vm/SavedFrame.h"
 #include "vm/SPSProfiler.h"
 #include "vm/StringBuffer.h"
 #include "vm/Time.h"
 #include "vm/WrapperObject.h"
--- a/js/src/vm/ScopeObject.cpp
+++ b/js/src/vm/ScopeObject.cpp
@@ -8,19 +8,18 @@
 
 #include "mozilla/PodOperations.h"
 #include "mozilla/SizePrintfMacros.h"
 
 #include "jscompartment.h"
 #include "jsiter.h"
 
 #include "builtin/ModuleObject.h"
-
 #include "frontend/ParseNode.h"
-
+#include "gc/Policy.h"
 #include "vm/ArgumentsObject.h"
 #include "vm/GlobalObject.h"
 #include "vm/ProxyObject.h"
 #include "vm/Shape.h"
 #include "vm/Xdr.h"
 
 #include "jsatominlines.h"
 #include "jsobjinlines.h"
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -26,16 +26,17 @@
 #include "builtin/ModuleObject.h"
 #include "builtin/Object.h"
 #include "builtin/Reflect.h"
 #include "builtin/SelfHostingDefines.h"
 #include "builtin/SIMD.h"
 #include "builtin/TypedObject.h"
 #include "builtin/WeakSetObject.h"
 #include "gc/Marking.h"
+#include "gc/Policy.h"
 #include "jit/AtomicOperations.h"
 #include "jit/InlinableNatives.h"
 #include "js/Date.h"
 #include "vm/Compression.h"
 #include "vm/GeneratorObject.h"
 #include "vm/Interpreter.h"
 #include "vm/String.h"
 #include "vm/TypedArrayCommon.h"