[pypy-commit] pypy default: Hack hack hack at gdb_pypy: no longer preload all of typeids.txt,

arigo noreply at buildbot.pypy.org
Wed Oct 16 13:20:35 CEST 2013


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r67411:c9c7dba9ecc0
Date: 2013-10-16 13:19 +0200
http://bitbucket.org/pypy/pypy/changeset/c9c7dba9ecc0/

Log:	Hack hack hack at gdb_pypy: no longer preload all of typeids.txt,
	which takes forever.

diff --git a/pypy/tool/gdb_pypy.py b/pypy/tool/gdb_pypy.py
--- a/pypy/tool/gdb_pypy.py
+++ b/pypy/tool/gdb_pypy.py
@@ -113,24 +113,68 @@
         """
         exename = progspace.filename
         root = os.path.dirname(exename)
+        # XXX The same information is found in
+        # XXX   pypy_g_rpython_memory_gctypelayout_GCData.gcd_inst_typeids_z
+        # XXX Find out how to read it
         typeids_txt = os.path.join(root, 'typeids.txt')
         if not os.path.exists(typeids_txt):
             newroot = os.path.dirname(root)
             typeids_txt = os.path.join(newroot, 'typeids.txt')
         print 'loading', typeids_txt
-        typeids = {}
+        with open(typeids_txt) as f:
+            typeids = TypeIdsMap(f.readlines(), self.gdb)
+        return typeids
+
+
+class TypeIdsMap(object):
+    def __init__(self, lines, gdb):
+        self.lines = lines
+        self.gdb = gdb
+        self.line2offset = {0: 0}
+        self.offset2descr = {0: "(null typeid)"}
+
+    def __getitem__(self, key):
+        value = self.get(key)
+        if value is None:
+            raise KeyError(key)
+        return value
+
+    def __contains__(self, key):
+        return self.get(key) is not None
+
+    def _fetchline(self, linenum):
+        if linenum in self.line2offset:
+            return self.line2offset[linenum]
+        line = self.lines[linenum]
+        member, descr = map(str.strip, line.split(None, 1))
         if sys.maxint < 2**32:
             TIDT = "int*"
         else:
             TIDT = "char*"
-        with open(typeids_txt) as f:
-            for line in f:
-                member, descr = map(str.strip, line.split(None, 1))
-                expr = ("((%s)(&pypy_g_typeinfo.%s)) - (%s)&pypy_g_typeinfo"
-                           % (TIDT, member, TIDT))
-                offset = int(self.gdb.parse_and_eval(expr))
-                typeids[offset] = descr
-        return typeids
+        expr = ("((%s)(&pypy_g_typeinfo.%s)) - (%s)&pypy_g_typeinfo"
+                   % (TIDT, member, TIDT))
+        offset = int(self.gdb.parse_and_eval(expr))
+        self.line2offset[linenum] = offset
+        self.offset2descr[offset] = descr
+        return offset
+
+    def get(self, offset, default=None):
+        # binary search through the lines, asking gdb to parse stuff lazily
+        if offset in self.offset2descr:
+            return self.offset2descr[offset]
+        if not (0 < offset < sys.maxint):
+            return None
+        linerange = (0, len(self.lines))
+        while linerange[0] < linerange[1]:
+            linemiddle = (linerange[0] + linerange[1]) >> 1
+            offsetmiddle = self._fetchline(linemiddle)
+            if offsetmiddle == offset:
+                return self.offset2descr[offset]
+            elif offsetmiddle < offset:
+                linerange = (linemiddle + 1, linerange[1])
+            else:
+                linerange = (linerange[0], linemiddle)
+        return None
 
 
 def is_ptr(type, gdb):
diff --git a/pypy/tool/test/test_gdb_pypy.py b/pypy/tool/test/test_gdb_pypy.py
--- a/pypy/tool/test/test_gdb_pypy.py
+++ b/pypy/tool/test/test_gdb_pypy.py
@@ -1,11 +1,6 @@
 import py, sys
 from pypy.tool import gdb_pypy
 
-if sys.maxint < 2**32:
-    TIDT = "int*"
-else:
-    TIDT = "char*"
-
 class FakeGdb(object):
 
     COMMAND_NONE = -1
@@ -17,8 +12,10 @@
     def __init__(self, exprs, progspace=None):
         self.exprs = exprs
         self.progspace = progspace
+        self._parsed = []
 
     def parse_and_eval(self, expr):
+        self._parsed.append(expr)
         return self.exprs[expr]
 
     def current_progspace(self):
@@ -105,29 +102,39 @@
     hdr = gdb_pypy.lookup(obj, 'gcheader')
     assert hdr['h_tid'] == 123
 
+def exprmember(n):
+    if sys.maxint < 2**32:
+        TIDT = "int*"
+    else:
+        TIDT = "char*"
+    return ('((%s)(&pypy_g_typeinfo.member%d)) - (%s)&pypy_g_typeinfo'
+            % (TIDT, n, TIDT))
+
 def test_load_typeids(tmpdir):
     exe = tmpdir.join('testing_1').join('pypy-c')
     typeids = tmpdir.join('typeids.txt')
     typeids.write("""
-member0    GcStruct xxx {}
+member0    ?
+member1    GcStruct xxx {}
 """.strip())
     progspace = Mock(filename=str(exe))
-    exprs = {
-        '((%s)(&pypy_g_typeinfo.member0)) - (%s)&pypy_g_typeinfo'
-            % (TIDT, TIDT): 0,
-        }
+    exprs = {exprmember(1): 111}
     gdb = FakeGdb(exprs, progspace)
     cmd = gdb_pypy.RPyType(gdb)
     typeids = cmd.load_typeids(progspace)
-    assert typeids[0] == 'GcStruct xxx {}'
+    assert typeids[0] == '(null typeid)'
+    assert typeids[111] == 'GcStruct xxx {}'
+    py.test.raises(KeyError, "typeids[50]")
+    py.test.raises(KeyError, "typeids[150]")
 
 def test_RPyType(tmpdir):
     exe = tmpdir.join('pypy-c')
     typeids = tmpdir.join('typeids.txt')
     typeids.write("""
-member0    GcStruct xxx {}
-member1    GcStruct yyy {}
-member2    GcStruct zzz {}
+member0    ?
+member1    GcStruct xxx {}
+member2    GcStruct yyy {}
+member3    GcStruct zzz {}
 """.strip())
     #
     progspace = Mock(filename=str(exe))
@@ -141,12 +148,9 @@
     myvar = Value(d)
     exprs = {
         '*myvar': myvar,
-        '((%s)(&pypy_g_typeinfo.member0)) - (%s)&pypy_g_typeinfo'
-            % (TIDT, TIDT): 0,
-        '((%s)(&pypy_g_typeinfo.member1)) - (%s)&pypy_g_typeinfo'
-            % (TIDT, TIDT): 123,
-        '((%s)(&pypy_g_typeinfo.member2)) - (%s)&pypy_g_typeinfo'
-            % (TIDT, TIDT): 456,
+        exprmember(1): 0,
+        exprmember(2): 123,
+        exprmember(3): 456,
         }
     gdb = FakeGdb(exprs, progspace)
     cmd = gdb_pypy.RPyType(gdb)
@@ -192,3 +196,23 @@
 
     mylist.type.target().tag = None
     assert gdb_pypy.RPyListPrinter.lookup(mylist, FakeGdb) is None
+
+def test_typeidsmap():
+    gdb = FakeGdb({exprmember(1): 111,
+                   exprmember(2): 222,
+                   exprmember(3): 333})
+    typeids = gdb_pypy.TypeIdsMap(["member0  ?\n",
+                                   "member1  FooBar\n",
+                                   "member2  Baz\n",
+                                   "member3  Bok\n"], gdb)
+    assert gdb._parsed == []
+    assert typeids.get(111) == "FooBar"
+    assert gdb._parsed == [exprmember(2), exprmember(1)]
+    assert typeids.get(222) == "Baz"
+    assert gdb._parsed == [exprmember(2), exprmember(1)]
+    assert typeids.get(333) == "Bok"
+    assert gdb._parsed == [exprmember(2), exprmember(1), exprmember(3)]
+    assert typeids.get(400) == None
+    assert typeids.get(300) == None
+    assert typeids.get(200) == None
+    assert typeids.get(100) == None


More information about the pypy-commit mailing list