forked from Imagelibrary/littlefs
scripts: Improved cycle detection notes in scripts
- Prevented childrenof memoization from hiding the source of a detected cycle. - Deduplicated multiple cycle detected notes. - Fixed note rendering when last column does not have a notes list. Currently this only happens when entry is None (no results).
This commit is contained in:
@@ -889,8 +889,13 @@ def table(Result, results, diff_results=None, *,
|
|||||||
getattr(r, k, None),
|
getattr(r, k, None),
|
||||||
getattr(diff_r, k, None)))))
|
getattr(diff_r, k, None)))))
|
||||||
# append any notes
|
# append any notes
|
||||||
if hasattr(Result, '_notes'):
|
if hasattr(Result, '_notes') and r is not None:
|
||||||
entry[-1][1].extend(getattr(r, Result._notes))
|
notes = getattr(r, Result._notes)
|
||||||
|
if isinstance(entry[-1], tuple):
|
||||||
|
entry[-1] = (entry[-1][0], entry[-1][1] + notes)
|
||||||
|
else:
|
||||||
|
entry[-1] = (entry[-1], notes)
|
||||||
|
|
||||||
return entry
|
return entry
|
||||||
|
|
||||||
# recursive entry helper, only used by some scripts
|
# recursive entry helper, only used by some scripts
|
||||||
|
|||||||
@@ -623,8 +623,13 @@ def table(Result, results, diff_results=None, *,
|
|||||||
getattr(r, k, None),
|
getattr(r, k, None),
|
||||||
getattr(diff_r, k, None)))))
|
getattr(diff_r, k, None)))))
|
||||||
# append any notes
|
# append any notes
|
||||||
if hasattr(Result, '_notes'):
|
if hasattr(Result, '_notes') and r is not None:
|
||||||
entry[-1][1].extend(getattr(r, Result._notes))
|
notes = getattr(r, Result._notes)
|
||||||
|
if isinstance(entry[-1], tuple):
|
||||||
|
entry[-1] = (entry[-1][0], entry[-1][1] + notes)
|
||||||
|
else:
|
||||||
|
entry[-1] = (entry[-1], notes)
|
||||||
|
|
||||||
return entry
|
return entry
|
||||||
|
|
||||||
# recursive entry helper, only used by some scripts
|
# recursive entry helper, only used by some scripts
|
||||||
|
|||||||
@@ -1638,8 +1638,13 @@ def table(Result, results, diff_results=None, *,
|
|||||||
getattr(r, k, None),
|
getattr(r, k, None),
|
||||||
getattr(diff_r, k, None)))))
|
getattr(diff_r, k, None)))))
|
||||||
# append any notes
|
# append any notes
|
||||||
if hasattr(Result, '_notes'):
|
if hasattr(Result, '_notes') and r is not None:
|
||||||
entry[-1][1].extend(getattr(r, Result._notes))
|
notes = getattr(r, Result._notes)
|
||||||
|
if isinstance(entry[-1], tuple):
|
||||||
|
entry[-1] = (entry[-1][0], entry[-1][1] + notes)
|
||||||
|
else:
|
||||||
|
entry[-1] = (entry[-1], notes)
|
||||||
|
|
||||||
return entry
|
return entry
|
||||||
|
|
||||||
# recursive entry helper, only used by some scripts
|
# recursive entry helper, only used by some scripts
|
||||||
|
|||||||
@@ -157,7 +157,8 @@ class CtxResult(co.namedtuple('CtxResult', [
|
|||||||
else other.i if self.i is None
|
else other.i if self.i is None
|
||||||
else min(self.i, other.i),
|
else min(self.i, other.i),
|
||||||
self.children + other.children,
|
self.children + other.children,
|
||||||
self.notes + other.notes)
|
list(co.OrderedDict.fromkeys(it.chain(
|
||||||
|
self.notes, other.notes)).keys()))
|
||||||
|
|
||||||
|
|
||||||
def openio(path, mode='r', buffering=-1):
|
def openio(path, mode='r', buffering=-1):
|
||||||
@@ -681,7 +682,7 @@ def collect(obj_paths, *,
|
|||||||
def childrenof(entry, seen=set()):
|
def childrenof(entry, seen=set()):
|
||||||
# found a cycle? stop here
|
# found a cycle? stop here
|
||||||
if entry.off in seen:
|
if entry.off in seen:
|
||||||
return [], ['cycle detected']
|
return [], ['cycle detected'], True
|
||||||
# cached?
|
# cached?
|
||||||
if not hasattr(childrenof, 'cache'):
|
if not hasattr(childrenof, 'cache'):
|
||||||
childrenof.cache = {}
|
childrenof.cache = {}
|
||||||
@@ -690,7 +691,7 @@ def collect(obj_paths, *,
|
|||||||
|
|
||||||
# pointer? deref and include size
|
# pointer? deref and include size
|
||||||
if entry.tag == 'DW_TAG_pointer_type':
|
if entry.tag == 'DW_TAG_pointer_type':
|
||||||
children, notes = [], []
|
children, notes, dirty = [], [], False
|
||||||
if 'DW_AT_type' in entry:
|
if 'DW_AT_type' in entry:
|
||||||
type = info[int(entry['DW_AT_type'].strip('<>'), 0)]
|
type = info[int(entry['DW_AT_type'].strip('<>'), 0)]
|
||||||
# skip modifiers to try to find name
|
# skip modifiers to try to find name
|
||||||
@@ -702,8 +703,9 @@ def collect(obj_paths, *,
|
|||||||
and type.tag != 'DW_TAG_subroutine_type'):
|
and type.tag != 'DW_TAG_subroutine_type'):
|
||||||
name_ = type.name
|
name_ = type.name
|
||||||
size_ = sizeof(type, seen | {entry.off})
|
size_ = sizeof(type, seen | {entry.off})
|
||||||
children_, notes_ = childrenof(
|
children_, notes_, dirty_ = childrenof(
|
||||||
type, seen | {entry.off})
|
type, seen | {entry.off})
|
||||||
|
dirty = dirty or dirty_
|
||||||
children.append(CtxResult(file, name_, size_,
|
children.append(CtxResult(file, name_, size_,
|
||||||
children=children_,
|
children=children_,
|
||||||
notes=notes_))
|
notes=notes_))
|
||||||
@@ -711,14 +713,15 @@ def collect(obj_paths, *,
|
|||||||
elif entry.tag in {
|
elif entry.tag in {
|
||||||
'DW_TAG_structure_type',
|
'DW_TAG_structure_type',
|
||||||
'DW_TAG_union_type'}:
|
'DW_TAG_union_type'}:
|
||||||
children, notes = [], []
|
children, notes, dirty = [], [], False
|
||||||
for child in entry.children:
|
for child in entry.children:
|
||||||
if child.tag != 'DW_TAG_member':
|
if child.tag != 'DW_TAG_member':
|
||||||
continue
|
continue
|
||||||
name_ = child.name
|
name_ = child.name
|
||||||
size_ = sizeof(child, seen | {entry.off})
|
size_ = sizeof(child, seen | {entry.off})
|
||||||
children_, notes_ = childrenof(
|
children_, notes_, dirty_ = childrenof(
|
||||||
child, seen | {entry.off})
|
child, seen | {entry.off})
|
||||||
|
dirty = dirty or dirty_
|
||||||
children.append(CtxResult(file, name_, size_,
|
children.append(CtxResult(file, name_, size_,
|
||||||
i=child.off,
|
i=child.off,
|
||||||
children=children_,
|
children=children_,
|
||||||
@@ -727,7 +730,7 @@ def collect(obj_paths, *,
|
|||||||
elif entry.tag in {
|
elif entry.tag in {
|
||||||
'DW_TAG_base_type',
|
'DW_TAG_base_type',
|
||||||
'DW_TAG_subroutine_type'}:
|
'DW_TAG_subroutine_type'}:
|
||||||
children, notes = [], []
|
children, notes, dirty = [], [], False
|
||||||
# a modifier?
|
# a modifier?
|
||||||
elif (entry.tag in {
|
elif (entry.tag in {
|
||||||
'DW_TAG_typedef',
|
'DW_TAG_typedef',
|
||||||
@@ -740,17 +743,18 @@ def collect(obj_paths, *,
|
|||||||
'DW_TAG_restrict_type'}
|
'DW_TAG_restrict_type'}
|
||||||
and 'DW_AT_type' in entry):
|
and 'DW_AT_type' in entry):
|
||||||
type = int(entry['DW_AT_type'].strip('<>'), 0)
|
type = int(entry['DW_AT_type'].strip('<>'), 0)
|
||||||
children, notes = childrenof(
|
children, notes, dirty = childrenof(
|
||||||
info[type], seen | {entry.off})
|
info[type], seen | {entry.off})
|
||||||
# void?
|
# void?
|
||||||
elif ('DW_AT_type' not in entry
|
elif ('DW_AT_type' not in entry
|
||||||
and 'DW_AT_byte_size' not in entry):
|
and 'DW_AT_byte_size' not in entry):
|
||||||
children, notes = [], []
|
children, notes = [], [], False
|
||||||
else:
|
else:
|
||||||
assert False, "Unknown dwarf entry? %r" % entry.tag
|
assert False, "Unknown dwarf entry? %r" % entry.tag
|
||||||
|
|
||||||
childrenof.cache[entry.off] = children, notes
|
if not dirty:
|
||||||
return children, notes
|
childrenof.cache[entry.off] = children, notes, dirty
|
||||||
|
return children, notes, dirty
|
||||||
|
|
||||||
# find each function's context
|
# find each function's context
|
||||||
for sym in syms:
|
for sym in syms:
|
||||||
@@ -796,7 +800,7 @@ def collect(obj_paths, *,
|
|||||||
size_ = sizeof(param)
|
size_ = sizeof(param)
|
||||||
|
|
||||||
# find children, recursing if necessary
|
# find children, recursing if necessary
|
||||||
children_, notes_ = childrenof(param)
|
children_, notes_, _ = childrenof(param)
|
||||||
|
|
||||||
params.append(CtxResult(file, name_, size_,
|
params.append(CtxResult(file, name_, size_,
|
||||||
i=param.off,
|
i=param.off,
|
||||||
@@ -1078,8 +1082,13 @@ def table(Result, results, diff_results=None, *,
|
|||||||
getattr(r, k, None),
|
getattr(r, k, None),
|
||||||
getattr(diff_r, k, None)))))
|
getattr(diff_r, k, None)))))
|
||||||
# append any notes
|
# append any notes
|
||||||
if hasattr(Result, '_notes'):
|
if hasattr(Result, '_notes') and r is not None:
|
||||||
entry[-1][1].extend(getattr(r, Result._notes))
|
notes = getattr(r, Result._notes)
|
||||||
|
if isinstance(entry[-1], tuple):
|
||||||
|
entry[-1] = (entry[-1][0], entry[-1][1] + notes)
|
||||||
|
else:
|
||||||
|
entry[-1] = (entry[-1], notes)
|
||||||
|
|
||||||
return entry
|
return entry
|
||||||
|
|
||||||
# recursive entry helper, only used by some scripts
|
# recursive entry helper, only used by some scripts
|
||||||
|
|||||||
@@ -889,8 +889,13 @@ def table(Result, results, diff_results=None, *,
|
|||||||
getattr(r, k, None),
|
getattr(r, k, None),
|
||||||
getattr(diff_r, k, None)))))
|
getattr(diff_r, k, None)))))
|
||||||
# append any notes
|
# append any notes
|
||||||
if hasattr(Result, '_notes'):
|
if hasattr(Result, '_notes') and r is not None:
|
||||||
entry[-1][1].extend(getattr(r, Result._notes))
|
notes = getattr(r, Result._notes)
|
||||||
|
if isinstance(entry[-1], tuple):
|
||||||
|
entry[-1] = (entry[-1][0], entry[-1][1] + notes)
|
||||||
|
else:
|
||||||
|
entry[-1] = (entry[-1], notes)
|
||||||
|
|
||||||
return entry
|
return entry
|
||||||
|
|
||||||
# recursive entry helper, only used by some scripts
|
# recursive entry helper, only used by some scripts
|
||||||
|
|||||||
@@ -1069,8 +1069,13 @@ def table(Result, results, diff_results=None, *,
|
|||||||
getattr(r, k, None),
|
getattr(r, k, None),
|
||||||
getattr(diff_r, k, None)))))
|
getattr(diff_r, k, None)))))
|
||||||
# append any notes
|
# append any notes
|
||||||
if hasattr(Result, '_notes'):
|
if hasattr(Result, '_notes') and r is not None:
|
||||||
entry[-1][1].extend(getattr(r, Result._notes))
|
notes = getattr(r, Result._notes)
|
||||||
|
if isinstance(entry[-1], tuple):
|
||||||
|
entry[-1] = (entry[-1][0], entry[-1][1] + notes)
|
||||||
|
else:
|
||||||
|
entry[-1] = (entry[-1], notes)
|
||||||
|
|
||||||
return entry
|
return entry
|
||||||
|
|
||||||
# recursive entry helper, only used by some scripts
|
# recursive entry helper, only used by some scripts
|
||||||
|
|||||||
@@ -1034,8 +1034,13 @@ def table(Result, results, diff_results=None, *,
|
|||||||
getattr(r, k, None),
|
getattr(r, k, None),
|
||||||
getattr(diff_r, k, None)))))
|
getattr(diff_r, k, None)))))
|
||||||
# append any notes
|
# append any notes
|
||||||
if hasattr(Result, '_notes'):
|
if hasattr(Result, '_notes') and r is not None:
|
||||||
entry[-1][1].extend(getattr(r, Result._notes))
|
notes = getattr(r, Result._notes)
|
||||||
|
if isinstance(entry[-1], tuple):
|
||||||
|
entry[-1] = (entry[-1][0], entry[-1][1] + notes)
|
||||||
|
else:
|
||||||
|
entry[-1] = (entry[-1], notes)
|
||||||
|
|
||||||
return entry
|
return entry
|
||||||
|
|
||||||
# recursive entry helper, only used by some scripts
|
# recursive entry helper, only used by some scripts
|
||||||
|
|||||||
@@ -153,7 +153,8 @@ class StackResult(co.namedtuple('StackResult', [
|
|||||||
self.frame + other.frame,
|
self.frame + other.frame,
|
||||||
max(self.limit, other.limit),
|
max(self.limit, other.limit),
|
||||||
self.children + other.children,
|
self.children + other.children,
|
||||||
self.notes + other.notes)
|
list(co.OrderedDict.fromkeys(it.chain(
|
||||||
|
self.notes, other.notes)).keys()))
|
||||||
|
|
||||||
|
|
||||||
def openio(path, mode='r', buffering=-1):
|
def openio(path, mode='r', buffering=-1):
|
||||||
@@ -873,7 +874,7 @@ def collect(obj_paths, *,
|
|||||||
def limitof(func, seen=set()):
|
def limitof(func, seen=set()):
|
||||||
# found a cycle? stop here
|
# found a cycle? stop here
|
||||||
if id(func) in seen:
|
if id(func) in seen:
|
||||||
return 0, 0
|
return 0, mt.inf
|
||||||
# cached?
|
# cached?
|
||||||
if not hasattr(limitof, 'cache'):
|
if not hasattr(limitof, 'cache'):
|
||||||
limitof.cache = {}
|
limitof.cache = {}
|
||||||
@@ -903,7 +904,7 @@ def collect(obj_paths, *,
|
|||||||
def childrenof(func, seen=set()):
|
def childrenof(func, seen=set()):
|
||||||
# found a cycle? stop here
|
# found a cycle? stop here
|
||||||
if id(func) in seen:
|
if id(func) in seen:
|
||||||
return [], ['cycle detected']
|
return [], ['cycle detected'], True
|
||||||
# cached?
|
# cached?
|
||||||
if not hasattr(childrenof, 'cache'):
|
if not hasattr(childrenof, 'cache'):
|
||||||
childrenof.cache = {}
|
childrenof.cache = {}
|
||||||
@@ -912,17 +913,20 @@ def collect(obj_paths, *,
|
|||||||
|
|
||||||
# find children recursively
|
# find children recursively
|
||||||
children = []
|
children = []
|
||||||
|
dirty = False
|
||||||
for addr, callee in func['calls']:
|
for addr, callee in func['calls']:
|
||||||
file_ = callee['file']
|
file_ = callee['file']
|
||||||
name_ = callee['sym'].name
|
name_ = callee['sym'].name
|
||||||
frame_, limit_ = limitof(callee, seen | {id(func)})
|
frame_, limit_ = limitof(callee, seen | {id(func)})
|
||||||
children_, notes_ = childrenof(callee, seen | {id(func)})
|
children_, notes_, dirty_ = childrenof(callee, seen | {id(func)})
|
||||||
|
dirty = dirty or dirty_
|
||||||
children.append(StackResult(file_, name_, frame_, limit_,
|
children.append(StackResult(file_, name_, frame_, limit_,
|
||||||
children=children_,
|
children=children_,
|
||||||
notes=notes_))
|
notes=notes_))
|
||||||
|
|
||||||
childrenof.cache[id(func)] = children, []
|
if not dirty:
|
||||||
return children, []
|
childrenof.cache[id(func)] = children, [], dirty
|
||||||
|
return children, [], dirty
|
||||||
|
|
||||||
# build results
|
# build results
|
||||||
results = []
|
results = []
|
||||||
@@ -930,7 +934,7 @@ def collect(obj_paths, *,
|
|||||||
file = func['file']
|
file = func['file']
|
||||||
name = func['sym'].name
|
name = func['sym'].name
|
||||||
frame, limit = limitof(func)
|
frame, limit = limitof(func)
|
||||||
children, notes = childrenof(func)
|
children, notes, _ = childrenof(func)
|
||||||
|
|
||||||
results.append(StackResult(file, name, frame, limit,
|
results.append(StackResult(file, name, frame, limit,
|
||||||
children=children,
|
children=children,
|
||||||
@@ -1205,8 +1209,13 @@ def table(Result, results, diff_results=None, *,
|
|||||||
getattr(r, k, None),
|
getattr(r, k, None),
|
||||||
getattr(diff_r, k, None)))))
|
getattr(diff_r, k, None)))))
|
||||||
# append any notes
|
# append any notes
|
||||||
if hasattr(Result, '_notes'):
|
if hasattr(Result, '_notes') and r is not None:
|
||||||
entry[-1][1].extend(getattr(r, Result._notes))
|
notes = getattr(r, Result._notes)
|
||||||
|
if isinstance(entry[-1], tuple):
|
||||||
|
entry[-1] = (entry[-1][0], entry[-1][1] + notes)
|
||||||
|
else:
|
||||||
|
entry[-1] = (entry[-1], notes)
|
||||||
|
|
||||||
return entry
|
return entry
|
||||||
|
|
||||||
# recursive entry helper, only used by some scripts
|
# recursive entry helper, only used by some scripts
|
||||||
@@ -1419,6 +1428,7 @@ def main(obj_paths,
|
|||||||
by=by if by is not None else ['function'],
|
by=by if by is not None else ['function'],
|
||||||
fields=fields,
|
fields=fields,
|
||||||
sort=sort,
|
sort=sort,
|
||||||
|
detect_cycles=False,
|
||||||
**args)
|
**args)
|
||||||
|
|
||||||
# error on recursion
|
# error on recursion
|
||||||
|
|||||||
@@ -906,8 +906,13 @@ def table(Result, results, diff_results=None, *,
|
|||||||
getattr(r, k, None),
|
getattr(r, k, None),
|
||||||
getattr(diff_r, k, None)))))
|
getattr(diff_r, k, None)))))
|
||||||
# append any notes
|
# append any notes
|
||||||
if hasattr(Result, '_notes'):
|
if hasattr(Result, '_notes') and r is not None:
|
||||||
entry[-1][1].extend(getattr(r, Result._notes))
|
notes = getattr(r, Result._notes)
|
||||||
|
if isinstance(entry[-1], tuple):
|
||||||
|
entry[-1] = (entry[-1][0], entry[-1][1] + notes)
|
||||||
|
else:
|
||||||
|
entry[-1] = (entry[-1], notes)
|
||||||
|
|
||||||
return entry
|
return entry
|
||||||
|
|
||||||
# recursive entry helper, only used by some scripts
|
# recursive entry helper, only used by some scripts
|
||||||
|
|||||||
Reference in New Issue
Block a user