[pypy-svn] r35482 - in pypy/branch/jit-real-world/pypy: interpreter jit jit/codegen/i386 module/pypyjit

arigo at codespeak.net arigo at codespeak.net
Fri Dec 8 14:51:23 CET 2006


Author: arigo
Date: Fri Dec  8 14:51:20 2006
New Revision: 35482

Modified:
   pypy/branch/jit-real-world/pypy/interpreter/pyopcode.py
   pypy/branch/jit-real-world/pypy/jit/TODO.txt
   pypy/branch/jit-real-world/pypy/jit/codegen/i386/codebuf.py
   pypy/branch/jit-real-world/pypy/jit/codegen/i386/viewcode.py
   pypy/branch/jit-real-world/pypy/module/pypyjit/interp_jit.py
Log:
(pedronis, arigo)

A bug fix in our hacked interpreter main loop.
More JIT debugging support.


Modified: pypy/branch/jit-real-world/pypy/interpreter/pyopcode.py
==============================================================================
--- pypy/branch/jit-real-world/pypy/interpreter/pyopcode.py	(original)
+++ pypy/branch/jit-real-world/pypy/interpreter/pyopcode.py	Fri Dec  8 14:51:20 2006
@@ -109,8 +109,8 @@
         space = self.space
         while True:
             hint(None, global_merge_point=True)
+            self.last_instr = intmask(next_instr)
             if not we_are_translated():   # JJJ
-                self.last_instr = intmask(next_instr)
                 ec.bytecode_trace(self)
                 # For the sequel, force 'next_instr' to be unsigned for performance
                 next_instr = r_uint(self.last_instr)
@@ -152,6 +152,7 @@
                     continue    # now inside a 'finally' block
 
             if opcode == opcodedesc.YIELD_VALUE.index:
+                #self.last_instr = intmask(next_instr - 1) XXX clean up!
                 w_yieldvalue = self.valuestack.pop()
                 return w_yieldvalue
 

Modified: pypy/branch/jit-real-world/pypy/jit/TODO.txt
==============================================================================
--- pypy/branch/jit-real-world/pypy/jit/TODO.txt	(original)
+++ pypy/branch/jit-real-world/pypy/jit/TODO.txt	Fri Dec  8 14:51:20 2006
@@ -1,4 +1,4 @@
-- review codegen (e.g. getfield/setfield for size != word)
+- fix the XXXs in codegen
 
 - [] (getitem) used inside complex try/except ends up using the bound
   checking version: transformation after flowgraphing that marks op
@@ -36,3 +36,8 @@
 
 - reduce the size of the timeshifted code: no dispatch for no
   split/merge functions ...
+
+- insert hints to forget uninteresting constants, e.g. the
+  initial 0 of RPython list iterators
+
+- pyopcode.compare_dispatch_table => switch statement

Modified: pypy/branch/jit-real-world/pypy/jit/codegen/i386/codebuf.py
==============================================================================
--- pypy/branch/jit-real-world/pypy/jit/codegen/i386/codebuf.py	(original)
+++ pypy/branch/jit-real-world/pypy/jit/codegen/i386/codebuf.py	Fri Dec  8 14:51:20 2006
@@ -61,6 +61,7 @@
 class MachineCodeDumper:
     enabled = True
     log_fd = -1
+    sys_executable = None
 
     def open(self):
         if self.log_fd < 0:
@@ -77,6 +78,12 @@
                 os.write(2, "could not create log file\n")
                 self.enabled = False
                 return False
+            # log the executable name
+            from pypy.jit.codegen.hlinfo import highleveljitinfo
+            os.write(self.log_fd, 'BACKEND i386\n')
+            if highleveljitinfo.sys_executable:
+                os.write(self.log_fd, 'SYS_EXECUTABLE %s\n' % (
+                    highleveljitinfo.sys_executable,))
         return True
 
     def dump(self, cb, tag, pos, msg):

Modified: pypy/branch/jit-real-world/pypy/jit/codegen/i386/viewcode.py
==============================================================================
--- pypy/branch/jit-real-world/pypy/jit/codegen/i386/viewcode.py	(original)
+++ pypy/branch/jit-real-world/pypy/jit/codegen/i386/viewcode.py	Fri Dec  8 14:51:20 2006
@@ -20,24 +20,42 @@
 # Some support code from Psyco.  There is more over there,
 # I am porting it in a lazy fashion...  See py-utils/xam.py
 
-# the disassembler to use. 'objdump' writes GNU-style instructions.
-# 'ndisasm' uses Intel syntax.  XXX ndisasm output parsing is missing...
-
-objdump = 'objdump -b binary -m i386 --adjust-vma=%(origin)d -D %(file)s'
-#objdump = 'ndisasm -o %(origin)d -u %(file)s'
 if sys.platform == "win32":
     XXX   # lots more in Psyco
 
 def machine_code_dump(data, originaddr):
+    # the disassembler to use. 'objdump' writes GNU-style instructions.
+    # 'ndisasm' would use Intel syntax, but you need to fix the output parsing.
+    objdump = 'objdump -b binary -m i386 --adjust-vma=%(origin)d -D %(file)s'
+    #
     f = open(tmpfile, 'wb')
     f.write(data)
     f.close()
     g = os.popen(objdump % {'file': tmpfile, 'origin': originaddr}, 'r')
     result = g.readlines()
     g.close()
-    return result
+    return result[6:]   # drop some objdump cruft
+
+def load_symbols(filename):
+    # the program that lists symbols, and the output it gives
+    symbollister = 'nm %s'
+    re_symbolentry = re.compile(r'([0-9a-fA-F]+)\s\w\s(.*)')
+    #
+    symbols = {}
+    g = os.popen(symbollister % filename, "r")
+    for line in g:
+        match = re_symbolentry.match(line)
+        if match:
+            addr = long(match.group(1), 16)
+            name = match.group(2)
+            if name.startswith('pypy_g_'):
+                name = '\xb7' + name[7:]
+            symbols[addr] = name
+    g.close()
+    return symbols
 
-re_addr = re.compile(r'[\s,$]0x([0-9a-fA-F]+)')
+re_addr = re.compile(r'[\s,$]0x([0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]+)')
+re_lineaddr = re.compile(r'\s*0?x?([0-9a-fA-F]+)')
 
 def lineaddresses(line):
     result = []
@@ -56,7 +74,8 @@
 class CodeRange(object):
     fallthrough = False
 
-    def __init__(self, addr, data):
+    def __init__(self, world, addr, data):
+        self.world = world
         self.addr = addr
         self.data = data
 
@@ -87,7 +106,23 @@
     def disassemble(self):
         if not hasattr(self, 'text'):
             lines = machine_code_dump(self.data, self.addr)
-            self.text = ''.join(lines[6:])   # drop some objdump cruft
+            # instead of adding symbol names in the dumps we could
+            # also make the 0xNNNNNNNN addresses be red and show the
+            # symbol name when the mouse is over them
+            logentries = self.world.logentries
+            symbols = self.world.symbols
+            for i, line in enumerate(lines):
+                match = re_lineaddr.match(line)
+                if match:
+                    addr = long(match.group(1), 16)
+                    logentry = logentries.get(addr)
+                    if logentry:
+                        lines[i] = '\n%s\n%s' % (logentry, lines[i])
+                for addr in lineaddresses(line):
+                    sym = symbols.get(addr)
+                    if sym:
+                        lines[i] = '%s\t%s\n' % (lines[i].rstrip(), sym)
+            self.text = ''.join(lines)
         return self.text
 
     def findjumps(self):
@@ -112,6 +147,8 @@
         self.ranges = []
         self.labeltargets = {}
         self.jumps = {}
+        self.symbols = {}
+        self.logentries = {}
 
     def parse(self, f):
         for line in f:
@@ -123,7 +160,7 @@
                 offset = int(pieces[2][1:])
                 addr = baseaddr + offset
                 data = pieces[3].replace(':', '').decode('hex')
-                coderange = CodeRange(addr, data)
+                coderange = CodeRange(self, addr, data)
                 # XXX sloooooooow!
                 for r in self.ranges:
                     if addr < r.addr+len(r.data) and r.addr < addr+len(data):
@@ -131,6 +168,17 @@
                         break
                 else:
                     self.ranges.append(coderange)
+            elif line.startswith('LOG '):
+                pieces = line.split(None, 3)
+                assert pieces[1].startswith('@')
+                assert pieces[2].startswith('+')
+                baseaddr = long(pieces[1][1:], 16) & 0xFFFFFFFFL
+                offset = int(pieces[2][1:])
+                addr = baseaddr + offset
+                self.logentries[addr] = pieces[3]
+            elif line.startswith('SYS_EXECUTABLE '):
+                filename = line[len('SYS_EXECUTABLE '):].strip()
+                self.symbols.update(load_symbols(filename))
         # find cross-references between blocks
         for r in self.ranges:
             for lineno, targetaddr, _ in r.findjumps():
@@ -145,7 +193,7 @@
                 if i in t:
                     print i
                     ofs = i - r.addr
-                    self.ranges.append(CodeRange(i, r.data[ofs:]))
+                    self.ranges.append(CodeRange(self, i, r.data[ofs:]))
                     r.data = r.data[:ofs]
                     r.fallthrough = True
                     try:
@@ -161,7 +209,7 @@
             text, width = tab2columns(r.disassemble())
             text = '0x%x\n\n%s' % (r.addr, text)
             g1.emit_node('N_%x' % r.addr, shape="box", label=text,
-                         width=str(width*0.125))
+                         width=str(width*0.1125))
             for lineno, targetaddr, final in r.findjumps():
                 if final:
                     color = "black"
@@ -175,7 +223,7 @@
     lines = text.split('\n')
     columnwidth = []
     for line in lines:
-        columns = line.split('\t')
+        columns = line.split('\t')[:-1]
         while len(columnwidth) < len(columns):
             columnwidth.append(0)
         for i, s in enumerate(columns):
@@ -183,6 +231,7 @@
             if not s.endswith(':'):
                 width += 2
             columnwidth[i] = max(columnwidth[i], width)
+    columnwidth.append(1)
     result = []
     for line in lines:
         columns = line.split('\t')
@@ -190,10 +239,9 @@
         for width, s in zip(columnwidth, columns):
             text.append(s.strip().ljust(width))
         result.append(' '.join(text))
-    if result:
-        totalwidth = len(result[0])
-    else:
-        totalwidth = 1
+    lengths = [len(line) for line in result]
+    lengths.append(1)
+    totalwidth = max(lengths)
     return '\\l'.join(result), totalwidth
 
 # ____________________________________________________________

Modified: pypy/branch/jit-real-world/pypy/module/pypyjit/interp_jit.py
==============================================================================
--- pypy/branch/jit-real-world/pypy/module/pypyjit/interp_jit.py	(original)
+++ pypy/branch/jit-real-world/pypy/module/pypyjit/interp_jit.py	Fri Dec  8 14:51:20 2006
@@ -73,5 +73,14 @@
 # Public interface
 
 def enable(space, w_code, w_enabled=True):
+    # save the app-level sys.executable in JITInfo, where the machine
+    # code backend can fish for it - XXX the following import will look
+    # less obscure once codebuf.py is moved to a general
+    # processor-independent place
+    from pypy.jit.codegen.hlinfo import highleveljitinfo
+    if highleveljitinfo.sys_executable is None:
+        highleveljitinfo.sys_executable = space.str_w(
+            space.sys.get('executable'))
+
     code = space.interp_w(PyCode, w_code)
     code.jit_enable = space.is_true(w_enabled)



More information about the Pypy-commit mailing list