Bug 1286795 part 3 - Change UbiNode APIs to take JSContext instead of JSRuntime. r=fitzgen
authorJan de Mooij <jdemooij@mozilla.com>
Sat, 23 Jul 2016 19:52:25 +0200
changeset 306344 6a92c25165546ad34e2ffa1f5d63c1c13fcca2d3
parent 306343 8499aa209426a046dacbab3189d9e82bceff85c3
child 306345 beeb4bc99662b22a6c7224937e003d07976ea59f
push id79840
push userjandemooij@gmail.com
push dateSat, 23 Jul 2016 17:58:50 +0000
treeherdermozilla-inbound@64b87ac9b20b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfitzgen
bugs1286795
milestone50.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 1286795 part 3 - Change UbiNode APIs to take JSContext instead of JSRuntime. r=fitzgen
devtools/shared/heapsnapshot/DeserializedNode.cpp
devtools/shared/heapsnapshot/DeserializedNode.h
devtools/shared/heapsnapshot/HeapSnapshot.cpp
devtools/shared/heapsnapshot/tests/gtest/DeserializedNodeUbiNodes.cpp
devtools/shared/heapsnapshot/tests/gtest/DevTools.h
devtools/shared/heapsnapshot/tests/gtest/SerializesEdgeNames.cpp
js/public/UbiNode.h
js/public/UbiNodeBreadthFirst.h
js/public/UbiNodeDominatorTree.h
js/public/UbiNodePostOrder.h
js/public/UbiNodeShortestPaths.h
js/src/builtin/TestingFunctions.cpp
js/src/jsapi-tests/testUbiNode.cpp
js/src/vm/Debugger.cpp
js/src/vm/DebuggerMemory.cpp
js/src/vm/UbiNode.cpp
js/src/vm/UbiNodeShortestPaths.cpp
--- a/devtools/shared/heapsnapshot/DeserializedNode.cpp
+++ b/devtools/shared/heapsnapshot/DeserializedNode.cpp
@@ -116,17 +116,17 @@ Concrete<DeserializedNode>::allocationSt
   MOZ_ASSERT(ptr);
   // See above comment in DeserializedNode::getEdgeReferent about why this
   // const_cast is needed and safe.
   return JS::ubi::StackFrame(const_cast<DeserializedStackFrame*>(&*ptr));
 }
 
 
 js::UniquePtr<EdgeRange>
-Concrete<DeserializedNode>::edges(JSRuntime* rt, bool) const
+Concrete<DeserializedNode>::edges(JSContext* cx, bool) const
 {
   js::UniquePtr<DeserializedEdgeRange> range(js_new<DeserializedEdgeRange>(get()));
 
   if (!range)
     return nullptr;
 
   return js::UniquePtr<EdgeRange>(range.release());
 }
--- a/devtools/shared/heapsnapshot/DeserializedNode.h
+++ b/devtools/shared/heapsnapshot/DeserializedNode.h
@@ -265,17 +265,17 @@ public:
   const char* jsObjectClassName() const override { return get().jsObjectClassName; }
   const char* scriptFilename() const final { return get().scriptFilename; }
 
   bool hasAllocationStack() const override { return get().allocationStack.isSome(); }
   StackFrame allocationStack() const override;
 
   // We ignore the `bool wantNames` parameter because we can't control whether
   // the core dump was serialized with edge names or not.
-  js::UniquePtr<EdgeRange> edges(JSRuntime* rt, bool) const override;
+  js::UniquePtr<EdgeRange> edges(JSContext* cx, bool) const override;
 
   static const char16_t concreteTypeName[];
 };
 
 template<>
 class ConcreteStackFrame<DeserializedStackFrame> : public BaseStackFrame
 {
 protected:
--- a/devtools/shared/heapsnapshot/HeapSnapshot.cpp
+++ b/devtools/shared/heapsnapshot/HeapSnapshot.cpp
@@ -484,17 +484,17 @@ HeapSnapshot::TakeCensus(JSContext* cx, 
     return;
   }
 
   JS::ubi::CensusHandler handler(census, rootCount, GetCurrentThreadDebuggerMallocSizeOf());
 
   {
     JS::AutoCheckCannotGC nogc;
 
-    JS::ubi::CensusTraversal traversal(JS_GetRuntime(cx), handler, nogc);
+    JS::ubi::CensusTraversal traversal(cx, handler, nogc);
     if (NS_WARN_IF(!traversal.init())) {
       rv.Throw(NS_ERROR_OUT_OF_MEMORY);
       return;
     }
 
     if (NS_WARN_IF(!traversal.addStart(getRoot()))) {
       rv.Throw(NS_ERROR_OUT_OF_MEMORY);
       return;
@@ -551,20 +551,20 @@ HeapSnapshot::DescribeNode(JSContext* cx
 
 already_AddRefed<DominatorTree>
 HeapSnapshot::ComputeDominatorTree(ErrorResult& rv)
 {
   Maybe<JS::ubi::DominatorTree> maybeTree;
   {
     auto ccrt = CycleCollectedJSRuntime::Get();
     MOZ_ASSERT(ccrt);
-    auto rt = ccrt->Runtime();
-    MOZ_ASSERT(rt);
-    JS::AutoCheckCannotGC nogc(rt);
-    maybeTree = JS::ubi::DominatorTree::Create(rt, nogc, getRoot());
+    auto cx = ccrt->Context();
+    MOZ_ASSERT(cx);
+    JS::AutoCheckCannotGC nogc(JS_GetRuntime(cx));
+    maybeTree = JS::ubi::DominatorTree::Create(cx, nogc, getRoot());
   }
 
   if (NS_WARN_IF(maybeTree.isNothing())) {
     rv.Throw(NS_ERROR_OUT_OF_MEMORY);
     return nullptr;
   }
 
   return MakeAndAddRef<DominatorTree>(Move(*maybeTree), this, mParent);
@@ -616,22 +616,18 @@ HeapSnapshot::ComputeShortestPaths(JSCon
       return;
     }
   }
 
   // Walk the heap graph and find the shortest paths.
 
   Maybe<ShortestPaths> maybeShortestPaths;
   {
-    auto ccrt = CycleCollectedJSRuntime::Get();
-    MOZ_ASSERT(ccrt);
-    auto rt = ccrt->Runtime();
-    MOZ_ASSERT(rt);
-    JS::AutoCheckCannotGC nogc(rt);
-    maybeShortestPaths = ShortestPaths::Create(rt, nogc, maxNumPaths, *startNode,
+    JS::AutoCheckCannotGC nogc(JS_GetRuntime(cx));
+    maybeShortestPaths = ShortestPaths::Create(cx, nogc, maxNumPaths, *startNode,
                                                Move(targetsSet));
   }
 
   if (NS_WARN_IF(maybeShortestPaths.isNothing())) {
     rv.Throw(NS_ERROR_OUT_OF_MEMORY);
     return;
   }
 
@@ -1233,17 +1229,17 @@ public:
       return false;
     }
 
     mozilla::MallocSizeOf mallocSizeOf = dbg::GetDebuggerMallocSizeOf(cx);
     MOZ_ASSERT(mallocSizeOf);
     protobufNode.set_size(ubiNode.size(mallocSizeOf));
 
     if (includeEdges) {
-      auto edges = ubiNode.edges(JS_GetRuntime(cx), wantNames);
+      auto edges = ubiNode.edges(cx, wantNames);
       if (NS_WARN_IF(!edges))
         return false;
 
       for ( ; !edges->empty(); edges->popFront()) {
         ubi::Edge& ubiEdge = edges->front();
 
         protobuf::Edge* protobufEdge = protobufNode.add_edges();
         if (NS_WARN_IF(!protobufEdge)) {
@@ -1375,17 +1371,17 @@ WriteHeapGraph(JSContext* cx,
   if (NS_WARN_IF(!writer.writeNode(node, CoreDumpWriter::INCLUDE_EDGES))) {
     return false;
   }
 
   // Walk the heap graph starting from the given node and serialize it into the
   // core dump.
 
   HeapSnapshotHandler handler(writer, compartments);
-  HeapSnapshotHandler::Traversal traversal(JS_GetRuntime(cx), handler, noGC);
+  HeapSnapshotHandler::Traversal traversal(cx, handler, noGC);
   if (!traversal.init())
     return false;
   traversal.wantNames = wantNames;
 
   bool ok = traversal.addStartVisited(node) &&
             traversal.traverse();
 
   if (ok) {
@@ -1540,17 +1536,17 @@ ThreadSafeChromeUtils::SaveHeapSnapshot(
   StreamWriter writer(cx, gzipStream, wantNames);
   if (NS_WARN_IF(!writer.init())) {
     rv.Throw(NS_ERROR_OUT_OF_MEMORY);
     return;
   }
 
   {
     Maybe<AutoCheckCannotGC> maybeNoGC;
-    ubi::RootList rootList(JS_GetRuntime(cx), maybeNoGC, wantNames);
+    ubi::RootList rootList(cx, maybeNoGC, wantNames);
     if (!EstablishBoundaries(cx, rv, boundaries, rootList, compartments))
       return;
 
     MOZ_ASSERT(maybeNoGC.isSome());
     ubi::Node roots(&rootList);
 
     // Serialize the initial heap snapshot metadata to the core dump.
     if (!writer.writeMetadata(PR_Now()) ||
--- a/devtools/shared/heapsnapshot/tests/gtest/DeserializedNodeUbiNodes.cpp
+++ b/devtools/shared/heapsnapshot/tests/gtest/DeserializedNodeUbiNodes.cpp
@@ -85,16 +85,16 @@ DEF_TEST(DeserializedNodeUbiNodes, {
                                                                    nullptr,
                                                                    30));
     DeserializedEdge edge3(referent3->id);
     mocked.addEdge(Move(edge3));
     EXPECT_CALL(mocked, getEdgeReferent(EdgeTo(referent3->id)))
       .Times(1)
       .WillOnce(Return(JS::ubi::Node(referent3.get())));
 
-    auto range = ubi.edges(rt);
+    auto range = ubi.edges(cx);
     ASSERT_TRUE(!!range);
 
     for ( ; !range->empty(); range->popFront()) {
       // Nothing to do here. This loop ensures that we get each edge referent
       // that we expect above.
     }
   });
--- a/devtools/shared/heapsnapshot/tests/gtest/DevTools.h
+++ b/devtools/shared/heapsnapshot/tests/gtest/DevTools.h
@@ -153,17 +153,17 @@ namespace ubi {
 
 template<>
 class Concrete<FakeNode> : public Base
 {
   const char16_t* typeName() const override {
     return concreteTypeName;
   }
 
-  js::UniquePtr<EdgeRange> edges(JSRuntime*, bool) const override {
+  js::UniquePtr<EdgeRange> edges(JSContext*, bool) const override {
     return js::UniquePtr<EdgeRange>(js_new<PreComputedEdgeRange>(get().edges));
   }
 
   Size size(mozilla::MallocSizeOf) const override {
     return get().size;
   }
 
   JS::Zone* zone() const override {
@@ -204,32 +204,32 @@ void AddEdge(FakeNode& node, FakeNode& r
 
 // Custom GMock Matchers
 
 // Use the testing namespace to avoid static analysis failures in the gmock
 // matcher classes that get generated from MATCHER_P macros.
 namespace testing {
 
 // Ensure that given node has the expected number of edges.
-MATCHER_P2(EdgesLength, rt, expectedLength, "") {
-  auto edges = arg.edges(rt);
+MATCHER_P2(EdgesLength, cx, expectedLength, "") {
+  auto edges = arg.edges(cx);
   if (!edges)
     return false;
 
   int actualLength = 0;
   for ( ; !edges->empty(); edges->popFront())
     actualLength++;
 
   return Matcher<int>(Eq(expectedLength))
     .MatchAndExplain(actualLength, result_listener);
 }
 
 // Get the nth edge and match it with the given matcher.
-MATCHER_P3(Edge, rt, n, matcher, "") {
-  auto edges = arg.edges(rt);
+MATCHER_P3(Edge, cx, n, matcher, "") {
+  auto edges = arg.edges(cx);
   if (!edges)
     return false;
 
   int i = 0;
   for ( ; !edges->empty(); edges->popFront()) {
     if (i == n) {
       return Matcher<const JS::ubi::Edge&>(matcher)
         .MatchAndExplain(edges->front(), result_listener);
--- a/devtools/shared/heapsnapshot/tests/gtest/SerializesEdgeNames.cpp
+++ b/devtools/shared/heapsnapshot/tests/gtest/SerializesEdgeNames.cpp
@@ -23,22 +23,22 @@ DEF_TEST(SerializesEdgeNames, {
     AddEdge(node, referent, emptyStr);
     AddEdge(node, referent, nullptr);
 
     ::testing::NiceMock<MockWriter> writer;
 
     // Should get the node with edges once.
     EXPECT_CALL(
       writer,
-      writeNode(AllOf(EdgesLength(rt, 3),
-                      Edge(rt, 0, Field(&JS::ubi::Edge::name,
+      writeNode(AllOf(EdgesLength(cx, 3),
+                      Edge(cx, 0, Field(&JS::ubi::Edge::name,
                                         UniqueUTF16StrEq(edgeName))),
-                      Edge(rt, 1, Field(&JS::ubi::Edge::name,
+                      Edge(cx, 1, Field(&JS::ubi::Edge::name,
                                         UniqueUTF16StrEq(emptyStr))),
-                      Edge(rt, 2, Field(&JS::ubi::Edge::name,
+                      Edge(cx, 2, Field(&JS::ubi::Edge::name,
                                         UniqueIsNull()))),
                 _)
     )
       .Times(1)
       .WillOnce(Return(true));
 
     // Should get the referent node that doesn't have any edges once.
     ExpectWriteNode(writer, referent);
--- a/js/public/UbiNode.h
+++ b/js/public/UbiNode.h
@@ -66,17 +66,17 @@
 // ubi::Node values require no supporting data structures, making them
 // feasible for use in memory-constrained devices --- ideally, the memory
 // requirements of the algorithm which uses them will be the limiting factor,
 // not the demands of ubi::Node itself.
 //
 // One can construct a ubi::Node value given a pointer to a type that ubi::Node
 // supports. In the other direction, one can convert a ubi::Node back to a
 // pointer; these downcasts are checked dynamically. In particular, one can
-// convert a 'JSRuntime*' to a ubi::Node, yielding a node with an outgoing edge
+// convert a 'JSContext*' to a ubi::Node, yielding a node with an outgoing edge
 // for every root registered with the runtime; starting from this, one can walk
 // the entire heap. (Of course, one could also start traversal at any other kind
 // of type to which one has a pointer.)
 //
 //
 // Extending ubi::Node To Handle Your Embedding's Types
 //
 // To add support for a new ubi::Node referent type R, you must define a
@@ -586,17 +586,17 @@ class Base {
     using Size = uint64_t;
     virtual Size size(mozilla::MallocSizeOf mallocSizeof) const { return 1; }
 
     // Return an EdgeRange that initially contains all the referent's outgoing
     // edges. The caller takes ownership of the EdgeRange.
     //
     // If wantNames is true, compute names for edges. Doing so can be expensive
     // in time and memory.
-    virtual js::UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames) const = 0;
+    virtual js::UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const = 0;
 
     // Return the Zone to which this node's referent belongs, or nullptr if the
     // referent is not of a type allocated in SpiderMonkey Zones.
     virtual JS::Zone* zone() const { return nullptr; }
 
     // Return the compartment for this node. Some ubi::Node referents are not
     // associated with JSCompartments, such as JSStrings (which are associated
     // with Zones). When the referent is not associated with a compartment,
@@ -787,18 +787,18 @@ class Node {
     Size size(mozilla::MallocSizeOf mallocSizeof) const {
         auto size =  base()->size(mallocSizeof);
         MOZ_ASSERT(size > 0,
                    "C++ does not have zero-sized types! Choose 1 if you just need a "
                    "conservative default.");
         return size;
     }
 
-    js::UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames = true) const {
-        return base()->edges(rt, wantNames);
+    js::UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames = true) const {
+        return base()->edges(cx, wantNames);
     }
 
     bool hasAllocationStack() const { return base()->hasAllocationStack(); }
     StackFrame allocationStack() const {
         return base()->allocationStack();
     }
 
     using Id = Base::Id;
@@ -953,36 +953,36 @@ class PreComputedEdgeRange : public Edge
 // has been created, GC must not occur, as the referent ubi::Nodes are not
 // stable across GC. The init calls emplace on |noGC|'s AutoCheckCannotGC, whose
 // lifetime must extend at least as long as the RootList itself.
 //
 // Example usage:
 //
 //    {
 //        mozilla::Maybe<JS::AutoCheckCannotGC> maybeNoGC;
-//        JS::ubi::RootList rootList(rt, maybeNoGC);
+//        JS::ubi::RootList rootList(cx, maybeNoGC);
 //        if (!rootList.init())
 //            return false;
 //
 //        // The AutoCheckCannotGC is guaranteed to exist if init returned true.
 //        MOZ_ASSERT(maybeNoGC.isSome());
 //
 //        JS::ubi::Node root(&rootList);
 //
 //        ...
 //    }
 class MOZ_STACK_CLASS RootList {
     Maybe<AutoCheckCannotGC>& noGC;
 
   public:
-    JSRuntime* rt;
+    JSContext* cx;
     EdgeVector edges;
     bool       wantNames;
 
-    RootList(JSRuntime* rt, Maybe<AutoCheckCannotGC>& noGC, bool wantNames = false);
+    RootList(JSContext* cx, Maybe<AutoCheckCannotGC>& noGC, bool wantNames = false);
 
     // Find all GC roots.
     MOZ_MUST_USE bool init();
     // Find only GC roots in the provided set of |JSCompartment|s.
     MOZ_MUST_USE bool init(CompartmentSet& debuggees);
     // Find only GC roots in the given Debugger object's set of debuggee
     // compartments.
     MOZ_MUST_USE bool init(HandleObject debuggees);
@@ -1004,27 +1004,27 @@ template<>
 class Concrete<RootList> : public Base {
   protected:
     explicit Concrete(RootList* ptr) : Base(ptr) { }
     RootList& get() const { return *static_cast<RootList*>(ptr); }
 
   public:
     static void construct(void* storage, RootList* ptr) { new (storage) Concrete(ptr); }
 
-    js::UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames) const override;
+    js::UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const override;
 
     const char16_t* typeName() const override { return concreteTypeName; }
     static const char16_t concreteTypeName[];
 };
 
 // A reusable ubi::Concrete specialization base class for types supported by
 // JS::TraceChildren.
 template<typename Referent>
 class TracerConcrete : public Base {
-    js::UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames) const override;
+    js::UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const override;
     JS::Zone* zone() const override;
 
   protected:
     explicit TracerConcrete(Referent* ptr) : Base(ptr) { }
     Referent& get() const { return *static_cast<Referent*>(ptr); }
 };
 
 // For JS::TraceChildren-based types that have a 'compartment' method.
@@ -1113,17 +1113,17 @@ class Concrete<JSString> : TracerConcret
     static const char16_t concreteTypeName[];
 };
 
 // The ubi::Node null pointer. Any attempt to operate on a null ubi::Node asserts.
 template<>
 class Concrete<void> : public Base {
     const char16_t* typeName() const override;
     Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
-    js::UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames) const override;
+    js::UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const override;
     JS::Zone* zone() const override;
     JSCompartment* compartment() const override;
     CoarseType coarseType() const final;
 
     explicit Concrete(void* ptr) : Base(ptr) { }
 
   public:
     static void construct(void* storage, void* ptr) { new (storage) Concrete(ptr); }
--- a/js/public/UbiNodeBreadthFirst.h
+++ b/js/public/UbiNodeBreadthFirst.h
@@ -78,18 +78,18 @@ template<typename Handler>
 struct BreadthFirst {
 
     // Construct a breadth-first traversal object that reports the nodes it
     // reaches to |handler|. The traversal asserts that no GC happens in its
     // runtime during its lifetime.
     //
     // We do nothing with noGC, other than require it to exist, with a lifetime
     // that encloses our own.
-    BreadthFirst(JSRuntime* rt, Handler& handler, const JS::AutoCheckCannotGC& noGC)
-      : wantNames(true), rt(rt), visited(), handler(handler), pending(),
+    BreadthFirst(JSContext* cx, Handler& handler, const JS::AutoCheckCannotGC& noGC)
+      : wantNames(true), cx(cx), visited(), handler(handler), pending(),
         traversalBegun(false), stopRequested(false), abandonRequested(false)
     { }
 
     // Initialize this traversal object. Return false on OOM.
     bool init() { return visited.init(); }
 
     // Add |node| as a starting point for the traversal. You may add
     // as many starting points as you like. Return false on OOM.
@@ -121,17 +121,17 @@ struct BreadthFirst {
         traversalBegun = true;
 
         // While there are pending nodes, visit them.
         while (!pending.empty()) {
             Node origin = pending.front();
             pending.popFront();
 
             // Get a range containing all origin's outgoing edges.
-            auto range = origin.edges(rt, wantNames);
+            auto range = origin.edges(cx, wantNames);
             if (!range)
                 return false;
 
             // Traverse each edge.
             for (; !range->empty(); range->popFront()) {
                 MOZ_ASSERT(!stopRequested);
 
                 Edge& edge = range->front();
@@ -176,18 +176,18 @@ struct BreadthFirst {
     // error.
     void stop() { stopRequested = true; }
 
     // Request that the current edge's referent's outgoing edges not be
     // traversed. This must be called the first time that referent is reached.
     // Other edges *to* that referent will still be traversed.
     void abandonReferent() { abandonRequested = true; }
 
-    // The runtime with which we were constructed.
-    JSRuntime* rt;
+    // The context with which we were constructed.
+    JSContext* cx;
 
     // A map associating each node N that we have reached with a
     // Handler::NodeData, for |handler|'s use. This is public, so that
     // |handler| can access it to see the traversal thus far.
     using NodeMap = js::HashMap<Node, typename Handler::NodeData, js::DefaultHasher<Node>,
                                 js::SystemAllocPolicy>;
     NodeMap visited;
 
--- a/js/public/UbiNodeDominatorTree.h
+++ b/js/public/UbiNodeDominatorTree.h
@@ -318,17 +318,17 @@ class JS_PUBLIC_API(DominatorTree)
             else if (finger2 < finger1)
                 finger2 = doms[finger2];
         }
         return finger1;
     }
 
     // Do the post order traversal of the heap graph and populate our
     // predecessor sets.
-    static MOZ_MUST_USE bool doTraversal(JSRuntime* rt, AutoCheckCannotGC& noGC, const Node& root,
+    static MOZ_MUST_USE bool doTraversal(JSContext* cx, AutoCheckCannotGC& noGC, const Node& root,
                                          JS::ubi::Vector<Node>& postOrder,
                                          PredecessorSets& predecessorSets) {
         uint32_t nodeCount = 0;
         auto onNode = [&](const Node& node) {
             nodeCount++;
             if (MOZ_UNLIKELY(nodeCount == UINT32_MAX))
                 return false;
             return postOrder.append(node);
@@ -344,17 +344,17 @@ class JS_PUBLIC_API(DominatorTree)
                 {
                     return false;
                 }
             }
             MOZ_ASSERT(p && p->value());
             return p->value()->put(origin);
         };
 
-        PostOrder traversal(rt, noGC);
+        PostOrder traversal(cx, noGC);
         return traversal.init() &&
                traversal.addStart(root) &&
                traversal.traverse(onNode, onEdge);
     }
 
     // Populates the given `map` with an entry for each node to its index in
     // `postOrder`.
     static MOZ_MUST_USE bool mapNodesToTheirIndices(JS::ubi::Vector<Node>& postOrder,
@@ -508,20 +508,20 @@ class JS_PUBLIC_API(DominatorTree)
      * `DominatorTree` as if it were backed by the live heap graph and trust
      * that embedders with knowledge of the graph's implementation will do the
      * Right Thing.
      *
      * Returns `mozilla::Nothing()` on OOM failure. It is the caller's
      * responsibility to handle and report the OOM.
      */
     static mozilla::Maybe<DominatorTree>
-    Create(JSRuntime* rt, AutoCheckCannotGC& noGC, const Node& root) {
+    Create(JSContext* cx, AutoCheckCannotGC& noGC, const Node& root) {
         JS::ubi::Vector<Node> postOrder;
         PredecessorSets predecessorSets;
-        if (!predecessorSets.init() || !doTraversal(rt, noGC, root, postOrder, predecessorSets))
+        if (!predecessorSets.init() || !doTraversal(cx, noGC, root, postOrder, predecessorSets))
             return mozilla::Nothing();
 
         MOZ_ASSERT(postOrder.length() < UINT32_MAX);
         uint32_t length = postOrder.length();
         MOZ_ASSERT(postOrder[length - 1] == root);
 
         // From here on out we wish to avoid hash table lookups, and we use
         // indices into `postOrder` instead of actual nodes wherever
--- a/js/public/UbiNodePostOrder.h
+++ b/js/public/UbiNodePostOrder.h
@@ -78,17 +78,17 @@ struct PostOrder {
             new (this) OriginAndEdges(mozilla::Move(rhs));
             return *this;
         }
     };
 
     using Stack = js::Vector<OriginAndEdges, 256, js::SystemAllocPolicy>;
     using Set = js::HashSet<Node, js::DefaultHasher<Node>, js::SystemAllocPolicy>;
 
-    JSRuntime*               rt;
+    JSContext*               cx;
     Set                      seen;
     Stack                    stack;
 #ifdef DEBUG
     bool                     traversed;
 #endif
 
   private:
     MOZ_MUST_USE bool fillEdgesFromRange(EdgeVector& edges, js::UniquePtr<EdgeRange>& range) {
@@ -97,31 +97,31 @@ struct PostOrder {
             if (!edges.append(mozilla::Move(range->front())))
                 return false;
         }
         return true;
     }
 
     MOZ_MUST_USE bool pushForTraversing(const Node& node) {
         EdgeVector edges;
-        auto range = node.edges(rt, /* wantNames */ false);
+        auto range = node.edges(cx, /* wantNames */ false);
         return range &&
             fillEdgesFromRange(edges, range) &&
             stack.append(OriginAndEdges(node, mozilla::Move(edges)));
     }
 
 
   public:
     // Construct a post-order traversal object.
     //
     // The traversal asserts that no GC happens in its runtime during its
     // lifetime via the `AutoCheckCannotGC&` parameter. We do nothing with it,
     // other than require it to exist with a lifetime that encloses our own.
-    PostOrder(JSRuntime* rt, AutoCheckCannotGC&)
-      : rt(rt)
+    PostOrder(JSContext* cx, AutoCheckCannotGC&)
+      : cx(cx)
       , seen()
       , stack()
 #ifdef DEBUG
       , traversed(false)
 #endif
     { }
 
     // Initialize this traversal object. Return false on OOM.
--- a/js/public/UbiNodeShortestPaths.h
+++ b/js/public/UbiNodeShortestPaths.h
@@ -240,27 +240,27 @@ struct JS_PUBLIC_API(ShortestPaths)
      *   - For `JS::ubi::Node` graphs backed by some other offline structure
      *     provided by the embedder, the resulting `ShortestPaths`'s lifetime is
      *     bounded by that offline structure's lifetime.
      *
      * Returns `mozilla::Nothing()` on OOM failure. It is the caller's
      * responsibility to handle and report the OOM.
      */
     static mozilla::Maybe<ShortestPaths>
-    Create(JSRuntime* rt, AutoCheckCannotGC& noGC, uint32_t maxNumPaths, const Node& root, NodeSet&& targets) {
+    Create(JSContext* cx, AutoCheckCannotGC& noGC, uint32_t maxNumPaths, const Node& root, NodeSet&& targets) {
         MOZ_ASSERT(targets.count() > 0);
         MOZ_ASSERT(maxNumPaths > 0);
 
         size_t count = targets.count();
         ShortestPaths paths(maxNumPaths, root, mozilla::Move(targets));
         if (!paths.paths_.init(count))
             return mozilla::Nothing();
 
         Handler handler(paths);
-        Traversal traversal(rt, handler, noGC);
+        Traversal traversal(cx, handler, noGC);
         traversal.wantNames = true;
         if (!traversal.init() || !traversal.addStart(root) || !traversal.traverse())
             return mozilla::Nothing();
 
         // Take ownership of the back edges we created while traversing the
         // graph so that we can follow them from `paths_` and don't
         // use-after-free.
         paths.backEdges_ = mozilla::Move(traversal.visited);
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -2693,17 +2693,17 @@ FindPath(JSContext* cx, unsigned argc, V
     {
         // We can't tolerate the GC moving things around while we're searching
         // the heap. Check that nothing we do causes a GC.
         JS::AutoCheckCannotGC autoCannotGC;
 
         JS::ubi::Node start(args[0]), target(args[1]);
 
         heaptools::FindPathHandler handler(cx, start, target, &nodes, edges);
-        heaptools::FindPathHandler::Traversal traversal(cx->runtime(), handler, autoCannotGC);
+        heaptools::FindPathHandler::Traversal traversal(cx, handler, autoCannotGC);
         if (!traversal.init() || !traversal.addStart(start)) {
             ReportOutOfMemory(cx);
             return false;
         }
 
         if (!traversal.traverse()) {
             if (!cx->isExceptionPending())
                 ReportOutOfMemory(cx);
@@ -2840,17 +2840,17 @@ ShortestPaths(JSContext* cx, unsigned ar
             JS::ubi::Node node(val);
             if (!targets.put(node)) {
                 ReportOutOfMemory(cx);
                 return false;
             }
         }
 
         JS::ubi::Node root(args[0]);
-        auto maybeShortestPaths = JS::ubi::ShortestPaths::Create(cx->runtime(), noGC, maxNumPaths,
+        auto maybeShortestPaths = JS::ubi::ShortestPaths::Create(cx, noGC, maxNumPaths,
                                                                  root, mozilla::Move(targets));
         if (maybeShortestPaths.isNothing()) {
             ReportOutOfMemory(cx);
             return false;
         }
         auto& shortestPaths = *maybeShortestPaths;
 
         for (size_t i = 0; i < length; i++) {
--- a/js/src/jsapi-tests/testUbiNode.cpp
+++ b/js/src/jsapi-tests/testUbiNode.cpp
@@ -45,17 +45,17 @@ class Concrete<FakeNode> : public Base
 {
   protected:
     explicit Concrete(FakeNode* ptr) : Base(ptr) { }
     FakeNode& get() const { return *static_cast<FakeNode*>(ptr); }
 
   public:
     static void construct(void* storage, FakeNode* ptr) { new (storage) Concrete(ptr); }
 
-    UniquePtr<EdgeRange> edges(JSRuntime* rt, bool wantNames) const override {
+    UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const override {
         return UniquePtr<EdgeRange>(js_new<PreComputedEdgeRange>(get().edges));
     }
 
     Node::Size size(mozilla::MallocSizeOf) const override {
         return 1;
     }
 
     static const char16_t concreteTypeName[];
@@ -370,18 +370,18 @@ BEGIN_TEST(test_ubiPostOrder)
 
     js::Vector<char, 8, js::SystemAllocPolicy> visited;
     {
         // Do a PostOrder traversal, starting from r. Accumulate the names of
         // the nodes we visit in `visited`. Remove edges we traverse from
         // `expectedEdges` as we find them to ensure that we only find each edge
         // once.
 
-        JS::AutoCheckCannotGC nogc(rt);
-        JS::ubi::PostOrder traversal(rt, nogc);
+        JS::AutoCheckCannotGC nogc(cx);
+        JS::ubi::PostOrder traversal(cx, nogc);
         CHECK(traversal.init());
         CHECK(traversal.addStart(&r));
 
         auto onNode = [&](const JS::ubi::Node& node) {
             return visited.append(node.as<FakeNode>()->name);
         };
 
         auto onEdge = [&](const JS::ubi::Node& origin, const JS::ubi::Edge& edge) {
@@ -518,18 +518,18 @@ BEGIN_TEST(test_JS_ubi_DominatorTree)
     CHECK(i.addEdgeTo(k));
     CHECK(j.addEdgeTo(i));
     CHECK(k.addEdgeTo(r));
     CHECK(k.addEdgeTo(i));
     CHECK(l.addEdgeTo(h));
 
     mozilla::Maybe<JS::ubi::DominatorTree> maybeTree;
     {
-        JS::AutoCheckCannotGC noGC(rt);
-        maybeTree = JS::ubi::DominatorTree::Create(rt, noGC, &r);
+        JS::AutoCheckCannotGC noGC(cx);
+        maybeTree = JS::ubi::DominatorTree::Create(cx, noGC, &r);
     }
 
     CHECK(maybeTree.isSome());
     auto& tree = *maybeTree;
 
     // We return the null JS::ubi::Node for nodes that were not reachable in the
     // graph when computing the dominator tree.
     FakeNode m('m');
@@ -688,23 +688,23 @@ BEGIN_TEST(test_JS_ubi_ShortestPaths_no_
     FakeNode a('a');
     FakeNode b('b');
     FakeNode c('c');
     CHECK(a.addEdgeTo(c));
     CHECK(c.addEdgeTo(a));
 
     mozilla::Maybe<JS::ubi::ShortestPaths> maybeShortestPaths;
     {
-        JS::AutoCheckCannotGC noGC(rt);
+        JS::AutoCheckCannotGC noGC(cx);
 
         JS::ubi::NodeSet targets;
         CHECK(targets.init());
         CHECK(targets.put(&b));
 
-        maybeShortestPaths = JS::ubi::ShortestPaths::Create(rt, noGC, 10, &a,
+        maybeShortestPaths = JS::ubi::ShortestPaths::Create(cx, noGC, 10, &a,
                                                             mozilla::Move(targets));
     }
 
     CHECK(maybeShortestPaths);
     auto& paths = *maybeShortestPaths;
 
     size_t numPathsFound = 0;
     bool ok = paths.forEachPath(&b, [&](JS::ubi::Path& path) {
@@ -730,23 +730,23 @@ BEGIN_TEST(test_JS_ubi_ShortestPaths_one
     FakeNode b('b');
     FakeNode c('c');
     CHECK(a.addEdgeTo(c));
     CHECK(c.addEdgeTo(a));
     CHECK(c.addEdgeTo(b));
 
     mozilla::Maybe<JS::ubi::ShortestPaths> maybeShortestPaths;
     {
-        JS::AutoCheckCannotGC noGC(rt);
+        JS::AutoCheckCannotGC noGC(cx);
 
         JS::ubi::NodeSet targets;
         CHECK(targets.init());
         CHECK(targets.put(&b));
 
-        maybeShortestPaths = JS::ubi::ShortestPaths::Create(rt, noGC, 10, &a,
+        maybeShortestPaths = JS::ubi::ShortestPaths::Create(cx, noGC, 10, &a,
                                                             mozilla::Move(targets));
     }
 
     CHECK(maybeShortestPaths);
     auto& paths = *maybeShortestPaths;
 
     size_t numPathsFound = 0;
     bool ok = paths.forEachPath(&b, [&](JS::ubi::Path& path) {
@@ -797,23 +797,23 @@ BEGIN_TEST(test_JS_ubi_ShortestPaths_mul
     CHECK(a.addEdgeTo(d));
     CHECK(b.addEdgeTo(c));
     CHECK(c.addEdgeTo(f));
     CHECK(d.addEdgeTo(e));
     CHECK(e.addEdgeTo(f));
 
     mozilla::Maybe<JS::ubi::ShortestPaths> maybeShortestPaths;
     {
-        JS::AutoCheckCannotGC noGC(rt);
+        JS::AutoCheckCannotGC noGC(cx);
 
         JS::ubi::NodeSet targets;
         CHECK(targets.init());
         CHECK(targets.put(&f));
 
-        maybeShortestPaths = JS::ubi::ShortestPaths::Create(rt, noGC, 10, &a,
+        maybeShortestPaths = JS::ubi::ShortestPaths::Create(cx, noGC, 10, &a,
                                                             mozilla::Move(targets));
     }
 
     CHECK(maybeShortestPaths);
     auto& paths = *maybeShortestPaths;
 
     size_t numPathsFound = 0;
     bool ok = paths.forEachPath(&f, [&](JS::ubi::Path& path) {
@@ -889,23 +889,23 @@ BEGIN_TEST(test_JS_ubi_ShortestPaths_mor
     CHECK(a.addEdgeTo(d));
     CHECK(b.addEdgeTo(c));
     CHECK(c.addEdgeTo(f));
     CHECK(d.addEdgeTo(e));
     CHECK(e.addEdgeTo(f));
 
     mozilla::Maybe<JS::ubi::ShortestPaths> maybeShortestPaths;
     {
-        JS::AutoCheckCannotGC noGC(rt);
+        JS::AutoCheckCannotGC noGC(cx);
 
         JS::ubi::NodeSet targets;
         CHECK(targets.init());
         CHECK(targets.put(&f));
 
-        maybeShortestPaths = JS::ubi::ShortestPaths::Create(rt, noGC, 1, &a,
+        maybeShortestPaths = JS::ubi::ShortestPaths::Create(cx, noGC, 1, &a,
                                                             mozilla::Move(targets));
     }
 
     CHECK(maybeShortestPaths);
     auto& paths = *maybeShortestPaths;
 
     size_t numPathsFound = 0;
     bool ok = paths.forEachPath(&f, [&](JS::ubi::Path& path) {
@@ -939,23 +939,23 @@ BEGIN_TEST(test_JS_ubi_ShortestPaths_mul
     FakeNode a('a');
     FakeNode b('b');
     CHECK(a.addEdgeTo(b, u"x"));
     CHECK(a.addEdgeTo(b, u"y"));
     CHECK(a.addEdgeTo(b, u"z"));
 
     mozilla::Maybe<JS::ubi::ShortestPaths> maybeShortestPaths;
     {
-        JS::AutoCheckCannotGC noGC(rt);
+        JS::AutoCheckCannotGC noGC(cx);
 
         JS::ubi::NodeSet targets;
         CHECK(targets.init());
         CHECK(targets.put(&b));
 
-        maybeShortestPaths = JS::ubi::ShortestPaths::Create(rt, noGC, 10, &a,
+        maybeShortestPaths = JS::ubi::ShortestPaths::Create(cx, noGC, 10, &a,
                                                             mozilla::Move(targets));
     }
 
     CHECK(maybeShortestPaths);
     auto& paths = *maybeShortestPaths;
 
     size_t numPathsFound = 0;
     bool foundX = false;
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -4518,23 +4518,23 @@ class MOZ_STACK_CLASS Debugger::ObjectQu
 
         {
             /*
              * We can't tolerate the GC moving things around while we're
              * searching the heap. Check that nothing we do causes a GC.
              */
             Maybe<JS::AutoCheckCannotGC> maybeNoGC;
             RootedObject dbgObj(cx, dbg->object);
-            JS::ubi::RootList rootList(cx->runtime(), maybeNoGC);
+            JS::ubi::RootList rootList(cx, maybeNoGC);
             if (!rootList.init(dbgObj)) {
                 ReportOutOfMemory(cx);
                 return false;
             }
 
-            Traversal traversal(cx->runtime(), *this, maybeNoGC.ref());
+            Traversal traversal(cx, *this, maybeNoGC.ref());
             if (!traversal.init()) {
                 ReportOutOfMemory(cx);
                 return false;
             }
             traversal.wantNames = false;
 
             return traversal.addStart(JS::ubi::Node(&rootList)) &&
                    traversal.traverse();
--- a/js/src/vm/DebuggerMemory.cpp
+++ b/js/src/vm/DebuggerMemory.cpp
@@ -409,23 +409,23 @@ DebuggerMemory::takeCensus(JSContext* cx
     // Populate our target set of debuggee zones.
     for (WeakGlobalObjectSet::Range r = dbg->allDebuggees(); !r.empty(); r.popFront()) {
         if (!census.targetZones.put(r.front()->zone()))
             return false;
     }
 
     {
         Maybe<JS::AutoCheckCannotGC> maybeNoGC;
-        JS::ubi::RootList rootList(cx->runtime(), maybeNoGC);
+        JS::ubi::RootList rootList(cx, maybeNoGC);
         if (!rootList.init(dbgObj)) {
             ReportOutOfMemory(cx);
             return false;
         }
 
-        JS::ubi::CensusTraversal traversal(cx->runtime(), handler, maybeNoGC.ref());
+        JS::ubi::CensusTraversal traversal(cx, handler, maybeNoGC.ref());
         if (!traversal.init()) {
             ReportOutOfMemory(cx);
             return false;
         }
         traversal.wantNames = false;
 
         if (!traversal.addStart(JS::ubi::Node(&rootList)) ||
             !traversal.traverse())
--- a/js/src/vm/UbiNode.cpp
+++ b/js/src/vm/UbiNode.cpp
@@ -154,17 +154,17 @@ StackFrame::functionDisplayNameLength()
 
 // All operations on null ubi::Nodes crash.
 CoarseType Concrete<void>::coarseType() const      { MOZ_CRASH("null ubi::Node"); }
 const char16_t* Concrete<void>::typeName() const   { MOZ_CRASH("null ubi::Node"); }
 JS::Zone* Concrete<void>::zone() const             { MOZ_CRASH("null ubi::Node"); }
 JSCompartment* Concrete<void>::compartment() const { MOZ_CRASH("null ubi::Node"); }
 
 UniquePtr<EdgeRange>
-Concrete<void>::edges(JSRuntime*, bool) const {
+Concrete<void>::edges(JSContext*, bool) const {
     MOZ_CRASH("null ubi::Node");
 }
 
 Node::Size
 Concrete<void>::size(mozilla::MallocSizeOf mallocSizeof) const
 {
     MOZ_CRASH("null ubi::Node");
 }
@@ -309,34 +309,34 @@ template JS::Zone* TracerConcrete<js::La
 template JS::Zone* TracerConcrete<js::Shape>::zone() const;
 template JS::Zone* TracerConcrete<js::BaseShape>::zone() const;
 template JS::Zone* TracerConcrete<js::ObjectGroup>::zone() const;
 template JS::Zone* TracerConcrete<JS::Symbol>::zone() const;
 template JS::Zone* TracerConcrete<JSString>::zone() const;
 
 template<typename Referent>
 UniquePtr<EdgeRange>
-TracerConcrete<Referent>::edges(JSRuntime* rt, bool wantNames) const {
+TracerConcrete<Referent>::edges(JSContext* cx, bool wantNames) const {
     UniquePtr<SimpleEdgeRange, JS::DeletePolicy<SimpleEdgeRange>> range(js_new<SimpleEdgeRange>());
     if (!range)
         return nullptr;
 
-    if (!range->init(rt, ptr, JS::MapTypeToTraceKind<Referent>::kind, wantNames))
+    if (!range->init(cx, ptr, JS::MapTypeToTraceKind<Referent>::kind, wantNames))
         return nullptr;
 
     return UniquePtr<EdgeRange>(range.release());
 }
 
-template UniquePtr<EdgeRange> TracerConcrete<JSScript>::edges(JSRuntime* rt, bool wantNames) const;
-template UniquePtr<EdgeRange> TracerConcrete<js::LazyScript>::edges(JSRuntime* rt, bool wantNames) const;
-template UniquePtr<EdgeRange> TracerConcrete<js::Shape>::edges(JSRuntime* rt, bool wantNames) const;
-template UniquePtr<EdgeRange> TracerConcrete<js::BaseShape>::edges(JSRuntime* rt, bool wantNames) const;
-template UniquePtr<EdgeRange> TracerConcrete<js::ObjectGroup>::edges(JSRuntime* rt, bool wantNames) const;
-template UniquePtr<EdgeRange> TracerConcrete<JS::Symbol>::edges(JSRuntime* rt, bool wantNames) const;
-template UniquePtr<EdgeRange> TracerConcrete<JSString>::edges(JSRuntime* rt, bool wantNames) const;
+template UniquePtr<EdgeRange> TracerConcrete<JSScript>::edges(JSContext* cx, bool wantNames) const;
+template UniquePtr<EdgeRange> TracerConcrete<js::LazyScript>::edges(JSContext* cx, bool wantNames) const;
+template UniquePtr<EdgeRange> TracerConcrete<js::Shape>::edges(JSContext* cx, bool wantNames) const;
+template UniquePtr<EdgeRange> TracerConcrete<js::BaseShape>::edges(JSContext* cx, bool wantNames) const;
+template UniquePtr<EdgeRange> TracerConcrete<js::ObjectGroup>::edges(JSContext* cx, bool wantNames) const;
+template UniquePtr<EdgeRange> TracerConcrete<JS::Symbol>::edges(JSContext* cx, bool wantNames) const;
+template UniquePtr<EdgeRange> TracerConcrete<JSString>::edges(JSContext* cx, bool wantNames) const;
 
 template<typename Referent>
 JSCompartment*
 TracerConcreteWithCompartment<Referent>::compartment() const
 {
     return TracerBase::get().compartment();
 }
 
@@ -393,40 +393,40 @@ const char16_t Concrete<js::LazyScript>:
 const char16_t Concrete<js::jit::JitCode>::concreteTypeName[] = u"js::jit::JitCode";
 const char16_t Concrete<js::Shape>::concreteTypeName[] = u"js::Shape";
 const char16_t Concrete<js::BaseShape>::concreteTypeName[] = u"js::BaseShape";
 const char16_t Concrete<js::ObjectGroup>::concreteTypeName[] = u"js::ObjectGroup";
 
 namespace JS {
 namespace ubi {
 
-RootList::RootList(JSRuntime* rt, Maybe<AutoCheckCannotGC>& noGC, bool wantNames /* = false */)
+RootList::RootList(JSContext* cx, Maybe<AutoCheckCannotGC>& noGC, bool wantNames /* = false */)
   : noGC(noGC),
-    rt(rt),
+    cx(cx),
     edges(),
     wantNames(wantNames)
 { }
 
 
 bool
 RootList::init()
 {
-    EdgeVectorTracer tracer(rt, &edges, wantNames);
+    EdgeVectorTracer tracer(cx, &edges, wantNames);
     js::TraceRuntime(&tracer);
     if (!tracer.okay)
         return false;
-    noGC.emplace(rt);
+    noGC.emplace(cx);
     return true;
 }
 
 bool
 RootList::init(CompartmentSet& debuggees)
 {
     EdgeVector allRootEdges;
-    EdgeVectorTracer tracer(rt, &allRootEdges, wantNames);
+    EdgeVectorTracer tracer(cx, &allRootEdges, wantNames);
 
     ZoneSet debuggeeZones;
     if (!debuggeeZones.init())
         return false;
     for (auto range = debuggees.all(); !range.empty(); range.popFront()) {
         if (!debuggeeZones.put(range.front()->zone()))
             return false;
     }
@@ -448,17 +448,17 @@ RootList::init(CompartmentSet& debuggees
         Zone* zone = edge.referent.zone();
         if (zone && !debuggeeZones.has(zone))
             continue;
 
         if (!edges.append(mozilla::Move(edge)))
             return false;
     }
 
-    noGC.emplace(rt);
+    noGC.emplace(cx);
     return true;
 }
 
 bool
 RootList::init(HandleObject debuggees)
 {
     MOZ_ASSERT(debuggees && JS::dbg::IsDebugger(*debuggees));
     js::Debugger* dbg = js::Debugger::fromJSObject(debuggees.get());
@@ -501,15 +501,15 @@ RootList::addRoot(Node node, const char1
     }
 
     return edges.append(mozilla::Move(Edge(name.release(), node)));
 }
 
 const char16_t Concrete<RootList>::concreteTypeName[] = u"JS::ubi::RootList";
 
 UniquePtr<EdgeRange>
-Concrete<RootList>::edges(JSRuntime* rt, bool wantNames) const {
+Concrete<RootList>::edges(JSContext* cx, bool wantNames) const {
     MOZ_ASSERT_IF(wantNames, get().wantNames);
     return UniquePtr<EdgeRange>(js_new<PreComputedEdgeRange>(get().edges));
 }
 
 } // namespace ubi
 } // namespace JS
--- a/js/src/vm/UbiNodeShortestPaths.cpp
+++ b/js/src/vm/UbiNodeShortestPaths.cpp
@@ -40,28 +40,28 @@ dumpNode(const JS::ubi::Node& node)
     if (node.coarseType() == JS::ubi::CoarseType::Object) {
         if (const char* clsName = node.jsObjectClassName())
             fprintf(stderr, " [object %s]", clsName);
     }
     fputc('\n', stderr);
 }
 
 JS_PUBLIC_API(void)
-dumpPaths(JSRuntime* rt, Node node, uint32_t maxNumPaths /* = 10 */)
+dumpPaths(JSContext* cx, Node node, uint32_t maxNumPaths /* = 10 */)
 {
     mozilla::Maybe<AutoCheckCannotGC> nogc;
 
-    JS::ubi::RootList rootList(rt, nogc, true);
+    JS::ubi::RootList rootList(cx, nogc, true);
     MOZ_ASSERT(rootList.init());
 
     NodeSet targets;
     bool ok = targets.init() && targets.putNew(node);
     MOZ_ASSERT(ok);
 
-    auto paths = ShortestPaths::Create(rt, nogc.ref(), maxNumPaths, &rootList, mozilla::Move(targets));
+    auto paths = ShortestPaths::Create(cx, nogc.ref(), maxNumPaths, &rootList, mozilla::Move(targets));
     MOZ_ASSERT(paths.isSome());
 
     int i = 0;
     ok = paths->forEachPath(node, [&](Path& path) {
         fprintf(stderr, "Path %d:\n", i++);
         for (auto backEdge : path) {
             dumpNode(backEdge->predecessor());
             fprintf(stderr, "            |\n");