зеркало из https://github.com/mozilla/gecko-dev.git
Bug 822563: Pretty-print references to JSObject and its subclasses. r=sfink
This commit is contained in:
Родитель
d67d0c218c
Коммит
ef6e51ee3c
|
@ -3,7 +3,7 @@
|
|||
import gdb
|
||||
import mozilla.JSString
|
||||
import mozilla.prettyprinters as prettyprinters
|
||||
from mozilla.prettyprinters import ptr_pretty_printer
|
||||
from mozilla.prettyprinters import ptr_pretty_printer, ref_pretty_printer
|
||||
from mozilla.Root import deref
|
||||
|
||||
prettyprinters.clear_module_printers(__name__)
|
||||
|
@ -19,9 +19,9 @@ class JSObjectTypeCache(object):
|
|||
# JSFunction has JSObject as a base class.
|
||||
|
||||
@ptr_pretty_printer('JSObject')
|
||||
class JSObjectPtr(prettyprinters.Pointer):
|
||||
class JSObjectPtrOrRef(prettyprinters.Pointer):
|
||||
def __init__(self, value, cache):
|
||||
super(JSObjectPtr, self).__init__(value, cache)
|
||||
super(JSObjectPtrOrRef, self).__init__(value, cache)
|
||||
if not cache.mod_JSObject:
|
||||
cache.mod_JSObject = JSObjectTypeCache(value, cache)
|
||||
self.otc = cache.mod_JSObject
|
||||
|
@ -34,9 +34,15 @@ class JSObjectPtr(prettyprinters.Pointer):
|
|||
is_delegate = bool(flags & self.otc.flag_DELEGATE)
|
||||
name = None
|
||||
if class_name == 'Function':
|
||||
function = self.value.cast(self.otc.func_ptr_type)
|
||||
if self.value.type.code == gdb.TYPE_CODE_PTR:
|
||||
function = self.value.cast(self.otc.func_ptr_type)
|
||||
elif self.value.type.code == gdb.TYPE_CODE_REF:
|
||||
function = self.value.address.cast(self.otc.func_ptr_type)
|
||||
atom = deref(function['atom_'])
|
||||
name = str(atom) if atom else '<unnamed>'
|
||||
return '[object %s%s]%s' % (class_name,
|
||||
' ' + name if name else '',
|
||||
' delegate' if is_delegate else '')
|
||||
|
||||
@ref_pretty_printer('JSObject')
|
||||
def JSObjectRef(value, cache): return JSObjectPtrOrRef(value, cache)
|
||||
|
|
|
@ -45,6 +45,20 @@ def ptr_pretty_printer(type_name):
|
|||
return fn
|
||||
return add
|
||||
|
||||
# a dictionary mapping gdb.Type tags to pretty-printer functions for
|
||||
# references to that type.
|
||||
ref_printers_by_tag = {}
|
||||
|
||||
# A decorator: add the decoratee as a pretty-printer lookup function for
|
||||
# references to instances of types named |type_name|.
|
||||
def ref_pretty_printer(type_name):
|
||||
def add(fn):
|
||||
check_for_reused_pretty_printer(fn)
|
||||
add_to_subprinter_list(fn, "ref-to-" + type_name)
|
||||
ref_printers_by_tag[type_name] = fn
|
||||
return fn
|
||||
return add
|
||||
|
||||
# a dictionary mapping the template name portion of gdb.Type tags to
|
||||
# pretty-printer functions for instantiations of that template.
|
||||
template_printers_by_tag = {}
|
||||
|
@ -83,7 +97,8 @@ def pretty_printer_for_regexp(pattern, name):
|
|||
#
|
||||
# clear_module_printers(__name__)
|
||||
def clear_module_printers(module_name):
|
||||
global printers_by_tag, ptr_printers_by_tag, template_printers_by_tag, printers_by_regexp
|
||||
global printers_by_tag, ptr_printers_by_tag, ref_printers_by_tag
|
||||
global template_printers_by_tag, printers_by_regexp
|
||||
|
||||
# Remove all pretty-printers defined in the module named |module_name|
|
||||
# from d.
|
||||
|
@ -101,6 +116,7 @@ def clear_module_printers(module_name):
|
|||
|
||||
clear_dictionary(printers_by_tag)
|
||||
clear_dictionary(ptr_printers_by_tag)
|
||||
clear_dictionary(ref_printers_by_tag)
|
||||
clear_dictionary(template_printers_by_tag)
|
||||
|
||||
# Iterate over printers_by_regexp, deleting entries from the given module.
|
||||
|
@ -226,28 +242,31 @@ def lookup_for_objfile(objfile):
|
|||
return f(value, cache)
|
||||
return None
|
||||
|
||||
def check_table_by_type_name(table, t):
|
||||
if t.code == gdb.TYPE_CODE_TYPEDEF:
|
||||
return check_table(table, str(t))
|
||||
elif t.code == gdb.TYPE_CODE_STRUCT and t.tag:
|
||||
return check_table(table, t.tag)
|
||||
else:
|
||||
return None
|
||||
|
||||
for t in implemented_types(value.type):
|
||||
if t.code == gdb.TYPE_CODE_PTR:
|
||||
for t2 in implemented_types(t.target()):
|
||||
if t2.code == gdb.TYPE_CODE_TYPEDEF:
|
||||
p = check_table(ptr_printers_by_tag, str(t2))
|
||||
elif t2.code == gdb.TYPE_CODE_STRUCT and t2.tag:
|
||||
p = check_table(ptr_printers_by_tag, t2.tag)
|
||||
else:
|
||||
p = None
|
||||
p = check_table_by_type_name(ptr_printers_by_tag, t2)
|
||||
if p: return p
|
||||
elif t.code == gdb.TYPE_CODE_REF:
|
||||
for t2 in implemented_types(t.target()):
|
||||
p = check_table_by_type_name(ref_printers_by_tag, t2)
|
||||
if p: return p
|
||||
else:
|
||||
if t.code == gdb.TYPE_CODE_TYPEDEF:
|
||||
p = check_table(printers_by_tag, str(t))
|
||||
elif t.code == gdb.TYPE_CODE_STRUCT and t.tag:
|
||||
p = check_table_by_type_name(printers_by_tag, t)
|
||||
if p: return p
|
||||
if t.code == gdb.TYPE_CODE_STRUCT and t.tag:
|
||||
m = template_regexp.match(t.tag)
|
||||
if m:
|
||||
p = check_table(template_printers_by_tag, m.group(1))
|
||||
else:
|
||||
p = check_table(printers_by_tag, t.tag)
|
||||
else:
|
||||
p = None
|
||||
if p: return p
|
||||
if p: return p
|
||||
|
||||
# Failing that, look for a printer in printers_by_regexp. We have
|
||||
# to scan the whole list, so regexp printers should be used
|
||||
|
@ -275,6 +294,8 @@ def lookup_for_objfile(objfile):
|
|||
# pointers, by declining to construct a pretty-printer for them at all.
|
||||
# Derived classes may simply assume that self.value is non-null.
|
||||
#
|
||||
# To help share code, this class can also be used with reference types.
|
||||
#
|
||||
# This class provides the following methods, which subclasses are free to
|
||||
# override:
|
||||
#
|
||||
|
@ -291,7 +312,8 @@ def lookup_for_objfile(objfile):
|
|||
class Pointer(object):
|
||||
def __new__(cls, value, cache):
|
||||
# Don't try to provide pretty-printers for NULL pointers.
|
||||
if value == 0: return None
|
||||
if value.type.code == gdb.TYPE_CODE_PTR and value == 0:
|
||||
return None
|
||||
return super(Pointer, cls).__new__(cls)
|
||||
|
||||
def __init__(self, value, cache):
|
||||
|
@ -301,7 +323,10 @@ class Pointer(object):
|
|||
def to_string(self):
|
||||
# See comment above.
|
||||
assert not hasattr(self, 'display_hint') or self.display_hint() != 'string'
|
||||
address = self.value.cast(self.cache.void_ptr_t)
|
||||
if self.value.type.code == gdb.TYPE_CODE_PTR:
|
||||
address = self.value.cast(self.cache.void_ptr_t)
|
||||
elif self.value.type.code == gdb.TYPE_CODE_REF:
|
||||
address = '@' + str(self.value.address.cast(self.cache.void_ptr_t))
|
||||
try:
|
||||
summary = self.summary()
|
||||
except gdb.MemoryError as r:
|
||||
|
|
|
@ -10,6 +10,9 @@ FRAGMENT(JSObject, simple) {
|
|||
js::Rooted<JSFunction *> funcPtr(cx, JS_NewFunction(cx, (JSNative) 1, 0, 0,
|
||||
JS_GetGlobalObject(cx), "formFollows"));
|
||||
|
||||
JSObject &plainRef = *plain;
|
||||
JSFunction &funcRef = *funcPtr;
|
||||
|
||||
breakpoint();
|
||||
|
||||
(void) glob;
|
||||
|
@ -17,6 +20,8 @@ FRAGMENT(JSObject, simple) {
|
|||
(void) func;
|
||||
(void) anon;
|
||||
(void) funcPtr;
|
||||
(void) plainRef;
|
||||
(void) funcRef;
|
||||
}
|
||||
|
||||
FRAGMENT(JSObject, null) {
|
||||
|
@ -26,4 +31,3 @@ FRAGMENT(JSObject, null) {
|
|||
|
||||
(void) null;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
# Printing JSObjects.
|
||||
|
||||
assert_subprinter_registered('SpiderMonkey', 'ptr-to-JSObject')
|
||||
assert_subprinter_registered('SpiderMonkey', 'ref-to-JSObject')
|
||||
|
||||
run_fragment('JSObject.simple')
|
||||
|
||||
# These patterns look a little strange because of prolog.py's 'set print
|
||||
|
@ -13,3 +15,6 @@ assert_pretty('plain', '(JSObject *) [object Object]')
|
|||
assert_pretty('func', '(JSObject *) [object Function "dys"]')
|
||||
assert_pretty('anon', '(JSObject *) [object Function <unnamed>]')
|
||||
assert_pretty('funcPtr', '(JSFunction *) [object Function "formFollows"]')
|
||||
|
||||
assert_pretty('plainRef', '(JSObject &) @ [object Object]')
|
||||
assert_pretty('funcRef', '(JSFunction &) @ [object Function "formFollows"]')
|
||||
|
|
|
@ -16,3 +16,7 @@ assert_eq(implemented_type_names('e'), ['E', 'C', 'D'])
|
|||
assert_eq(implemented_type_names('e_'), ['E_', 'E', 'C', 'D'])
|
||||
assert_eq(implemented_type_names('f'), ['F', 'C', 'D'])
|
||||
assert_eq(implemented_type_names('h'), ['H', 'F', 'G', 'C', 'D'])
|
||||
|
||||
# Check that our pretty-printers aren't interfering with printing other types.
|
||||
assert_pretty('10', '10')
|
||||
assert_pretty('(void*) 0', '') # Because of 'set print address off'
|
||||
|
|
Загрузка…
Ссылка в новой задаче