From 6aeb7e75957d65fe1995d7462ed0319195c2e2c5 Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Thu, 21 Apr 2016 19:23:22 -0700 Subject: [PATCH] Bug 1266573 - Add the `JS::ubi::dumpPaths` debug utility; r=jimb MozReview-Commit-ID: Gx37kFnasVl --HG-- extra : rebase_source : b5ba6bf7853a4ab1753b168c0c304eace5739d5d --- js/public/UbiNodeShortestPaths.h | 13 +++++++++ js/src/vm/UbiNodeShortestPaths.cpp | 47 ++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/js/public/UbiNodeShortestPaths.h b/js/public/UbiNodeShortestPaths.h index 6f8ee8475de0..f4fda5aa35a0 100644 --- a/js/public/UbiNodeShortestPaths.h +++ b/js/public/UbiNodeShortestPaths.h @@ -330,6 +330,19 @@ struct JS_PUBLIC_API(ShortestPaths) } }; +#ifdef DEBUG +// A helper function to dump the first `maxNumPaths` shortest retaining paths to +// `node` from the GC roots. Useful when GC things you expect to have been +// reclaimed by the collector haven't been! +// +// Usage: +// +// JSObject* foo = ...; +// JS::ubi::dumpPaths(rt, JS::ubi::Node(foo)); +JS_PUBLIC_API(void) +dumpPaths(JSRuntime* rt, Node node, uint32_t maxNumPaths = 10); +#endif + } // namespace ubi } // namespace JS diff --git a/js/src/vm/UbiNodeShortestPaths.cpp b/js/src/vm/UbiNodeShortestPaths.cpp index 46308f606d06..14258b149b4f 100644 --- a/js/src/vm/UbiNodeShortestPaths.cpp +++ b/js/src/vm/UbiNodeShortestPaths.cpp @@ -6,6 +6,9 @@ #include "js/UbiNodeShortestPaths.h" +#include "mozilla/Maybe.h" +#include "mozilla/Move.h" + #include "jsstr.h" namespace JS { @@ -27,5 +30,49 @@ BackEdge::clone() const return mozilla::Move(clone); } +#ifdef DEBUG +JS_PUBLIC_API(void) +dumpPaths(JSRuntime* rt, Node node, uint32_t maxNumPaths /* = 10 */) +{ + mozilla::Maybe nogc; + + JS::ubi::RootList rootList(rt, nogc); + 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)); + MOZ_ASSERT(paths.isSome()); + + int i = 0; + ok = paths->forEachPath(node, [&](Path& path) { + fprintf(stderr, "Path %d:\n", i++); + for (auto backEdge : path) { + fprintf(stderr, " predecessor = %p\n", (void*) backEdge->predecessor().identifier()); + fprintf(stderr, " |\n"); + fprintf(stderr, " |\n"); + fprintf(stderr, " '"); + + const char16_t* name = backEdge->name().get(); + if (!name) + name = (const char16_t*) MOZ_UTF16(""); + auto len = js_strlen(name); + for (size_t i = 0; i < len; i++) + fprintf(stderr, "%c", char(name[i])); + fprintf(stderr, "'\n"); + + fprintf(stderr, " |\n"); + fprintf(stderr, " V\n"); + } + + fprintf(stderr, " target = %p\n\n\n", (void*) node.identifier()); + return true; + }); + MOZ_ASSERT(ok); +} +#endif + } // namespace ubi } // namespace JS