forked from ethanchewy/PythonBuddy
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlltracker.py
More file actions
161 lines (146 loc) · 5.61 KB
/
lltracker.py
File metadata and controls
161 lines (146 loc) · 5.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
"""
Reference tracker for lltype data structures.
"""
import sys, os
from rpython.rtyper.lltypesystem import lltype, llmemory
from rpython.memory.gcheader import header2obj
from rpython.translator.tool.reftracker import BaseRefTrackerPage, MARKER
from rpython.tool.uid import uid
from rpython.tool.identity_dict import identity_dict
class LLRefTrackerPage(BaseRefTrackerPage):
def compute(self, objectlist, size_gc_header):
self.size_gc_header = size_gc_header
return BaseRefTrackerPage.compute(self, objectlist)
def formatobject(self, o):
lines = []
for name, value in self.enum_content(o):
if not isinstance(value, str):
value = '0x%x' % uid(value)
lines.append('%s = %s' % (name, value))
s = '\n'.join(lines)
t = shorttypename(lltype.typeOf(o))
return t, s, ''
def get_referrers(self, o):
return [] # not implemented
def get_referents(self, o):
for name, value in self.enum_content(o):
if not isinstance(value, str):
yield value
def edgelabel(self, o1, o2):
slst = []
for name, value in self.enum_content(o1):
if value is o2:
slst.append(name)
return '/'.join(slst)
def newpage(self, objectlist):
return self.__class__(objectlist, self.size_gc_header)
def normalize(self, o):
if self.size_gc_header is not None:
try:
return header2obj[o]._obj
except (KeyError, TypeError):
pass
return o
def enum_content(self, o, name='', with_header=True):
# XXX clean up
T = lltype.typeOf(o)
if (self.size_gc_header is not None and with_header
and isinstance(T, lltype.ContainerType) and T._gckind == 'gc'):
adr = llmemory.cast_ptr_to_adr(o._as_ptr())
adr -= self.size_gc_header
o = adr.get()._obj
T = lltype.typeOf(o)
if isinstance(T, lltype.Struct):
try:
gcobjptr = header2obj[o]
fmt = '(%s)'
except KeyError:
gcobjptr = None
fmt = '%s'
for name in T._names:
for name, value in self.enum_content(getattr(o, name), name,
with_header=False):
yield fmt % (name,), value
if gcobjptr:
if self.size_gc_header is not None:
for sub in self.enum_content(gcobjptr._obj,
with_header=False):
yield sub
else:
# display as a link to avoid the same data showing up
# twice in the graph
yield 'header of', gcobjptr._obj
elif isinstance(T, lltype.Array):
for index, o1 in enumerate(o.items):
for sub in self.enum_content(o1, str(index)):
yield sub
elif isinstance(T, lltype.Ptr):
if not o:
yield name, 'null'
else:
yield name, self.normalize(lltype.normalizeptr(o)._obj)
elif isinstance(T, lltype.OpaqueType) and hasattr(o, 'container'):
T = lltype.typeOf(o.container)
yield 'container', '<%s>' % (shorttypename(T),)
for sub in self.enum_content(o.container, name, with_header=False):
yield sub
elif T == llmemory.Address:
if not o:
yield name, 'NULL'
else:
addrof = o.ref()
T1 = lltype.typeOf(addrof)
if (isinstance(T1, lltype.Ptr) and
isinstance(T1.TO, lltype.Struct) and
addrof._obj in header2obj):
yield name + ' @hdr', self.normalize(addrof._obj)
else:
yield name + ' @', self.normalize(o.ptr._obj)
else:
yield name, str(o)
def shorttypename(T):
return '%s %s' % (T.__class__.__name__, getattr(T, '__name__', ''))
def track(*ll_objects):
"""Invoke a dot+pygame object reference tracker."""
lst = [MARKER]
size_gc_header = None
seen = identity_dict()
for ll_object in ll_objects:
if isinstance(ll_object, llmemory.GCHeaderOffset):
size_gc_header = ll_object
continue
#if isinstance(lltype.typeOf(ll_object), lltype.Ptr):
# ptr = lltype.normalizeptr(ll_object)
# if ptr is not None:
# ll_object = ptr._obj
# else:
# ll_object = None
if ll_object is not None and ll_object not in seen:
lst.append(ll_object)
seen[ll_object] = ll_object
page = LLRefTrackerPage(lst, size_gc_header)
# auto-expand one level, for now
auto_expand = 1
for i in range(auto_expand):
page = page.content()
for ll_object in lst[1:]:
for name, value in page.enum_content(ll_object):
if not isinstance(value, str) and value not in seen:
lst.append(value)
seen[value] = value
page = page.newpage(lst)
page.display()
if __name__ == '__main__':
try:
sys.path.remove(os.getcwd())
except ValueError:
pass
T = lltype.GcArray(lltype.Signed)
S = lltype.GcForwardReference()
S.become(lltype.GcStruct('S', ('t', lltype.Ptr(T)),
('next', lltype.Ptr(S))))
s = lltype.malloc(S)
s.next = lltype.malloc(S)
s.next.t = lltype.malloc(T, 5)
s.next.t[1] = 123
track(s)