mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 15:25:52 +00:00
Bug 1621256: Update GCCellPtr gdb pretty printer and add support for out-of-line types. r=sfink
Differential Revision: https://phabricator.services.mozilla.com/D66216 --HG-- extra : source : e6218eafa1112c29badc2f988469b0ffc89b2c33
This commit is contained in:
parent
69a239d155
commit
5ad35aac9b
@ -12,31 +12,64 @@ 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 JS::TraceKind type for this objfile.
|
||||
# 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.
|
||||
e = gdb.types.make_enum_dict(self.TraceKind_t)
|
||||
kind_to_type = {}
|
||||
trace_map = {
|
||||
# Inline types.
|
||||
'Object': 'JSObject',
|
||||
'BigInt': 'JS::BigInt',
|
||||
'String': 'JSString',
|
||||
'Symbol': 'JS::Symbol',
|
||||
'Shape': 'js::Shape',
|
||||
'ObjectGroup': 'js::ObjectGroup',
|
||||
'Null': 'std::nullptr_t',
|
||||
|
||||
def kind(k, t):
|
||||
kind_to_type[e['JS::TraceKind::' + k]] = gdb.lookup_type(t)
|
||||
kind('Object', 'JSObject')
|
||||
kind('String', 'JSString')
|
||||
kind('Symbol', 'JS::Symbol')
|
||||
kind('Script', 'js::BaseScript')
|
||||
kind('Shape', 'js::Shape')
|
||||
kind('ObjectGroup', 'js::ObjectGroup')
|
||||
kind('BaseShape', 'js::BaseShape')
|
||||
kind('JitCode', 'js::jit::JitCode')
|
||||
self.kind_to_type = kind_to_type
|
||||
# Out-of-line types.
|
||||
'BaseShape': 'js::BaseShape',
|
||||
'JitCode': 'js::jit::JitCode',
|
||||
'Script': 'js::BaseScript',
|
||||
'Scope': 'js::Scope',
|
||||
'RegExpShared': 'js::RegExpShared',
|
||||
}
|
||||
|
||||
self.Null = e['JS::TraceKind::Null']
|
||||
self.mask = gdb.parse_and_eval('JS::OutOfLineTraceKindMask')
|
||||
# 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')
|
||||
@ -49,8 +82,35 @@ class GCCellPtr(object):
|
||||
|
||||
def to_string(self):
|
||||
ptr = self.value['ptr']
|
||||
kind = ptr & self.cache.mod_GCCellPtr.mask
|
||||
kind = ptr & self.cache.mod_GCCellPtr.tracekind_mask
|
||||
if kind == self.cache.mod_GCCellPtr.Null:
|
||||
return "JS::GCCellPtr(nullptr)"
|
||||
tipe = self.cache.mod_GCCellPtr.kind_to_type[int(kind)]
|
||||
return "JS::GCCellPtr(({}*) {})".format(tipe, ptr.cast(self.cache.void_ptr_t))
|
||||
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))
|
||||
|
@ -1,18 +1,57 @@
|
||||
#include "gdb-tests.h"
|
||||
|
||||
#include "mozilla/Unused.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
|
||||
#include "js/CompileOptions.h"
|
||||
#include "js/CompilationAndEvaluation.h"
|
||||
#include "js/HeapAPI.h"
|
||||
#include "js/RegExpFlags.h"
|
||||
#include "js/SourceText.h"
|
||||
#include "js/Symbol.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "vm/BigIntType.h"
|
||||
#include "vm/JSObject.h"
|
||||
#include "vm/ObjectGroup.h"
|
||||
#include "vm/RegExpObject.h"
|
||||
#include "vm/Shape.h"
|
||||
|
||||
#include "vm/JSObject-inl.h"
|
||||
|
||||
FRAGMENT(GCCellPtr, simple) {
|
||||
JS::Rooted<JSObject*> glob(cx, JS::CurrentGlobalOrNull(cx));
|
||||
JS::Rooted<JSString*> empty(cx, JS_NewStringCopyN(cx, nullptr, 0));
|
||||
JS::Rooted<JS::Symbol*> unique(cx, JS::NewSymbol(cx, nullptr));
|
||||
JS::Rooted<JS::BigInt*> zeroBigInt(cx, JS::BigInt::zero(cx));
|
||||
JS::Rooted<js::ObjectGroup*> rootedObjGroup(cx, JSObject::getGroup(cx, glob));
|
||||
JS::Rooted<js::RegExpObject*> regExp(
|
||||
cx, js::RegExpObject::create(cx, u"", 0, JS::RegExpFlags{},
|
||||
js::GenericObject));
|
||||
JS::Rooted<js::RegExpShared*> rootedRegExpShared(
|
||||
cx, js::RegExpObject::getShared(cx, regExp));
|
||||
|
||||
JS::CompileOptions options(cx);
|
||||
options.setFileAndLine(__FILE__, __LINE__);
|
||||
JS::SourceText<char16_t> srcBuf;
|
||||
mozilla::Unused << srcBuf.init(cx, nullptr, 0, JS::SourceOwnership::Borrowed);
|
||||
JS::RootedScript emptyScript(cx, JS::Compile(cx, options, srcBuf));
|
||||
|
||||
// Inline TraceKinds.
|
||||
JS::GCCellPtr nulll(nullptr);
|
||||
JS::GCCellPtr object(glob.get());
|
||||
JS::GCCellPtr string(empty.get());
|
||||
JS::GCCellPtr symbol(unique.get());
|
||||
JS::GCCellPtr bigint(zeroBigInt.get());
|
||||
JS::GCCellPtr shape(glob->shape());
|
||||
JS::GCCellPtr objectGroup(rootedObjGroup.get());
|
||||
|
||||
// Out-of-line TraceKinds.
|
||||
JS::GCCellPtr baseShape(glob->shape()->base());
|
||||
// JitCode can't easily be tested here, so skip it.
|
||||
JS::GCCellPtr script(emptyScript.get());
|
||||
JS::GCCellPtr scope(emptyScript->bodyScope());
|
||||
JS::GCCellPtr regExpShared(rootedRegExpShared.get());
|
||||
|
||||
breakpoint();
|
||||
|
||||
@ -20,4 +59,11 @@ FRAGMENT(GCCellPtr, simple) {
|
||||
use(object);
|
||||
use(string);
|
||||
use(symbol);
|
||||
use(bigint);
|
||||
use(shape);
|
||||
use(objectGroup);
|
||||
use(baseShape);
|
||||
use(script);
|
||||
use(scope);
|
||||
use(regExpShared);
|
||||
}
|
||||
|
@ -9,3 +9,10 @@ assert_pretty('nulll', 'JS::GCCellPtr(nullptr)')
|
||||
assert_pretty('object', 'JS::GCCellPtr((JSObject*) )')
|
||||
assert_pretty('string', 'JS::GCCellPtr((JSString*) )')
|
||||
assert_pretty('symbol', 'JS::GCCellPtr((JS::Symbol*) )')
|
||||
assert_pretty('bigint', 'JS::GCCellPtr((JS::BigInt*) )')
|
||||
assert_pretty('shape', 'JS::GCCellPtr((js::Shape*) )')
|
||||
assert_pretty('objectGroup', 'JS::GCCellPtr((js::ObjectGroup*) )')
|
||||
assert_pretty('baseShape', 'JS::GCCellPtr((js::BaseShape*) )')
|
||||
assert_pretty('script', 'JS::GCCellPtr((js::BaseScript*) )')
|
||||
assert_pretty('scope', 'JS::GCCellPtr((js::Scope*) )')
|
||||
assert_pretty('regExpShared', 'JS::GCCellPtr((js::RegExpShared*) )')
|
||||
|
Loading…
Reference in New Issue
Block a user