summaryrefslogtreecommitdiffstats
path: root/js/src/gdb/mozilla/GCCellPtr.py
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/gdb/mozilla/GCCellPtr.py')
-rw-r--r--js/src/gdb/mozilla/GCCellPtr.py125
1 files changed, 125 insertions, 0 deletions
diff --git a/js/src/gdb/mozilla/GCCellPtr.py b/js/src/gdb/mozilla/GCCellPtr.py
new file mode 100644
index 0000000000..e42ecfa893
--- /dev/null
+++ b/js/src/gdb/mozilla/GCCellPtr.py
@@ -0,0 +1,125 @@
+# 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/.
+
+# Pretty-printers for GCCellPtr values.
+
+import gdb
+
+import mozilla.prettyprinters
+from mozilla.prettyprinters import pretty_printer
+
+# Forget any printers from previous loads of this module.
+mozilla.prettyprinters.clear_module_printers(__name__)
+
+# Cache information about the types for this objfile.
+
+
+class GCCellPtrTypeCache(object):
+ def __init__(self, cache):
+ self.TraceKind_t = gdb.lookup_type("JS::TraceKind")
+ self.AllocKind_t = gdb.lookup_type("js::gc::AllocKind")
+ self.Arena_t = gdb.lookup_type("js::gc::Arena")
+ self.Cell_t = gdb.lookup_type("js::gc::Cell")
+ self.TenuredCell_t = gdb.lookup_type("js::gc::TenuredCell")
+
+ trace_kinds = gdb.types.make_enum_dict(self.TraceKind_t)
+ alloc_kinds = gdb.types.make_enum_dict(self.AllocKind_t)
+
+ def trace_kind(k):
+ return trace_kinds["JS::TraceKind::" + k]
+
+ def alloc_kind(k):
+ return alloc_kinds["js::gc::AllocKind::" + k]
+
+ # Build a mapping from TraceKind enum values to the types they denote.
+ trace_map = {
+ # Inline types.
+ "Object": "JSObject",
+ "BigInt": "JS::BigInt",
+ "String": "JSString",
+ "Symbol": "JS::Symbol",
+ "Shape": "js::Shape",
+ "BaseShape": "js::BaseShape",
+ "Null": "std::nullptr_t",
+ # Out-of-line types.
+ "JitCode": "js::jit::JitCode",
+ "Script": "js::BaseScript",
+ "Scope": "js::Scope",
+ "RegExpShared": "js::RegExpShared",
+ "GetterSetter": "js::GetterSetter",
+ "PropMap": "js::PropMap",
+ }
+
+ # Map from AllocKind to TraceKind for out-of-line types.
+ alloc_map = {
+ "JITCODE": "JitCode",
+ "SCRIPT": "Script",
+ "SCOPE": "Scope",
+ "REGEXP_SHARED": "RegExpShared",
+ "GETTER_SETTER": "GetterSetter",
+ "COMPACT_PROP_MAP": "PropMap",
+ "NORMAL_PROP_MAP": "PropMap",
+ "DICT_PROP_MAP": "PropMap",
+ }
+
+ self.trace_kind_to_type = {
+ trace_kind(k): gdb.lookup_type(v) for k, v in trace_map.items()
+ }
+ self.alloc_kind_to_trace_kind = {
+ alloc_kind(k): trace_kind(v) for k, v in alloc_map.items()
+ }
+
+ self.Null = trace_kind("Null")
+ self.tracekind_mask = gdb.parse_and_eval("JS::OutOfLineTraceKindMask")
+ self.arena_mask = gdb.parse_and_eval("js::gc::ArenaMask")
+
+
+@pretty_printer("JS::GCCellPtr")
+class GCCellPtr(object):
+ def __init__(self, value, cache):
+ self.value = value
+ if not cache.mod_GCCellPtr:
+ cache.mod_GCCellPtr = GCCellPtrTypeCache(cache)
+ self.cache = cache
+
+ def to_string(self):
+ ptr = self.value["ptr"]
+ kind = ptr & self.cache.mod_GCCellPtr.tracekind_mask
+ if kind == self.cache.mod_GCCellPtr.Null:
+ return "JS::GCCellPtr(nullptr)"
+ if kind == self.cache.mod_GCCellPtr.tracekind_mask:
+ # Out-of-line trace kinds.
+ #
+ # Compute the underlying type for out-of-line kinds by
+ # reimplementing the GCCellPtr::outOfLineKind() method.
+ #
+ # The extra casts below are only present to make it easier to
+ # compare this code against the C++ implementation.
+
+ # GCCellPtr::asCell()
+ cell_ptr = ptr & ~self.cache.mod_GCCellPtr.tracekind_mask
+ cell = cell_ptr.reinterpret_cast(self.cache.mod_GCCellPtr.Cell_t.pointer())
+
+ # Cell::asTenured()
+ tenured = cell.cast(self.cache.mod_GCCellPtr.TenuredCell_t.pointer())
+
+ # TenuredCell::arena()
+ addr = int(tenured)
+ arena_ptr = addr & ~self.cache.mod_GCCellPtr.arena_mask
+ arena = arena_ptr.reinterpret_cast(
+ self.cache.mod_GCCellPtr.Arena_t.pointer()
+ )
+
+ # Arena::getAllocKind()
+ alloc_kind = arena["allocKind"].cast(self.cache.mod_GCCellPtr.AllocKind_t)
+ alloc_idx = int(
+ alloc_kind.cast(self.cache.mod_GCCellPtr.AllocKind_t.target())
+ )
+
+ # Map the AllocKind to a TraceKind.
+ kind = self.cache.mod_GCCellPtr.alloc_kind_to_trace_kind[alloc_idx]
+ type_name = self.cache.mod_GCCellPtr.trace_kind_to_type[int(kind)]
+ return "JS::GCCellPtr(({}*) {})".format(
+ type_name, ptr.cast(self.cache.void_ptr_t)
+ )