[pypy-svn] r50266 - in pypy/branch/asmgcroot/pypy: config rpython/memory/gctransform translator/c translator/c/src

arigo at codespeak.net arigo at codespeak.net
Wed Jan 2 17:52:50 CET 2008


Author: arigo
Date: Wed Jan  2 17:52:49 2008
New Revision: 50266

Added:
   pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/asmgcroot.py
      - copied, changed from r50261, pypy/branch/asmgcroot/pypy/rpython/memory/gctransform/llvmgcroot.py
Modified:
   pypy/branch/asmgcroot/pypy/config/translationoption.py
   pypy/branch/asmgcroot/pypy/translator/c/funcgen.py
   pypy/branch/asmgcroot/pypy/translator/c/gc.py
   pypy/branch/asmgcroot/pypy/translator/c/genc.py
   pypy/branch/asmgcroot/pypy/translator/c/src/mem.h
   pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py
Log:
Another in-progress check-in.


Modified: pypy/branch/asmgcroot/pypy/config/translationoption.py
==============================================================================
--- pypy/branch/asmgcroot/pypy/config/translationoption.py	(original)
+++ pypy/branch/asmgcroot/pypy/config/translationoption.py	Wed Jan  2 17:52:49 2008
@@ -64,8 +64,12 @@
                suggests=[("translation.gc", "marksweep")]),
     BoolOption("llvmgcroot", "Use the 'llvm.gcroot' primitive to find roots",
                default=False, cmdline="--llvmgcroot",
-               requires=[("translation.gctransformer", "framework")],
-               suggests=[("translation.backend", "llvm")]),
+               requires=[("translation.gctransformer", "framework"),
+                         ("translation.backend", "llvm")]),
+    BoolOption("asmgcroot", "Use the 'trackgcroot' asm hack to find roots",
+               default=False, cmdline="--asmgcroot",
+               requires=[("translation.gctransformer", "framework"),
+                         ("translation.backend", "c")]),
     BoolOption("thread", "enable use of threading primitives",
                default=False, cmdline="--thread",
                requires=[("translation.gc", "boehm")]),

Modified: pypy/branch/asmgcroot/pypy/translator/c/funcgen.py
==============================================================================
--- pypy/branch/asmgcroot/pypy/translator/c/funcgen.py	(original)
+++ pypy/branch/asmgcroot/pypy/translator/c/funcgen.py	Wed Jan  2 17:52:49 2008
@@ -217,16 +217,6 @@
 
     def cfunction_body(self):
         graph = self.graph
-
-        gcrootscount = 0
-        for block in graph.iterblocks():
-            for op in block.operations:
-                if op.opname == 'llvm_store_gcroot':
-                    index = op.args[0].value
-                    gcrootscount = max(gcrootscount, index+1)
-        for i in range(gcrootscount):
-            yield 'void* gcroot%d;' % i
-
         # generate the body of each block
         for block in graph.iterblocks():
             self.currentblock = block
@@ -732,16 +722,8 @@
     def OP_IS_EARLY_CONSTANT(self, op):
         return self.expr(op.result)  + ' = 0;' # Allways false
 
-    def OP_LLVM_STORE_GCROOT(self, op):
-        index = op.args[0].value
-        value = self.expr(op.args[1])
-        return ('gcroot%d = %s; ' % (index, value) +
-            'asm volatile ("/*STORE GCROOT %%0*/"::"m"(gcroot%d));' % (index,))
-
-    def OP_LLVM_LOAD_GCROOT(self, op):
-        index = op.args[0].value
-        result = self.expr(op.result)
-        return ('%s = gcroot%d; ' % (result, index) +
-            'asm volatile ("/*LOAD GCROOT %%0*/"::"m"(gcroot%d));' % (index,))
+    def OP_ASM_GCROOT(self, op):
+        value = self.expr(op.args[0])
+        return 'PYPY_GCROOT(%s);' % (value,)
 
 assert not USESLOTS or '__dict__' not in dir(FunctionCodeGenerator)

Modified: pypy/branch/asmgcroot/pypy/translator/c/gc.py
==============================================================================
--- pypy/branch/asmgcroot/pypy/translator/c/gc.py	(original)
+++ pypy/branch/asmgcroot/pypy/translator/c/gc.py	Wed Jan  2 17:52:49 2008
@@ -5,7 +5,7 @@
      typeOf, Ptr, ContainerType, RttiStruct, \
      RuntimeTypeInfo, getRuntimeTypeInfo, top_container
 from pypy.rpython.memory.gctransform import \
-     refcounting, boehm, framework, stacklessframework, llvmgcroot
+     refcounting, boehm, framework, stacklessframework, llvmgcroot, asmgcroot
 from pypy.rpython.lltypesystem import lltype, llmemory
 
 class BasicGcPolicy(object):
@@ -308,6 +308,9 @@
 class LLVMGcRootFrameworkGcPolicy(FrameworkGcPolicy):
     transformerclass = llvmgcroot.LLVMGcRootFrameworkGCTransformer
 
+class AsmGcRootFrameworkGcPolicy(FrameworkGcPolicy):
+    transformerclass = asmgcroot.AsmGcRootFrameworkGCTransformer
+
 
 name_to_gcpolicy = {
     'boehm': BoehmGcPolicy,
@@ -316,6 +319,7 @@
     'framework': FrameworkGcPolicy,
     'framework+stacklessgc': StacklessFrameworkGcPolicy,
     'framework+llvmgcroot': LLVMGcRootFrameworkGcPolicy,
+    'framework+asmgcroot': AsmGcRootFrameworkGcPolicy,
 }
 
 

Modified: pypy/branch/asmgcroot/pypy/translator/c/genc.py
==============================================================================
--- pypy/branch/asmgcroot/pypy/translator/c/genc.py	(original)
+++ pypy/branch/asmgcroot/pypy/translator/c/genc.py	Wed Jan  2 17:52:49 2008
@@ -95,6 +95,8 @@
                 name = "%s+stacklessgc" % (name,)
             if self.config.translation.llvmgcroot:
                 name = "%s+llvmgcroot" % (name,)
+            if self.config.translation.asmgcroot:
+                name = "%s+asmgcroot" % (name,)
             return gc.name_to_gcpolicy[name]
         return self.gcpolicy
 
@@ -275,8 +277,8 @@
             self.eci, compiler_exe = cc, profbased = profbased)
 
     def compile(self):
-        if self.config.translation.llvmgcroot:
-            raise Exception("Dunno how to compile with --llvmgcroot. "
+        if self.config.translation.asmgcroot:
+            raise Exception("Dunno how to compile with --asmgcroot. "
                             "Just go to the %s directory and type 'make'."
                             % (self.targetdir,))
         assert self.c_source_filename
@@ -318,6 +320,7 @@
             compiler.compile_extra.append(self.config.translation.compilerflags)
         if self.config.translation.linkerflags:
             compiler.link_extra.append(self.config.translation.linkerflags)
+        assert not self.config.translation.llvmgcroot
         cfiles = []
         ofiles = []
         for fn in compiler.cfilenames:
@@ -328,7 +331,7 @@
                 assert fn.dirpath().dirpath() == udir
                 name = '../' + fn.relto(udir)
             cfiles.append(name)
-            if self.config.translation.llvmgcroot:
+            if self.config.translation.asmgcroot:
                 ofiles.append(name[:-2] + '.s')
             else:
                 ofiles.append(name[:-2] + '.o')
@@ -349,13 +352,13 @@
         print >> f
         write_list(cfiles, 'SOURCES =')
         print >> f
-        if self.config.translation.llvmgcroot:
+        if self.config.translation.asmgcroot:
             write_list(ofiles, 'ASMFILES =')
             print >> f, 'OBJECTS = $(ASMFILES) gcmaptable.s'
         else:
             write_list(ofiles, 'OBJECTS =')
         print >> f
-        if self.config.translation.llvmgcroot:
+        if self.config.translation.asmgcroot:
             print >> f, 'TRACKGCROOT="%s"' % (os.path.join(autopath.this_dir,
                                                            'trackgcroot.py'),)
         print >> f

Modified: pypy/branch/asmgcroot/pypy/translator/c/src/mem.h
==============================================================================
--- pypy/branch/asmgcroot/pypy/translator/c/src/mem.h	(original)
+++ pypy/branch/asmgcroot/pypy/translator/c/src/mem.h	Wed Jan  2 17:52:49 2008
@@ -12,6 +12,7 @@
 extern char __gcmapend;
 extern char* __gcmap_frame_address(void);
 
+#define PYPY_GCROOT(p)  asm ("/* GCROOT %0 */" : "=g" (p) : "0" (p) : "memory")
 #define OP_LLVM_GCMAPSTART(r)	r = &__gcmapstart
 #define OP_LLVM_GCMAPEND(r)	r = &__gcmapend
 #define OP_LLVM_FRAMEADDRESS(r)	asm ("pypygetframeaddress %0" : "=r" (r))

Modified: pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py
==============================================================================
--- pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py	(original)
+++ pypy/branch/asmgcroot/pypy/translator/c/trackgcroot.py	Wed Jan  2 17:52:49 2008
@@ -27,7 +27,7 @@
 
 class GcRootTracker(object):
 
-    def __init__(self, verbose=False):
+    def __init__(self, verbose=0):
         self.gcmaptable = []
         self.verbose = verbose
 
@@ -85,10 +85,10 @@
         if self.verbose:
             print >> sys.stderr, '[trackgcroot:%s] %s' % (filename,
                                                           tracker.funcname)
-        table = tracker.computegcmaptable()
-        #if self.verbose:
-        #    for label, state in table:
-        #        print >> sys.stderr, label, '\t', state
+        table = tracker.computegcmaptable(self.verbose)
+        if self.verbose > 1:
+            for label, state in table:
+                print >> sys.stderr, label, '\t', state
         if tracker.can_use_frame_pointer:
             # XXX for now we have no logic to track the gc roots of
             # functions using %ebp
@@ -98,7 +98,7 @@
         if tracker.funcname == entrypoint:
             table = [(label, (-1,)) for label, _ in table]
             # ^^^ we set the framesize of the entry point to -1 as a marker
-            # (the code in llvmgcroot.py actually takes any odd-valued number
+            # (the code in asmgcroot.py actually takes any odd-valued number
             # as marker.)
         self.gcmaptable.extend(table)
         newfile.writelines(tracker.lines)
@@ -116,28 +116,45 @@
         self.inconsistent_state = {}
         self.can_use_frame_pointer = False      # unless changed by caller
 
-    def computegcmaptable(self):
+    def computegcmaptable(self, verbose=0):
         self.findlabels()
         self.parse_instructions()
+        if not self.enumerate_call_insns():
+            return []
+        self.makeprevmap()
         self.findframesize()
         self.fixlocalvars()
         self.trackgcroots()
-        self.dump()
-        xxx
-        self.follow_control_flow()
-        table = self.gettable()
         self.extend_calls_with_labels()
-        return table
+        if verbose > 2:
+            self.dump()
+        return self.gettable()
 
     def gettable(self):
         "Returns a list [(label_after_call, (framesize, gcroot0, gcroot1,..))]"
-        table = self.calls.items()
-        table.sort()   # by line number
-        table = [value for key, value in table]
+        table = []
+        for i, insn in self.enumerate_call_insns():
+            info = [self.framesize[i]]
+            # the first gcroots are always the ones corresponding to
+            # the callee-saved registers
+            for reg in CALLEE_SAVE_REGISTERS:
+                info.append(None)
+            for loc, tag in insn.gcroots.items():
+                if not isinstance(loc, int):
+                    # a special representation for a register location,
+                    # as an odd-valued number
+                    loc = CALLEE_SAVE_REGISTERS.index(loc) * 2 + 1
+                if tag is None:
+                    info.append(loc)
+                else:
+                    regindex = CALLEE_SAVE_REGISTERS.index(tag)
+                    info[1 + regindex] = loc
+            assert None not in info
+            table.append((insn.global_label, tuple(info)))
         return table
 
     def findlabels(self):
-        self.labels = {}
+        self.labels = {}      # {name: line number}
         for i, line in enumerate(self.lines):
             match = r_label.match(line)
             if match:
@@ -145,52 +162,69 @@
                 assert label not in self.labels, "duplicate label"
                 self.labels[label] = i
 
-    def extend_calls_with_labels(self):
-        self.missing_labels_after_call.sort()
-        self.missing_labels_after_call.reverse()
-        for linenum, label in self.missing_labels_after_call:
-            self.lines.insert(linenum, '%s:\n' % (label,))
-            self.lines.insert(linenum, '\t.globl\t%s\n' % (label,))
-
     def parse_instructions(self):
+        self.jumpsto = {}    # {label: [list-of-source-node-indices]}
+        for label in self.labels:
+            self.jumpsto[label] = []
         self.insns = [InsnFunctionStart()]
-        self.linenum = 0
+        self.line2nodeindex = {0: 0}
         in_APP = False
         for lin in range(1, len(self.lines)):
-            self.linenum = lin
-            insn = no_op
+            self.currentlineno = lin
+            insn = []
             line = self.lines[lin]
             match = r_insn.match(line)
             if match:
                 if not in_APP:
-                    insn = match.group(1)
-                    meth = getattr(self, 'visit_' + insn)
+                    opname = match.group(1)
+                    meth = getattr(self, 'visit_' + opname)
                     insn = meth(line)
             elif r_gcroot_marker.match(line):
-                insn = self.handle_gcroot_marker(line)
+                insn = self._visit_gcroot_marker(line)
             elif line == '#APP\n':
                 in_APP = True
             elif line == '#NO_APP\n':
                 in_APP = False
-            self.insns.append(insn)
-        del self.linenum
+            self.line2nodeindex.setdefault(lin, len(self.insns))
+            if isinstance(insn, list):
+                self.insns.extend(insn)
+            else:
+                self.insns.append(insn)
+            del self.currentlineno
+
+    def makeprevmap(self):
+        # builds the prevmap, which only accounts for jumps.  Each insn node
+        # has an implicit previous node, which is (obviously) the previous
+        # one in self.insns -- unless the previous one is an InsnStop.
+        self.prevmap = {}   # {node-index: [list-of-previous-node-indices]}
+        for label, sourceindices in self.jumpsto.items():
+            line = self.labels[label]
+            while line not in self.line2nodeindex:
+                assert line < len(self.lines), (
+                    "no Insn found after label %r" % (label,))
+                line += 1
+            self.prevmap[self.line2nodeindex[line]] = sourceindices
+
+    def enumerate_call_insns(self):
+        return [(i, insn) for (i, insn) in enumerate(self.insns)
+                          if isinstance(insn, InsnCall)]
 
     def findframesize(self):
         self.framesize = {0: 0}
 
-        def walker(lin, insn, size_delta):
-            check = deltas.setdefault(lin, size_delta)
+        def walker(i, insn, size_delta):
+            check = deltas.setdefault(i, size_delta)
             assert check == size_delta, (
-                "inconsistent frame size at function line %d" % (lin,))
+                "inconsistent frame size at instruction %d: %s" % (i, insn))
             if isinstance(insn, InsnStackAdjust):
                 size_delta -= insn.delta
-            if lin not in self.framesize:
+            if i not in self.framesize:
                 yield size_delta   # continue walking backwards
 
-        for lin, insn in enumerate(self.insns):
+        for i, insn in enumerate(self.insns):
             if insn.requestgcroots():
                 deltas = {}
-                self.walk_instructions_backwards(walker, lin, 0)
+                self.walk_instructions_backwards(walker, i, 0)
                 size_at_insn = []
                 for n in deltas:
                     if n in self.framesize:
@@ -202,32 +236,33 @@
                     size_at_n = size_at_insn - deltas[n]
                     check = self.framesize.setdefault(n, size_at_n)
                     assert check == size_at_n, (
-                        "inconsistent frame size at function line %d" % (n,))
+                        "inconsistent frame size at instruction %d: %s" % (
+                        n, self.insns[n]))
 
     def fixlocalvars(self):
-        for lin, insn in enumerate(self.insns):
-            if lin in self.framesize:
+        for i, insn in enumerate(self.insns):
+            if i in self.framesize:
                 for name in insn._locals_:
                     localvar = getattr(insn, name)
                     match = r_localvar_esp.match(localvar)
                     if match:
                         ofs_from_esp = int(match.group(1) or '0')
-                        localvar = ofs_from_esp - self.framesize[lin]
+                        localvar = ofs_from_esp - self.framesize[i]
                         assert localvar != 0    # that's the return address
                         setattr(insn, name, localvar)
 
     def trackgcroots(self):
 
-        def walker(lin, insn, loc):
+        def walker(i, insn, loc):
             source = insn.source_of(loc, tag)
             if isinstance(source, Value):
                 pass   # done
             else:
                 yield source
 
-        for lin, insn in enumerate(self.insns):
+        for i, insn in enumerate(self.insns):
             for loc, tag in insn.requestgcroots().items():
-                self.walk_instructions_backwards(walker, lin, loc)
+                self.walk_instructions_backwards(walker, i, loc)
 
     def dump(self):
         for n, insn in enumerate(self.insns):
@@ -237,117 +272,72 @@
                 size = '?'
             print '%4s  %s' % (size, insn)
 
-    def walk_instructions_backwards(self, walker, initial_line, initial_state):
+    def walk_instructions_backwards(self, walker, initial_i, initial_state):
         pending = []
         seen = {}
-        def schedule(line, state):
-            assert 0 <= line < len(self.insns)
-            key = line, state
+        def schedule(i, state):
+            assert 0 <= i < len(self.insns)
+            key = i, state
             if key not in seen:
                 seen[key] = True
                 pending.append(key)
-        schedule(initial_line, initial_state)
+        schedule(initial_i, initial_state)
         while pending:
-            line, state = pending.pop()
-            for prevstate in walker(line, self.insns[line], state):
-                schedule(line - 1, prevstate)
-
-    def follow_control_flow(self):
-        # 'states' is a list [(framesize, gcroot0, gcroot1, gcroot2...)]
-        self.states = [None] * len(self.lines)
-        self.pending = []
-        self.framesize = 0
-        self.gcroots = {}
-        self.propagate_state_to(1)
-        while self.pending:
-            lin = self.pending.pop()
-            self.follow_basic_block(lin)
-        self.check_all_calls_seen()
-
-    def getstate(self):
-        if self.gcroots is Bogus:
-            gcroots = ()
-        else:
-            gcroots = self.gcroots.keys()
-            gcroots.sort()
-        return (self.framesize,) + tuple(gcroots)
-
-    def propagate_state_to(self, lin):
-        state = self.getstate()
-        if self.states[lin] is None:
-            self.states[lin] = state
-            self.pending.append(lin)
-        elif self.states[lin] != state:
-            if lin not in self.inconsistent_state:
-                self.inconsistent_state[lin] = (self.states[lin], state)
-                raise ReflowCompletely
-
-    def follow_basic_block(self, lin):
-        state = self.states[lin]
-        self.framesize = state[0]
-        self.gcroots = dict.fromkeys(state[1:])
-        if lin in self.inconsistent_state:  # in case of inconsistent gcroots,
-            self.framesize = Bogus          # assume that we're about to leave
-        if self.framesize is Bogus:         # the function or fail an assert
-            self.gcroots = Bogus
-        line = '?'
-        self.in_APP = False
-        while 1:
-            try:
-                self.currentlinenum = lin
-                line = self.lines[lin]
-                match = r_insn.match(line)
-                if match:
-                    insn = match.group(1)
-                    try:
-                        meth = self.VISIT_OPERATION[insn]
-                    except KeyError:
-                        meth = self.find_visitor(insn)
-                    meth(self, line)
-                elif r_label.match(line):
-                    if not self.in_APP:    # ignore labels inside #APP/#NO_APP
-                        self.propagate_state_to(lin+1)
-                    break
-                elif r_gcroot_marker.match(line):
-                    self.handle_gcroot_marker(line)
-                elif line == '#APP\n':
-                    self.in_APP = True
-                elif line == '#NO_APP\n':
-                    self.in_APP = False
-                lin += 1
-            except LeaveBasicBlock:
-                if self.in_APP:  # ignore control flow inside #APP/#NO_APP
-                    lin += 1
-                    continue
-                break
-            except UnrecognizedOperation:
-                if self.in_APP:  # ignore strange ops inside #APP/#NO_APP
-                    lin += 1
-                    continue
-                raise
-            except ReflowCompletely:
-                raise
-            except Exception, e:
-                print >> sys.stderr, '*'*60
-                print >> sys.stderr, "%s while processing line:" % (
-                    e.__class__.__name__,)
-                print >> sys.stderr, line
-                raise
+            i, state = pending.pop()
+            for prevstate in walker(i, self.insns[i], state):
+                if not isinstance(self.insns[i - 1], InsnStop):
+                    schedule(i - 1, prevstate)
+                if i in self.prevmap:
+                    for previndex in self.prevmap[i]:
+                        schedule(previndex, prevstate)
 
-    def check_all_calls_seen(self):
-        for i, line in enumerate(self.lines):
-            match = r_insn.match(line)
+    def extend_calls_with_labels(self):
+        # walk backwards, because inserting the global labels in self.lines
+        # is going to invalidate the lineno of all the InsnCall objects
+        # after the current one.
+        for i, call in self.enumerate_call_insns()[::-1]:
+            self.create_global_label(call)
+
+    def create_global_label(self, call):
+        # we need a globally-declared label just after the call.
+        # Reuse one if it is already there (e.g. from a previous run of this
+        # script); otherwise invent a name and add the label to tracker.lines.
+        label = None
+        # this checks for a ".globl NAME" followed by "NAME:"
+        match = r_globl.match(self.lines[call.lineno+1])
+        if match:
+            label1 = match.group(1)
+            match = r_label.match(self.lines[call.lineno+2])
             if match:
-                insn = match.group(1)
-                if insn == 'call':
-                    assert i in self.calls or i in self.ignore_calls, (
-                        "unreachable call!" + line)
+                label2 = match.group(1)
+                if label1 == label2:
+                    label = label2
+        if label is None:
+            k = call.lineno
+            while 1:
+                label = '__gcmap_IN_%s_%d' % (self.funcname, k)
+                if label not in self.labels:
+                    break
+                k += 1
+            self.labels[label] = call.lineno+1
+            self.lines.insert(call.lineno+1, '%s:\n' % (label,))
+            self.lines.insert(call.lineno+1, '\t.globl\t%s\n' % (label,))
+        call.global_label = label
+
+    # ____________________________________________________________
 
-    def handle_gcroot_marker(self, line):
+    def _visit_gcroot_marker(self, line):
         match = r_gcroot_marker.match(line)
         loc = match.group(1)
         return InsnGCROOT(loc)
 
+    def visit_nop(self, line):
+        return []
+
+    NOP_PREFIXES = dict.fromkeys(['cmp', 'test', 'set',
+                                  'f',   # floating-point operations
+                                  ])
+
     def visit_addl(self, line, sign=+1):
         match = r_binaryinsn.match(line)
         target = match.group(2)
@@ -363,29 +353,63 @@
     def visit_subl(self, line):
         return self.visit_addl(line, sign=-1)
 
-    def visit_movl(self, line):
+    def unary_insn(self, line):
+        match = r_unaryinsn.match(line)
+        target = match.group(1)
+        if r_localvar.match(target):
+            return InsnSetLocal(Value(), target)
+        else:
+            raise UnrecognizedOperation(line)
+
+    visit_incl = unary_insn
+
+    def binary_insn(self, line):
         match = r_binaryinsn.match(line)
-        source = match.group(1)
         target = match.group(2)
         if r_localvar.match(target):
+            return InsnSetLocal(Value(), target)
+        else:
+            raise UnrecognizedOperation(line)
+
+    visit_xorl = binary_insn
+    visit_movzbl = binary_insn
+    visit_leal = binary_insn
+    visit_imull = binary_insn
+
+    def insns_for_copy(self, source, target):
+        if r_localvar.match(target):
             if r_localvar.match(source):
-                return InsnCopyLocal(source, target)
+                return [InsnCopyLocal(source, target)]
             else:
-                return InsnSetLocal(Value(), target)
+                return [InsnSetLocal(Value(), target)]
         elif target == '%esp':
             raise UnrecognizedOperation
         else:
-            return no_op
+            return []
+
+    def visit_movl(self, line):
+        match = r_binaryinsn.match(line)
+        source = match.group(1)
+        target = match.group(2)
+        return self.insns_for_copy(source, target)
+
+    def visit_pushl(self, line):
+        match = r_unaryinsn.match(line)
+        source = match.group(1)
+        return [InsnStackAdjust(-4)] + self.insns_for_copy(source, '(%esp)')
+
+    def visit_popl(self, line):
+        match = r_unaryinsn.match(line)
+        target = match.group(1)
+        return self.insns_for_copy('(%esp)', target) + [InsnStackAdjust(+4)]
 
     def visit_ret(self, line):
         return InsnRet()
 
     def visit_jmp(self, line):
-        xxx
-        if self.in_APP:
-            return       # ignore jumps inside a #APP/#NO_APP block
         match = r_jmp_switch.match(line)
         if match:
+            xxx
             # this is a jmp *Label(%index), used for table-based switches.
             # Assume that the table is just a list of lines looking like
             # .long LABEL or .long 0, ending in a .text.
@@ -401,7 +425,7 @@
             raise LeaveBasicBlock
         if r_unaryinsn_star.match(line):
             # that looks like an indirect tail-call.
-            raise LeaveBasicBlock
+            return InsnStop()
         try:
             self.conditional_jump(line)
         except KeyError:
@@ -409,16 +433,17 @@
             match = r_unaryinsn.match(line)
             target = match.group(1)
             assert not target.startswith('.')
-        raise LeaveBasicBlock
+        return InsnStop()
+
+    def register_jump_to(self, label):
+        currentpos = len(self.insns)
+        self.jumpsto[label].append(currentpos)
 
     def conditional_jump(self, line):
-        xxx
-        if self.in_APP:
-            return       # ignore jumps inside a #APP/#NO_APP block
         match = r_jump.match(line)
         label = match.group(1)
-        targetlin = self.labels[label]
-        self.propagate_state_to(targetlin)
+        self.register_jump_to(label)
+        return []
 
     visit_je = conditional_jump
     visit_jne = conditional_jump
@@ -445,7 +470,7 @@
             target = match.group(1)
             if target in FUNCTIONS_NOT_RETURNING:
                 return InsnStop()
-        return InsnCall()
+        return InsnCall(self.currentlineno)
 
     def visit_pypygetframeaddress(self, line):
         xxx
@@ -501,10 +526,6 @@
             self.arguments[localvar] = Value()
         return self.arguments[localvar]
 
-class NoOp(Insn):
-    pass
-no_op = NoOp()
-
 class InsnSetLocal(Insn):
     _args_ = ['value', 'target']
     _locals_ = ['target']
@@ -542,8 +563,8 @@
         return dict(zip(CALLEE_SAVE_REGISTERS, CALLEE_SAVE_REGISTERS))
 
 class InsnCall(Insn):
-    _args_ = ['gcroots']
-    def __init__(self):
+    _args_ = ['lineno', 'gcroots']
+    def __init__(self, lineno):
         # 'gcroots' is a dict built by side-effect during the call to
         # FunctionGcRootTracker.trackgcroots().  Its meaning is as follows:
         # the keys are the location that contain gc roots (either register
@@ -565,6 +586,8 @@
         # epilogue).
         #
         self.gcroots = {}
+        self.lineno = lineno
+
     def source_of(self, localvar, tag):
         self.gcroots[localvar] = tag
         return localvar
@@ -587,7 +610,7 @@
 
 
 if __name__ == '__main__':
-    tracker = GcRootTracker(verbose=True)
+    tracker = GcRootTracker(verbose=sys.maxint)
     for fn in sys.argv[1:]:
         tmpfn = fn + '.TMP'
         f = open(fn, 'r')


More information about the pypy-svn mailing list