diff options
Diffstat (limited to 'js/src/gdb/mozilla/GCCellPtr.py')
-rw-r--r-- | js/src/gdb/mozilla/GCCellPtr.py | 121 |
1 files changed, 121 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..738d9b3e45 --- /dev/null +++ b/js/src/gdb/mozilla/GCCellPtr.py @@ -0,0 +1,121 @@ +# 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", + "ObjectGroup": "js::ObjectGroup", + "Null": "std::nullptr_t", + # Out-of-line types. + "BaseShape": "js::BaseShape", + "JitCode": "js::jit::JitCode", + "Script": "js::BaseScript", + "Scope": "js::Scope", + "RegExpShared": "js::RegExpShared", + } + + # Map from AllocKind to TraceKind for out-of-line types. + alloc_map = { + "BASE_SHAPE": "BaseShape", + "JITCODE": "JitCode", + "SCRIPT": "Script", + "SCOPE": "Scope", + "REGEXP_SHARED": "RegExpShared", + } + + 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) + ) |