[pypy-svn] r27512 - in pypy/dist/pypy: rpython rpython/lltypesystem rpython/memory translator/tool

arigo at codespeak.net arigo at codespeak.net
Sat May 20 18:37:32 CEST 2006


Author: arigo
Date: Sat May 20 18:37:29 2006
New Revision: 27512

Added:
   pypy/dist/pypy/translator/tool/lltracker.py   (contents, props changed)
Modified:
   pypy/dist/pypy/rpython/llinterp.py
   pypy/dist/pypy/rpython/lltypesystem/lloperation.py
   pypy/dist/pypy/rpython/memory/gcheader.py
   pypy/dist/pypy/translator/tool/reftracker.py
Log:
A pygame viewer for lltype data structures.  There is an lloperation
that will display one or several pointers or addresses, and you
click your way along further pointers.  Used from llhelpers as:
    
    from pypy.rpython.lltypesystem.lloperation import llop
    llop.debug_view(lltype.Void, myptr [, myptr...])



Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py	(original)
+++ pypy/dist/pypy/rpython/llinterp.py	Sat May 20 18:37:29 2006
@@ -401,6 +401,10 @@
     # __________________________________________________________
     # misc LL operation implementations
 
+    def op_debug_view(self, *ll_objects):
+        from pypy.translator.tool.lltracker import track
+        track(*ll_objects)
+
     def op_keepalive(self, value):
         pass
 

Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lloperation.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py	Sat May 20 18:37:29 2006
@@ -341,6 +341,9 @@
     'decode_arg':           LLOp(canraise=(Exception,)),
     'decode_arg_def':       LLOp(canraise=(Exception,)),
     'getslice':             LLOp(canraise=(Exception,)),
+
+    # __________ debugging __________
+    'debug_view':           LLOp(),
 }
 
     # __________ operations on PyObjects __________

Modified: pypy/dist/pypy/rpython/memory/gcheader.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gcheader.py	(original)
+++ pypy/dist/pypy/rpython/memory/gcheader.py	Sat May 20 18:37:29 2006
@@ -2,20 +2,23 @@
 from pypy.rpython.lltypesystem import lltype, llmemory
 
 
+# this is global because a header cannot be a header of more than one GcObj
+header2obj = weakref.WeakKeyDictionary()
+
+
 class GCHeaderBuilder(object):
 
     def __init__(self, HDR):
         """NOT_RPYTHON"""
         self.HDR = HDR
         self.obj2header = weakref.WeakKeyDictionary()
-        self.header2obj = weakref.WeakKeyDictionary()
         self.size_gc_header = llmemory.GCHeaderOffset(self)
 
     def header_of_object(self, gcptr):
         return self.obj2header[gcptr._as_obj()]
 
     def object_from_header(self, headerptr):
-        return self.header2obj[headerptr._as_obj()]
+        return header2obj[headerptr._as_obj()]
 
     def get_header(self, gcptr):
         return self.obj2header.get(gcptr._as_obj(), None)
@@ -29,7 +32,7 @@
         assert not gcobj._parentstructure()
         headerptr = lltype.malloc(self.HDR, immortal=True)
         self.obj2header[gcobj] = headerptr
-        self.header2obj[headerptr._obj] = gcptr._as_ptr()
+        header2obj[headerptr._obj] = gcptr._as_ptr()
         return headerptr
 
     def _freeze_(self):

Added: pypy/dist/pypy/translator/tool/lltracker.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/tool/lltracker.py	Sat May 20 18:37:29 2006
@@ -0,0 +1,122 @@
+"""
+Reference tracker for lltype data structures.
+"""
+
+import autopath, sys, os
+import gc
+from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.rpython.memory.gcheader import header2obj
+from pypy.translator.tool.reftracker import BaseRefTrackerPage, MARKER
+from pypy.tool.uid import uid
+
+
+class LLRefTrackerPage(BaseRefTrackerPage):
+
+    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 enum_content(cls, o, name=''):
+        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 cls.enum_content(getattr(o, name), name):
+                    yield fmt % (name,), value
+            if gcobjptr:
+                GCT = lltype.typeOf(gcobjptr)
+                yield 'header of', '<%s>' % (shorttypename(GCT.TO),)
+                for sub in cls.enum_content(gcobjptr._obj):
+                    yield sub
+        elif isinstance(T, lltype.Array):
+            for index, o1 in enumerate(o.items):
+                for sub in cls.enum_content(o1, str(index)):
+                    yield sub
+        elif isinstance(T, lltype.Ptr):
+            if not o:
+                yield name, 'null'
+            else:
+                yield name, o._obj
+        elif isinstance(T, lltype.OpaqueType) and hasattr(o, 'container'):
+            T = lltype.typeOf(o.container)
+            yield 'container', '<%s>' % (shorttypename(T),)
+            for sub in cls.enum_content(o.container, name):
+                yield sub
+        elif T == llmemory.Address:
+            if not o:
+                yield name, 'NULL'
+            else:
+                addrof = o.get()
+                T1 = lltype.typeOf(addrof)
+                if (isinstance(T1, lltype.Ptr) and
+                    isinstance(T1.TO, lltype.Struct) and
+                    addrof._obj in header2obj):
+                    yield name + ' @hdr', addrof._obj
+                else:
+                    yield name + ' @', o.ob._obj
+                    if o.offset:
+                        yield '... offset', str(o.offset)
+        else:
+            yield name, str(o)
+    enum_content = classmethod(enum_content)
+
+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]
+    for ll_object in ll_objects:
+        if isinstance(lltype.typeOf(ll_object), lltype.Ptr):
+            ll_object = ll_object._obj
+        lst.append(ll_object)
+    if len(ll_objects) == 1:
+        # auto-expand one level
+        for name, value in LLRefTrackerPage.enum_content(ll_objects[0]):
+            if not isinstance(value, str):
+                lst.append(value)
+    page = LLRefTrackerPage(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)

Modified: pypy/dist/pypy/translator/tool/reftracker.py
==============================================================================
--- pypy/dist/pypy/translator/tool/reftracker.py	(original)
+++ pypy/dist/pypy/translator/tool/reftracker.py	Sat May 20 18:37:29 2006
@@ -3,7 +3,7 @@
 Usage: call track(obj).
 """
 
-import autopath
+import autopath, sys, os
 import gc
 from pypy.translator.tool.graphpage import GraphPage, DotGen
 from pypy.tool.uid import uid
@@ -12,7 +12,7 @@
 MARKER = object()
 
 
-class RefTrackerPage(GraphPage):
+class BaseRefTrackerPage(GraphPage):
 
     def compute(self, objectlist):
         assert objectlist[0] is MARKER
@@ -24,36 +24,24 @@
 
         def addedge(o1, o2):
             key = (uid(o1), uid(o2))
-            slst = []
-            if type(o1) in (list, tuple):
-                for i in range(len(o1)):
-                    if o1[i] is o2:
-                        slst.append('[%d]' % i)
-            elif type(o1) is dict:
-                for k, v in o1.items():
-                    if v is o2:
-                        slst.append('[%r]' % (k,))
-            edges[key] = ', '.join(slst)
+            edges[key] = self.edgelabel(o1, o2)
 
         for i in range(1, len(objectlist)):
-            s = repr(objectlist[i])
+            typename, s, linktext = self.formatobject(objectlist[i])
             word = '0x%x' % uid(objectlist[i])
-            if len(s) > 50:
-                self.links[word] = s
-                s = s[:20] + ' ... ' + s[-20:]
-            s = '<%s> %s\\n%s' % (type(objectlist[i]).__name__,
-                                    word,
-                                    s)
+            if linktext:
+                self.links[word] = linktext
+            s = '<%s> %s\\n%s' % (typename, word, s)
             nodename = 'node%d' % len(nodes)
             dotgen.emit_node(nodename, label=s, shape="box")
             nodes[uid(objectlist[i])] = nodename
-            for o2 in gc.get_referents(objectlist[i]):
+            for o2 in self.get_referents(objectlist[i]):
                 if o2 is None:
                     continue
                 addedge(objectlist[i], o2)
                 id2typename[uid(o2)] = type(o2).__name__
                 del o2
-            for o2 in gc.get_referrers(objectlist[i]):
+            for o2 in self.get_referrers(objectlist[i]):
                 if o2 is None:
                     continue
                 if type(o2) is list and o2 and o2[0] is MARKER:
@@ -81,26 +69,60 @@
         found = None
         objectlist = self.objectlist
         for i in range(1, len(objectlist)):
-            for o2 in gc.get_referents(objectlist[i]):
+            for o2 in self.get_referents(objectlist[i]):
                 if uid(o2) == id1:
                     found = o2
-            for o2 in gc.get_referrers(objectlist[i]):
+            for o2 in self.get_referrers(objectlist[i]):
                 if uid(o2) == id1:
                     found = o2
         if found is not None:
             objectlist = objectlist + [found]
         else:
             print '*** NOTE: object not found'
-        return RefTrackerPage(objectlist)
+        return self.__class__(objectlist)
+
+    def formatobject(self, o):
+        s = repr(o)
+        if len(s) > 50:
+            linktext = s
+            s = s[:20] + ' ... ' + s[-20:]
+        else:
+            linktext = ''
+        return type(o).__name__, s, linktext
+
+    def edgelabel(self, o1, o2):
+        return ''
+
+
+class RefTrackerPage(BaseRefTrackerPage):
+
+    get_referrers = staticmethod(gc.get_referrers)
+    get_referents = staticmethod(gc.get_referents)
+
+    def edgelabel(self, o1, o2):
+        slst = []
+        if type(o1) in (list, tuple):
+            for i in range(len(o1)):
+                if o1[i] is o2:
+                    slst.append('[%d]' % i)
+        elif type(o1) is dict:
+            for k, v in o1.items():
+                if v is o2:
+                    slst.append('[%r]' % (k,))
+        return ', '.join(slst)
 
 
-def track(o):
+def track(*objs):
     """Invoke a dot+pygame object reference tracker."""
-    page = RefTrackerPage([MARKER, o])
-    del o
+    page = RefTrackerPage([MARKER] + list(objs))
+    del objs
     page.display()
 
 
 if __name__ == '__main__':
+    try:
+        sys.path.remove(os.getcwd())
+    except ValueError:
+        pass
     d = {"lskjadldjslkj": "adjoiadoixmdoiemdwoi"}
     track(d)



More information about the Pypy-commit mailing list