Merge inbound to mozilla-central. a=merge
authorCsoregi Natalia <ncsoregi@mozilla.com>
Mon, 15 Apr 2019 12:44:31 +0300
changeset 469469 6c9e7cba261d72303c39d9f3a9bb45b91fa1fd3e
parent 469468 dc2fb967b01982c985558197b923c459811705c6 (current diff)
parent 469443 6741a996b17d76f8dd26d68ef610d4ee3436b93c (diff)
child 469470 a57f27d3ccd0d5066c8fa85f0a5a97b5bc17601b
child 469487 7b8dc38bb07efef7a6e8dacca0f0ac695685050e
child 469494 ee0e5ecb371489783d82b4956909c185ff1a8f7a
push id112792
push userncsoregi@mozilla.com
push dateMon, 15 Apr 2019 09:49:11 +0000
treeherdermozilla-inbound@a57f27d3ccd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone68.0a1
first release with
nightly linux32
6c9e7cba261d / 68.0a1 / 20190415094551 / files
nightly linux64
6c9e7cba261d / 68.0a1 / 20190415094551 / files
nightly mac
6c9e7cba261d / 68.0a1 / 20190415094551 / files
nightly win32
6c9e7cba261d / 68.0a1 / 20190415094551 / files
nightly win64
6c9e7cba261d / 68.0a1 / 20190415094551 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central. a=merge
--- a/js/public/HeapAPI.h
+++ b/js/public/HeapAPI.h
@@ -344,18 +344,18 @@ class JS_FRIEND_API GCCellPtr {
   uintptr_t ptr;
 };
 
 // Unwraps the given GCCellPtr, calls the functor |f| with a template argument
 // of the actual type of the pointer, and returns the result.
 template <typename F>
 auto MapGCThingTyped(GCCellPtr thing, F&& f) {
   switch (thing.kind()) {
-#define JS_EXPAND_DEF(name, type, _) \
-  case JS::TraceKind::name:          \
+#define JS_EXPAND_DEF(name, type, _, _1) \
+  case JS::TraceKind::name:              \
     return f(&thing.as<type>());
     JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF);
 #undef JS_EXPAND_DEF
     default:
       MOZ_CRASH("Invalid trace kind in MapGCThingTyped for GCCellPtr.");
   }
 }
 
--- a/js/public/TraceKind.h
+++ b/js/public/TraceKind.h
@@ -61,28 +61,16 @@ enum class TraceKind {
   JitCode = 0x1F,
   LazyScript = 0x2F,
   Scope = 0x3F,
   RegExpShared = 0x4F,
   BigInt = 0x5F
 };
 const static uintptr_t OutOfLineTraceKindMask = 0x07;
 
-// Returns true if the JS::TraceKind is one the cycle collector cares about.
-// Everything used as WeakMap key should be listed here, to represent the key
-// in cycle collector's graph, otherwise the key is considered to be pointed
-// from somewhere unknown, and results in leaking the subgraph which contains
-// the key.
-// See the comments in NoteWeakMapsTracer::trace for more details.
-inline constexpr bool IsCCTraceKind(JS::TraceKind aKind) {
-  return aKind == JS::TraceKind::Object || aKind == JS::TraceKind::Script ||
-         aKind == JS::TraceKind::LazyScript || aKind == JS::TraceKind::Scope ||
-         aKind == JS::TraceKind::RegExpShared;
-}
-
 #define ASSERT_TRACE_KIND(tk)                                             \
   static_assert(                                                          \
       (uintptr_t(tk) & OutOfLineTraceKindMask) == OutOfLineTraceKindMask, \
       "mask bits are set")
 ASSERT_TRACE_KIND(JS::TraceKind::BaseShape);
 ASSERT_TRACE_KIND(JS::TraceKind::JitCode);
 ASSERT_TRACE_KIND(JS::TraceKind::LazyScript);
 ASSERT_TRACE_KIND(JS::TraceKind::Scope);
@@ -94,63 +82,85 @@ ASSERT_TRACE_KIND(JS::TraceKind::RegExpS
 // directly from the class hierarchy.
 template <typename T>
 struct MapTypeToTraceKind {
   static const JS::TraceKind kind = T::TraceKind;
 };
 
 // When this header is used outside SpiderMonkey, the class definitions are not
 // available, so the following table containing all public GC types is used.
-#define JS_FOR_EACH_TRACEKIND(D)                          \
-  /* PrettyName       TypeName           IsCCTraceKind */ \
-  D(BaseShape, js::BaseShape, true)                       \
-  D(JitCode, js::jit::JitCode, true)                      \
-  D(LazyScript, js::LazyScript, true)                     \
-  D(Scope, js::Scope, true)                               \
-  D(Object, JSObject, true)                               \
-  D(ObjectGroup, js::ObjectGroup, true)                   \
-  D(Script, JSScript, true)                               \
-  D(Shape, js::Shape, true)                               \
-  D(String, JSString, false)                              \
-  D(Symbol, JS::Symbol, false)                            \
-  D(BigInt, JS::BigInt, false)                            \
-  D(RegExpShared, js::RegExpShared, true)
+//
+// canBeGray: GC can mark things of this kind gray. The cycle collector
+//            traverses gray GC things when looking for cycles.
+// inCCGraph: Things of this kind are represented as nodes in the CC graph. This
+//            also means they can be used as a keys in WeakMap.
+
+// clang-format off
+#define JS_FOR_EACH_TRACEKIND(D)                                 \
+  /* name         type              canBeGray       inCCGraph */ \
+  D(BaseShape,    js::BaseShape,    true,           false)       \
+  D(JitCode,      js::jit::JitCode, true,           false)       \
+  D(LazyScript,   js::LazyScript,   true,           true)        \
+  D(Scope,        js::Scope,        true,           true)        \
+  D(Object,       JSObject,         true,           true)        \
+  D(ObjectGroup,  js::ObjectGroup,  true,           false)       \
+  D(Script,       JSScript,         true,           true)        \
+  D(Shape,        js::Shape,        true,           false)       \
+  D(String,       JSString,         false,          false)       \
+  D(Symbol,       JS::Symbol,       false,          false)       \
+  D(BigInt,       JS::BigInt,       false,          false)       \
+  D(RegExpShared, js::RegExpShared, true,           true)
+// clang-format on
+
+// Returns true if the JS::TraceKind is represented as a node in cycle collector
+// graph.
+inline constexpr bool IsCCTraceKind(JS::TraceKind aKind) {
+  switch (aKind) {
+#define JS_EXPAND_DEF(name, _1, _2, inCCGraph) \
+    case JS::TraceKind::name: \
+      return inCCGraph;
+      JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF);
+#undef JS_EXPAND_DEF
+    default:
+      return false;
+  }
+}
 
 // Map from all public types to their trace kind.
-#define JS_EXPAND_DEF(name, type, _)                       \
+#define JS_EXPAND_DEF(name, type, _, _1)                   \
   template <>                                              \
   struct MapTypeToTraceKind<type> {                        \
     static const JS::TraceKind kind = JS::TraceKind::name; \
   };
 JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF);
 #undef JS_EXPAND_DEF
 
 // RootKind is closely related to TraceKind. Whereas TraceKind's indices are
 // laid out for convenient embedding as a pointer tag, the indicies of RootKind
 // are designed for use as array keys via EnumeratedArray.
 enum class RootKind : int8_t {
 // These map 1:1 with trace kinds.
-#define EXPAND_ROOT_KIND(name, _0, _1) name,
+#define EXPAND_ROOT_KIND(name, _0, _1, _2) name,
   JS_FOR_EACH_TRACEKIND(EXPAND_ROOT_KIND)
 #undef EXPAND_ROOT_KIND
 
   // These tagged pointers are special-cased for performance.
   Id,
   Value,
 
   // Everything else.
   Traceable,
 
   Limit
 };
 
 // Most RootKind correspond directly to a trace kind.
 template <TraceKind traceKind>
 struct MapTraceKindToRootKind {};
-#define JS_EXPAND_DEF(name, _0, _1)                      \
+#define JS_EXPAND_DEF(name, _0, _1, _2)                  \
   template <>                                            \
   struct MapTraceKindToRootKind<JS::TraceKind::name> {   \
     static const JS::RootKind kind = JS::RootKind::name; \
   };
 JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF)
 #undef JS_EXPAND_DEF
 
 // Specify the RootKind for all types. Value and jsid map to special cases;
@@ -207,17 +217,17 @@ struct MapTypeToRootKind<JSFunction*> : 
 #if (defined(_MSC_VER) && _MSC_VER < 1910) && !defined(__clang__)
 #  define JS_DEPENDENT_TEMPLATE_HINT
 #else
 #  define JS_DEPENDENT_TEMPLATE_HINT template
 #endif
 template <typename F, typename... Args>
 auto DispatchTraceKindTyped(F f, JS::TraceKind traceKind, Args&&... args) {
   switch (traceKind) {
-#define JS_EXPAND_DEF(name, type, _)                      \
+#define JS_EXPAND_DEF(name, type, _, _1)                   \
   case JS::TraceKind::name:                               \
     return f.JS_DEPENDENT_TEMPLATE_HINT operator()<type>( \
         std::forward<Args>(args)...);
     JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF);
 #undef JS_EXPAND_DEF
     default:
       MOZ_CRASH("Invalid trace kind in DispatchTraceKindTyped.");
   }
@@ -225,18 +235,18 @@ auto DispatchTraceKindTyped(F f, JS::Tra
 #undef JS_DEPENDENT_TEMPLATE_HINT
 
 // Given a GC thing specified by pointer and trace kind, calls the functor |f|
 // with a template argument of the actual type of the pointer and returns the
 // result.
 template <typename F>
 auto MapGCThingTyped(void* thing, JS::TraceKind traceKind, F&& f) {
   switch (traceKind) {
-#define JS_EXPAND_DEF(name, type, _) \
-  case JS::TraceKind::name:          \
+#define JS_EXPAND_DEF(name, type, _, _1) \
+  case JS::TraceKind::name:             \
     return f(static_cast<type*>(thing));
     JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF);
 #undef JS_EXPAND_DEF
     default:
       MOZ_CRASH("Invalid trace kind in MapGCThingTyped.");
   }
 }
 
--- a/js/src/gc/GC.cpp
+++ b/js/src/gc/GC.cpp
@@ -8424,18 +8424,18 @@ JS::AutoEnterCycleCollection::~AutoEnter
 JS::AutoAssertGCCallback::AutoAssertGCCallback() : AutoSuppressGCAnalysis() {
   MOZ_ASSERT(JS::RuntimeHeapIsCollecting());
 }
 
 #endif  // DEBUG
 
 JS_FRIEND_API const char* JS::GCTraceKindToAscii(JS::TraceKind kind) {
   switch (kind) {
-#define MAP_NAME(name, _0, _1) \
-  case JS::TraceKind::name:    \
+#define MAP_NAME(name, _0, _1, _2) \
+  case JS::TraceKind::name:        \
     return #name;
     JS_FOR_EACH_TRACEKIND(MAP_NAME);
 #undef MAP_NAME
     default:
       return "Invalid";
   }
 }
 
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -275,17 +275,17 @@ void js::CheckTracedThing(JSTracer* trc,
 }
 
 template <typename T>
 void js::CheckTracedThing(JSTracer* trc, T thing) {
   ApplyGCThingTyped(thing, [](auto t) { CheckTracedThing(t); });
 }
 
 namespace js {
-#define IMPL_CHECK_TRACED_THING(_, type, __) \
+#define IMPL_CHECK_TRACED_THING(_, type, _1, _2) \
   template void CheckTracedThing<type>(JSTracer*, type*);
 JS_FOR_EACH_TRACEKIND(IMPL_CHECK_TRACED_THING);
 #undef IMPL_CHECK_TRACED_THING
 }  // namespace js
 
 static bool UnmarkGrayGCThing(JSRuntime* rt, JS::GCCellPtr thing);
 
 static inline bool ShouldMarkCrossCompartment(GCMarker* marker, JSObject* src,
@@ -446,17 +446,17 @@ namespace js {
 namespace gc {
 
 #define INSTANTIATE_INTERNAL_TRACE_FUNCTIONS(type)                          \
   template void TraceEdgeInternal<type>(JSTracer*, type*, const char*);     \
   template void TraceWeakEdgeInternal<type>(JSTracer*, type*, const char*); \
   template void TraceRangeInternal<type>(JSTracer*, size_t len, type*,      \
                                          const char*);
 
-#define INSTANTIATE_INTERNAL_TRACE_FUNCTIONS_FROM_TRACEKIND(_1, type, _2) \
+#define INSTANTIATE_INTERNAL_TRACE_FUNCTIONS_FROM_TRACEKIND(_1, type, _2, _3) \
   INSTANTIATE_INTERNAL_TRACE_FUNCTIONS(type*)
 
 JS_FOR_EACH_TRACEKIND(INSTANTIATE_INTERNAL_TRACE_FUNCTIONS_FROM_TRACEKIND)
 FOR_EACH_PUBLIC_TAGGED_GC_POINTER_TYPE(INSTANTIATE_INTERNAL_TRACE_FUNCTIONS)
 
 #undef INSTANTIATE_INTERNAL_TRACE_FUNCTIONS_FROM_TRACEKIND
 #undef INSTANTIATE_INTERNAL_TRACE_FUNCTIONS
 
@@ -545,17 +545,17 @@ void js::TraceManuallyBarrieredGenericPo
   }
 }
 
 // This method is responsible for dynamic dispatch to the real tracer
 // implementation. Consider replacing this choke point with virtual dispatch:
 // a sufficiently smart C++ compiler may be able to devirtualize some paths.
 template <typename T>
 void js::gc::TraceEdgeInternal(JSTracer* trc, T* thingp, const char* name) {
-#define IS_SAME_TYPE_OR(name, type, _) mozilla::IsSame<type*, T>::value ||
+#define IS_SAME_TYPE_OR(name, type, _, _1) mozilla::IsSame<type*, T>::value ||
   static_assert(JS_FOR_EACH_TRACEKIND(IS_SAME_TYPE_OR)
                         mozilla::IsSame<T, JS::Value>::value ||
                     mozilla::IsSame<T, jsid>::value ||
                     mozilla::IsSame<T, TaggedProto>::value,
                 "Only the base cell layout types are allowed into "
                 "marking/tracing internals");
 #undef IS_SAME_TYPE_OR
   if (trc->isMarkingTracer()) {
@@ -919,52 +919,48 @@ template <typename S, typename T>
 void js::GCMarker::traverseEdge(S source, const T& thing) {
   ApplyGCThingTyped(thing,
                     [this, source](auto t) { this->traverseEdge(source, t); });
 }
 
 namespace {
 
 template <typename T>
-struct TypeParticipatesInCC {};
-#define EXPAND_PARTICIPATES_IN_CC(_, type, addToCCKind) \
-  template <>                                           \
-  struct TypeParticipatesInCC<type> {                   \
-    static const bool value = addToCCKind;              \
+struct TraceKindCanBeGray {};
+#define EXPAND_TRACEKIND_DEF(_, type, canBeGray, _1)  \
+  template <>                                         \
+  struct TraceKindCanBeGray<type> {                   \
+    static const bool value = canBeGray;              \
   };
-JS_FOR_EACH_TRACEKIND(EXPAND_PARTICIPATES_IN_CC)
-#undef EXPAND_PARTICIPATES_IN_CC
+JS_FOR_EACH_TRACEKIND(EXPAND_TRACEKIND_DEF)
+#undef EXPAND_TRACEKIND_DEF
 
 }  // namespace
 
-#ifdef DEBUG
-
-struct ParticipatesInCCFunctor {
+struct TraceKindCanBeGrayFunctor {
   template <typename T>
   bool operator()() {
-    return TypeParticipatesInCC<T>::value;
+    return TraceKindCanBeGray<T>::value;
   }
 };
 
-static bool TraceKindParticipatesInCC(JS::TraceKind kind) {
-  return DispatchTraceKindTyped(ParticipatesInCCFunctor(), kind);
+static bool TraceKindCanBeMarkedGray(JS::TraceKind kind) {
+  return DispatchTraceKindTyped(TraceKindCanBeGrayFunctor(), kind);
 }
 
-#endif  // DEBUG
-
 template <typename T>
 bool js::GCMarker::mark(T* thing) {
   if (IsInsideNursery(thing)) {
     return false;
   }
   AssertShouldMarkInZone(thing);
   TenuredCell* cell = TenuredCell::fromPointer(thing);
 
   MarkColor color =
-      TypeParticipatesInCC<T>::value ? markColor() : MarkColor::Black;
+      TraceKindCanBeGray<T>::value ? markColor() : MarkColor::Black;
   markCount++;
   return cell->markIfUnmarked(color);
 }
 
 /*** Inline, Eager GC Marking ***********************************************/
 
 // Each of the eager, inline marking paths is directly preceeded by the
 // out-of-line, generic tracing code for comparison. Both paths must end up
@@ -2497,17 +2493,17 @@ void GCMarker::delayMarkingChildren(Cell
   if (!arena->hasDelayedMarking(color)) {
     arena->setHasDelayedMarking(color, true);
     delayedMarkingWorkAdded = true;
   }
 }
 
 void GCMarker::markDelayedChildren(Arena* arena, MarkColor color) {
   JS::TraceKind kind = MapAllocToTraceKind(arena->getAllocKind());
-  MOZ_ASSERT_IF(color == MarkColor::Gray, TraceKindParticipatesInCC(kind));
+  MOZ_ASSERT_IF(color == MarkColor::Gray, TraceKindCanBeMarkedGray(kind));
 
   AutoSetMarkColor setColor(*this, color);
   for (ArenaCellIterUnderGC i(arena); !i.done(); i.next()) {
     TenuredCell* t = i.getCell();
     if ((color == MarkColor::Gray && t->isMarkedGray()) ||
         (color == MarkColor::Black && t->isMarkedBlack())) {
       js::TraceChildren(this, t, kind);
     }
@@ -3176,17 +3172,17 @@ size_t js::TenuringTracer::moveStringToT
 
   return size;
 }
 
 /*** IsMarked / IsAboutToBeFinalized ****************************************/
 
 template <typename T>
 static inline void CheckIsMarkedThing(T* thingp) {
-#define IS_SAME_TYPE_OR(name, type, _) mozilla::IsSame<type*, T>::value ||
+#define IS_SAME_TYPE_OR(name, type, _, _1) mozilla::IsSame<type*, T>::value ||
   static_assert(JS_FOR_EACH_TRACEKIND(IS_SAME_TYPE_OR) false,
                 "Only the base cell layout types are allowed into "
                 "marking/tracing internals");
 #undef IS_SAME_TYPE_OR
 
 #ifdef DEBUG
   MOZ_ASSERT(thingp);
   MOZ_ASSERT(*thingp);
@@ -3356,17 +3352,17 @@ FOR_EACH_PUBLIC_GC_POINTER_TYPE(INSTANTI
 FOR_EACH_PUBLIC_TAGGED_GC_POINTER_TYPE(
     INSTANTIATE_ALL_VALID_HEAP_TRACE_FUNCTIONS)
 
 #define INSTANTIATE_INTERNAL_MARKING_FUNCTIONS(type)               \
   template bool IsMarkedInternal(JSRuntime* rt, type* thing);      \
   template bool IsMarkedBlackInternal(JSRuntime* rt, type* thing); \
   template bool IsAboutToBeFinalizedInternal(type* thingp);
 
-#define INSTANTIATE_INTERNAL_MARKING_FUNCTIONS_FROM_TRACEKIND(_1, type, _2) \
+#define INSTANTIATE_INTERNAL_MARKING_FUNCTIONS_FROM_TRACEKIND(_1, type, _2, _3) \
   INSTANTIATE_INTERNAL_MARKING_FUNCTIONS(type*)
 
 JS_FOR_EACH_TRACEKIND(INSTANTIATE_INTERNAL_MARKING_FUNCTIONS_FROM_TRACEKIND)
 FOR_EACH_PUBLIC_TAGGED_GC_POINTER_TYPE(INSTANTIATE_INTERNAL_MARKING_FUNCTIONS)
 
 #undef INSTANTIATE_INTERNAL_MARKING_FUNCTIONS_FROM_TRACEKIND
 #undef INSTANTIATE_INTERNAL_MARKING_FUNCTIONS
 
@@ -3440,34 +3436,23 @@ class UnmarkGrayTracer : public JS::Call
 
   void onChild(const JS::GCCellPtr& thing) override;
 
 #ifdef DEBUG
   TracerKind getTracerKind() const override { return TracerKind::UnmarkGray; }
 #endif
 };
 
-static bool IsCCTraceKindInternal(JS::TraceKind kind) {
-  switch (kind) {
-#define EXPAND_IS_CC_TRACE_KIND(name, _, addToCCKind) \
-  case JS::TraceKind::name:                           \
-    return addToCCKind;
-    JS_FOR_EACH_TRACEKIND(EXPAND_IS_CC_TRACE_KIND)
-    default:
-      MOZ_CRASH("Unexpected trace kind");
-  }
-}
-
 void UnmarkGrayTracer::onChild(const JS::GCCellPtr& thing) {
   Cell* cell = thing.asCell();
 
   // Cells in the nursery cannot be gray, and nor can certain kinds of tenured
   // cells. These must necessarily point only to black edges.
   if (!cell->isTenured() ||
-      !IsCCTraceKindInternal(cell->asTenured().getTraceKind())) {
+      !TraceKindCanBeMarkedGray(cell->asTenured().getTraceKind())) {
 #ifdef DEBUG
     MOZ_ASSERT(!cell->isMarkedGray());
     AssertNonGrayTracer nongray(runtime());
     TraceChildren(&nongray, cell, thing.kind());
 #endif
     return;
   }
 
--- a/js/src/gc/Policy.h
+++ b/js/src/gc/Policy.h
@@ -16,17 +16,17 @@
 
 namespace js {
 
 // Define the GCPolicy for all internal pointers.
 template <typename T>
 struct InternalGCPointerPolicy : public JS::GCPointerPolicy<T> {
   using Type = typename mozilla::RemovePointer<T>::Type;
 
-#define IS_BASE_OF_OR(_1, BaseType, _2) \
+#define IS_BASE_OF_OR(_1, BaseType, _2, _3) \
   mozilla::IsBaseOf<BaseType, Type>::value ||
   static_assert(
       JS_FOR_EACH_TRACEKIND(IS_BASE_OF_OR) false,
       "InternalGCPointerPolicy must only be used for GC thing pointers");
 #undef IS_BASE_OF_OR
 
   static void preBarrier(T v) {
     if (v) {
--- a/js/src/gc/RootMarking.cpp
+++ b/js/src/gc/RootMarking.cpp
@@ -68,17 +68,17 @@ static inline void TraceExactStackRootLi
     T* addr = reinterpret_cast<JS::Rooted<T>*>(rooter)->address();
     TraceStackOrPersistentRoot(trc, addr, name);
     rooter = rooter->previous();
   }
 }
 
 static inline void TraceStackRoots(JSTracer* trc,
                                    JS::RootedListHeads& stackRoots) {
-#define TRACE_ROOTS(name, type, _)                                    \
+#define TRACE_ROOTS(name, type, _, _1)                                 \
   TraceExactStackRootList<type*>(trc, stackRoots[JS::RootKind::name], \
                                  "exact-" #name);
   JS_FOR_EACH_TRACEKIND(TRACE_ROOTS)
 #undef TRACE_ROOTS
   TraceExactStackRootList<jsid>(trc, stackRoots[JS::RootKind::Id], "exact-id");
   TraceExactStackRootList<Value>(trc, stackRoots[JS::RootKind::Value],
                                  "exact-value");
 
@@ -103,17 +103,17 @@ static inline void TracePersistentRooted
     const char* name) {
   for (PersistentRooted<void*>* r : list) {
     TraceStackOrPersistentRoot(
         trc, reinterpret_cast<PersistentRooted<T>*>(r)->address(), name);
   }
 }
 
 void JSRuntime::tracePersistentRoots(JSTracer* trc) {
-#define TRACE_ROOTS(name, type, _)                                           \
+#define TRACE_ROOTS(name, type, _, _1)                                        \
   TracePersistentRootedList<type*>(trc, heapRoots.ref()[JS::RootKind::name], \
                                    "persistent-" #name);
   JS_FOR_EACH_TRACEKIND(TRACE_ROOTS)
 #undef TRACE_ROOTS
   TracePersistentRootedList<jsid>(trc, heapRoots.ref()[JS::RootKind::Id],
                                   "persistent-id");
   TracePersistentRootedList<Value>(trc, heapRoots.ref()[JS::RootKind::Value],
                                    "persistent-value");
@@ -135,17 +135,17 @@ static void FinishPersistentRootedChain(
   auto& list =
       reinterpret_cast<mozilla::LinkedList<PersistentRooted<T>>&>(listArg);
   while (!list.isEmpty()) {
     list.getFirst()->reset();
   }
 }
 
 void JSRuntime::finishPersistentRoots() {
-#define FINISH_ROOT_LIST(name, type, _) \
+#define FINISH_ROOT_LIST(name, type, _, _1) \
   FinishPersistentRootedChain<type*>(heapRoots.ref()[JS::RootKind::name]);
   JS_FOR_EACH_TRACEKIND(FINISH_ROOT_LIST)
 #undef FINISH_ROOT_LIST
   FinishPersistentRootedChain<jsid>(heapRoots.ref()[JS::RootKind::Id]);
   FinishPersistentRootedChain<Value>(heapRoots.ref()[JS::RootKind::Value]);
 
   // Note that we do not finalize the Traceable list as we do not know how to
   // safely clear members. We instead assert that none escape the RootLists.
--- a/js/src/gc/Tracer.cpp
+++ b/js/src/gc/Tracer.cpp
@@ -40,17 +40,17 @@ void CheckTracedThing(JSTracer* trc, T t
 
 template <typename T>
 T* DoCallback(JS::CallbackTracer* trc, T** thingp, const char* name) {
   CheckTracedThing(trc, *thingp);
   JS::AutoTracingName ctx(trc, name);
   trc->dispatchToOnEdge(thingp);
   return *thingp;
 }
-#define INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS(name, type, _) \
+#define INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS(name, type, _, _1) \
   template type* DoCallback<type>(JS::CallbackTracer*, type**, const char*);
 JS_FOR_EACH_TRACEKIND(INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS);
 #undef INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS
 
 template <typename T>
 T DoCallback(JS::CallbackTracer* trc, T* thingp, const char* name) {
   auto thing = MapGCThingTyped(*thingp, [trc, name](auto t) {
     return TaggedPtr<T>::wrap(DoCallback(trc, &t, name));
--- a/js/src/gc/Tracer.h
+++ b/js/src/gc/Tracer.h
@@ -50,17 +50,17 @@ namespace js {
 //     this point.
 
 namespace gc {
 
 // Map from all trace kinds to the base GC type.
 template <JS::TraceKind kind>
 struct MapTraceKindToType {};
 
-#define DEFINE_TRACE_KIND_MAP(name, type, _)       \
+#define DEFINE_TRACE_KIND_MAP(name, type, _, _1)   \
   template <>                                      \
   struct MapTraceKindToType<JS::TraceKind::name> { \
     using Type = type;                             \
   };
 JS_FOR_EACH_TRACEKIND(DEFINE_TRACE_KIND_MAP);
 #undef DEFINE_TRACE_KIND_MAP
 
 // Map from a possibly-derived type to the base GC type.
--- a/js/src/gc/WeakMap-inl.h
+++ b/js/src/gc/WeakMap-inl.h
@@ -36,18 +36,21 @@ inline /* static */ JSObject* WeakMapBas
   return nullptr;
 }
 
 template <class K, class V>
 WeakMap<K, V>::WeakMap(JSContext* cx, JSObject* memOf)
     : Base(cx->zone()), WeakMapBase(memOf, cx->zone()) {
   using ElemType = typename K::ElementType;
   using NonPtrType = typename mozilla::RemovePointer<ElemType>::Type;
+
   // The object's TraceKind needs to be added to CC graph if this object is
-  // used as a WeakMap key. See the comments for IsCCTraceKind for details.
+  // used as a WeakMap key, otherwise the key is considered to be pointed from
+  // somewhere unknown, and results in leaking the subgraph which contains the
+  // key. See the comments in NoteWeakMapsTracer::trace for more details.
   static_assert(JS::IsCCTraceKind(NonPtrType::TraceKind),
                 "Object's TraceKind should be added to CC graph.");
 
   zone()->gcWeakMapList().insertFront(this);
   if (zone()->wasGCStarted()) {
     marked = true;
     markColor = gc::MarkColor::Black;
   }
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -5099,33 +5099,33 @@ bool jit::MakeLoopsContiguous(MIRGraph& 
     // the end of the loop, making the loop itself contiguous.
     MakeLoopContiguous(graph, header, numMarked);
   }
 
   return true;
 }
 
 MRootList::MRootList(TempAllocator& alloc) {
-#define INIT_VECTOR(name, _0, _1) roots_[JS::RootKind::name].emplace(alloc);
+#define INIT_VECTOR(name, _0, _1, _2) roots_[JS::RootKind::name].emplace(alloc);
   JS_FOR_EACH_TRACEKIND(INIT_VECTOR)
 #undef INIT_VECTOR
 }
 
 template <typename T>
 static void TraceVector(JSTracer* trc, const MRootList::RootVector& vector,
                         const char* name) {
   for (auto ptr : vector) {
     T ptrT = static_cast<T>(ptr);
     TraceManuallyBarrieredEdge(trc, &ptrT, name);
     MOZ_ASSERT(ptr == ptrT, "Shouldn't move without updating MIR pointers");
   }
 }
 
 void MRootList::trace(JSTracer* trc) {
-#define TRACE_ROOTS(name, type, _) \
+#define TRACE_ROOTS(name, type, _, _1) \
   TraceVector<type*>(trc, *roots_[JS::RootKind::name], "mir-root-" #name);
   JS_FOR_EACH_TRACEKIND(TRACE_ROOTS)
 #undef TRACE_ROOTS
 }
 
 MOZ_MUST_USE bool jit::CreateMIRRootList(IonBuilder& builder) {
   MOZ_ASSERT(!builder.info().isAnalysis());