[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