[pypy-svn] r63225 - in pypy/branch/pyjitpl5-simplify/pypy/jit: backend/llgraph metainterp

arigo at codespeak.net arigo at codespeak.net
Mon Mar 23 13:29:13 CET 2009


Author: arigo
Date: Mon Mar 23 13:29:10 2009
New Revision: 63225

Modified:
   pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/llimpl.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/executor.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/graphpage.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py
   pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/warmspot.py
Log:
Intermediate checkin: introduce the new model of operations
and port graphpage.py to display it.


Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/llimpl.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/llimpl.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/llimpl.py	Mon Mar 23 13:29:10 2009
@@ -125,14 +125,20 @@
 
 # ____________________________________________________________
 
-class LoopOrBridge(object):
+class CompiledLoop(object):
     def __init__(self):
         self.operations = []
 
     def __repr__(self):
-        lines = ['\t' + repr(op) for op in self.operations]
-        lines.insert(0, 'LoopOrBridge:')
-        return '\n'.join(lines)
+        lines = []
+        self.as_text(lines, 1)
+        return 'CompiledLoop:\n%s' % '\n'.join(lines)
+
+    def as_text(self, lines, indent):
+        for op in self.operations:
+            lines.append('\t'*indent + repr(op))
+            if op.is_guard():
+                op.subloop.as_text(lines, indent+1)
 
 class Operation(object):
     def __init__(self, opnum):
@@ -156,6 +162,9 @@
         except KeyError:
             return '<%d>' % self.opnum
 
+    def is_guard(self):
+        return rop._GUARD_FIRST <= self.opnum <= rop._GUARD_LAST
+
 def repr0(x):
     if isinstance(x, list):
         return '[' + ', '.join(repr0(y) for y in x) + ']'
@@ -228,7 +237,7 @@
 
 def compile_start():
     del _variables[:]
-    return _to_opaque(LoopOrBridge())
+    return _to_opaque(CompiledLoop())
 
 def compile_start_int_var(loop):
     loop = _from_opaque(loop)
@@ -299,6 +308,7 @@
     return r
 
 def compile_add_jump_target(loop, loop_target, loop_target_index):
+    xxx
     loop = _from_opaque(loop)
     loop_target = _from_opaque(loop_target)
     op = loop.operations[-1]
@@ -310,23 +320,12 @@
         else:
             log.info("compiling new bridge")
 
-def compile_add_failnum(loop, failnum):
-    loop = _from_opaque(loop)
-    op = loop.operations[-1]
-    op.failnum = failnum
-
-def compile_add_livebox(loop, intvar):
+def compile_suboperations(loop):
     loop = _from_opaque(loop)
     op = loop.operations[-1]
-    op.livevars.append(_variables[intvar])
-
-def compile_from_guard(loop, guard_loop, guard_opindex):
-    loop = _from_opaque(loop)
-    guard_loop = _from_opaque(guard_loop)
-    op = guard_loop.operations[guard_opindex]
-    assert rop._GUARD_FIRST <= op.opnum <= rop._GUARD_LAST
-    op.jump_target = loop
-    op.jump_target_index = 0
+    assert op.is_guard()
+    op.subloop = CompiledLoop()
+    return _to_opaque(op.subloop)
 
 # ------------------------------
 
@@ -936,19 +935,19 @@
                 return hop.genop('direct_call', [cfunc] + args_v, hop.r_result)
 
 
-LOOPORBRIDGE = lltype.Ptr(lltype.OpaqueType("LoopOrBridge"))
+COMPILEDLOOP = lltype.Ptr(lltype.OpaqueType("CompiledLoop"))
 FRAME = lltype.Ptr(lltype.OpaqueType("Frame"))
 MEMOCAST = lltype.Ptr(lltype.OpaqueType("MemoCast"))
 
-_TO_OPAQUE[LoopOrBridge] = LOOPORBRIDGE.TO
+_TO_OPAQUE[CompiledLoop] = COMPILEDLOOP.TO
 _TO_OPAQUE[Frame] = FRAME.TO
 _TO_OPAQUE[MemoCast] = MEMOCAST.TO
 
-s_LoopOrBridge = annmodel.SomePtr(LOOPORBRIDGE)
+s_CompiledLoop = annmodel.SomePtr(COMPILEDLOOP)
 s_Frame = annmodel.SomePtr(FRAME)
 s_MemoCast = annmodel.SomePtr(MEMOCAST)
 
-setannotation(compile_start, s_LoopOrBridge)
+setannotation(compile_start, s_CompiledLoop)
 setannotation(compile_start_int_var, annmodel.SomeInteger())
 setannotation(compile_start_ptr_var, annmodel.SomeInteger())
 setannotation(compile_add, annmodel.s_None)
@@ -959,9 +958,6 @@
 setannotation(compile_add_int_result, annmodel.SomeInteger())
 setannotation(compile_add_ptr_result, annmodel.SomeInteger())
 setannotation(compile_add_jump_target, annmodel.s_None)
-setannotation(compile_add_failnum, annmodel.s_None)
-setannotation(compile_from_guard, annmodel.s_None)
-setannotation(compile_add_livebox, annmodel.s_None)
 
 setannotation(new_frame, s_Frame)
 setannotation(frame_clear, annmodel.s_None)

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/backend/llgraph/runner.py	Mon Mar 23 13:29:10 2009
@@ -57,31 +57,25 @@
                  annmixlevel=None):
         self.rtyper = rtyper
         self.translate_support_code = translate_support_code
-        self.jumptarget2loop = {}
-        self.guard_ops = []
-        self.compiled_single_ops = {}
         self.stats = stats or MiniStats()
         self.stats.exec_counters = {}
         self.stats.exec_jumps = 0
         self.memo_cast = llimpl.new_memo_cast()
         llimpl._stats = self.stats
-        llimpl._rtyper = self.rtyper
         llimpl._llinterp = LLInterpreter(self.rtyper)
         if translate_support_code:
             self.mixlevelann = annmixlevel
         self.fielddescrof_vtable = self.fielddescrof(rclass.OBJECT, 'typeptr')
 
-    def set_meta_interp(self, metainterp):
-        self.metainterp = metainterp    # to handle guard failures
-
-    def compile_operations(self, operations, from_guard=None):
+    def compile_operations(self, loop):
         """In a real assembler backend, this should assemble the given
         list of operations.  Here we just generate a similar LoopOrBridge
         instance.  The code here is RPython, whereas the code in llimpl
         is not.
         """
-
+        operations = loop.operations
         c = llimpl.compile_start()
+        loop._compiled_version = c
         var2index = {}
         for i in range(len(operations[0].args)):
             box = operations[0].args[i]
@@ -89,18 +83,12 @@
                 var2index[box] = llimpl.compile_start_int_var(c)
             elif isinstance(box, history.BoxPtr):
                 var2index[box] = llimpl.compile_start_ptr_var(c)
-            elif isinstance(box, history.Const):
-                pass     # accept anything and ignore it
             else:
                 raise Exception("box is: %r" % (box,))
-        j = 0
-        for i in range(len(operations)):
-            op = operations[i]
-            #if op.opname[0] == '#':
-            #    continue
-            op._compiled = c
-            op._opindex = j
-            j += 1
+        self._compile_branch(c, operations[1:], var2index)
+
+    def _compile_branch(self, c, operations, var2index):
+        for op in operations:
             llimpl.compile_add(c, op.opnum)
             if op.descr is not None:
                 llimpl.compile_add_descr(c, op.descr.ofs, op.descr.type)
@@ -116,6 +104,9 @@
                 else:
                     raise Exception("%s args contain: %r" % (op.getopname(),
                                                              x))
+            if op.is_guard():
+                c2 = llimpl.compile_suboperations(c)
+                self._compile_branch(c2, op.suboperations, var2index.copy())
             x = op.result
             if x is not None:
                 if isinstance(x, history.BoxInt):
@@ -125,31 +116,14 @@
                 else:
                     raise Exception("%s.result contain: %r" % (op.getopname(),
                                                                x))
-            if op.jump_target is not None:
-                loop_target, loop_target_index = \
-                                           self.jumptarget2loop[op.jump_target]
-                llimpl.compile_add_jump_target(c, loop_target,
-                                                  loop_target_index)
-            if op.is_guard():
-                llimpl.compile_add_failnum(c, len(self.guard_ops))
-                self.guard_ops.append(op)
-                for box in op.liveboxes:
-                    assert isinstance(box, history.Box)
-                    llimpl.compile_add_livebox(c, var2index[box])
-            if op.opnum == rop.MERGE_POINT:
-                self.jumptarget2loop[op] = c, i
-        if from_guard is not None:
-            llimpl.compile_from_guard(c, from_guard._compiled,
-                                         from_guard._opindex)
-
-    def execute_operations_in_new_frame(self, name, operations, valueboxes):
-        """Perform a 'call' to the given merge point, i.e. create
-        a new CPU frame and use it to execute the operations that
-        follow the merge point.
+        llimpl.compile_add_jump_target(c, op.target_jump._compiled_version)
+
+    def execute_operations(self, loop, valueboxes):
+        """Calls the assembler generated for the given loop.
         """
         frame = llimpl.new_frame(self.memo_cast)
-        merge_point = operations[0]
-        llimpl.frame_clear(frame, merge_point._compiled, merge_point._opindex)
+        # setup the frame
+        llimpl.frame_clear(frame, loop._compiled_version)
         for box in valueboxes:
             if isinstance(box, history.BoxInt):
                 llimpl.frame_add_int(frame, box.value)
@@ -161,56 +135,15 @@
                 llimpl.frame_add_ptr(frame, box.value)
             else:
                 raise Exception("bad box in valueboxes: %r" % (box,))
-        return self.loop(frame)
-
-    def loop(self, frame):
-        """Execute a loop.  When the loop fails, ask the metainterp for more.
-        """
-        while True:
-            guard_index = llimpl.frame_execute(frame)
-            guard_op = self.guard_ops[guard_index]
-            assert isinstance(lltype.typeOf(frame), lltype.Ptr)
-            gf = GuardFailed(frame, guard_op)
-            self.metainterp.handle_guard_failure(gf)
-            if gf.returns:
-                return gf.retbox
-
-    def getvaluebox(self, frame, guard_op, argindex):
-        box = guard_op.liveboxes[argindex]
-        if isinstance(box, history.BoxInt):
-            value = llimpl.frame_int_getvalue(frame, argindex)
-            return history.BoxInt(value)
-        elif isinstance(box, history.BoxPtr):
-            value = llimpl.frame_ptr_getvalue(frame, argindex)
-            return history.BoxPtr(value)
-        else:
-            raise AssertionError('getvalue: box = %s' % (box,))
-
-    def setvaluebox(self, frame, guard_op, argindex, valuebox):
-        if isinstance(valuebox, history.BoxInt):
-            llimpl.frame_int_setvalue(frame, argindex, valuebox.value)
-        elif isinstance(valuebox, history.BoxPtr):
-            llimpl.frame_ptr_setvalue(frame, argindex, valuebox.value)
-        elif isinstance(valuebox, history.ConstInt):
-            llimpl.frame_int_setvalue(frame, argindex, valuebox.value)
-        elif isinstance(valuebox, history.ConstPtr):
-            llimpl.frame_ptr_setvalue(frame, argindex, valuebox.value)
-        elif isinstance(valuebox, history.ConstAddr):
-            llimpl.frame_int_setvalue(frame, argindex, valuebox.getint())
+        # run the loop
+        result = llimpl.frame_execute(frame)
+        # get the exception to raise and really raise it, if any
+        exception_addr = llimpl.frame_get_exception(frame)
+        if exception_addr:
+            exc_value_gcref = llimpl.frame_get_exc_value(frame)
+            xxxx
         else:
-            raise AssertionError('setvalue: valuebox = %s' % (valuebox,))
-
-    def get_exception(self):
-        return self.cast_adr_to_int(llimpl.get_exception())
-
-    def get_exc_value(self):
-        return llimpl.get_exc_value()
-
-    def clear_exception(self):
-        llimpl.clear_exception()
-
-    def set_overflow_error(self):
-        llimpl.set_overflow_error()
+            return result
 
     @staticmethod
     def sizeof(S):

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/compile.py	Mon Mar 23 13:29:10 2009
@@ -5,7 +5,7 @@
 from pypy.conftest import option
 
 from pypy.jit.metainterp.resoperation import ResOperation, rop
-from pypy.jit.metainterp.history import Graph, log, Box
+from pypy.jit.metainterp.history import Loop, log, Box
 from pypy.jit.metainterp import optimize
 
 
@@ -52,11 +52,11 @@
             loop = compile_fresh_loop(metainterp, loop, old_loops,
                                       endliveboxes)
         except Exception, exc:
-            show_loop(metainterp, loop, loop.operations[0], exc)
+            show_loop(metainterp, loop, error=exc)
             raise
         else:
             if loop == orgloop:
-                show_loop(metainterp, loop, loop.operations[0], None)
+                show_loop(metainterp, loop)
             else:
                 log.info("reusing loop at %r" % (loop,))
     except optimize.CancelInefficientLoop:
@@ -71,11 +71,11 @@
             bridge = compile_fresh_bridge(metainterp, bridge, old_loops,
                                           endliveboxes)
         except Exception, exc:
-            show_loop(metainterp, bridge, None, exc)
+            show_loop(metainterp, bridge, error=exc)
             raise
         else:
             if bridge == orgbridge:
-                show_loop(metainterp, bridge, None, None)
+                show_loop(metainterp, bridge)
             elif bridge is not None:
                 log.info("reusing bridge at %r" % (bridge,))
             else:
@@ -86,7 +86,7 @@
         bridge.check_consistency()
     return bridge
 
-def show_loop(metainterp, loop, mp=None, error=None):
+def show_loop(metainterp, loop, error=None):
     # debugging
     if option.view:
         if error:
@@ -95,39 +95,22 @@
                 errmsg += ': ' + str(error)
         else:
             errmsg = None
-        loop.show(in_stats=metainterp.stats, errmsg=errmsg,
-                  highlightops=find_highlight_ops(metainterp.history, mp))
-
-def find_highlight_ops(history, mp=None):
-    result = {}
-    for op in history.operations[::-1]:
-        result[op] = True
-        if op is mp:
-            break
-    return result
+        loop.show(errmsg=errmsg)
 
 def create_empty_loop(metainterp):
     if we_are_translated():
         name = 'Loop'
     else:
         name = 'Loop #%d' % len(metainterp.stats.loops)
-    graph = Graph(name, '#f084c2')
-    return graph
-
-def create_empty_bridge(metainterp):
-    if we_are_translated():
-        name = 'Bridge'
-    else:
-        name = 'Bridge #%d' % len(metainterp.stats.loops)
-    graph = Graph(name, '#84f0c2')
-    return graph
+    return Loop(name)
 
 # ____________________________________________________________
 
 def compile_fresh_loop(metainterp, loop, old_loops, endliveboxes):
     history = metainterp.history
+    loop.inputargs = history.inputargs
     loop.operations = history.operations
-    close_loop(loop, loop.operations[0], endliveboxes)
+    close_loop(loop, endliveboxes)
     old_loop = optimize.optimize_loop(metainterp.options, old_loops, loop,
                                       metainterp.cpu)
     if old_loop is not None:
@@ -136,17 +119,16 @@
     old_loops.append(loop)
     return loop
 
-def close_loop(loop, targetmp, endliveboxes):
-    assert targetmp.opnum == rop.MERGE_POINT
+def close_loop(loop, endliveboxes):
     op = ResOperation(rop.JUMP, endliveboxes, None)
-    op.jump_target = targetmp
+    op.jump_target = loop
     loop.operations.append(op)
 
-def finish_loop_or_bridge(metainterp, loop, targetmp, guard_op=None):
+def finish_loop_or_bridge(metainterp, loop, targetmp):
     assert targetmp.opnum == rop.MERGE_POINT
     assert loop.operations[-1].opnum == rop.JUMP
     loop.operations[-1].jump_target = targetmp
-    metainterp.cpu.compile_operations(loop.operations, guard_op)
+    metainterp.cpu.compile_operations(loop)
     metainterp.stats.loops.append(loop)
 
 # ____________________________________________________________

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/executor.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/executor.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/executor.py	Mon Mar 23 13:29:10 2009
@@ -192,7 +192,7 @@
     execute = [None] * (rop._LAST+1)
     for key, value in rop.__dict__.items():
         if not key.startswith('_'):
-            if (rop._SPECIAL_FIRST <= value <= rop._SPECIAL_LAST or
+            if (rop._FINAL_FIRST <= value <= rop._FINAL_LAST or
                 rop._GUARD_FIRST <= value <= rop._GUARD_LAST):
                 continue
             if execute[value] is not None:

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/graphpage.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/graphpage.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/graphpage.py	Mon Mar 23 13:29:10 2009
@@ -4,10 +4,28 @@
 from pypy.jit.metainterp.history import Box
 
 
+class SubGraph:
+    def __init__(self, suboperations):
+        self.suboperations = suboperations
+    def get_operations(self):
+        return self.suboperations
+    def get_display_text(self):
+        return None
+
+def display_loops(loops, errmsg=None):
+    graphs = loops[:]
+    for graph in graphs:
+        for op in graph.get_operations():
+            if op.is_guard():
+                graphs.append(SubGraph(op.suboperations))
+    graphpage = ResOpGraphPage(graphs, errmsg)
+    graphpage.display()
+
+
 class ResOpGraphPage(GraphPage):
 
-    def compute(self, graphs, errmsg=None, highlightops={}):
-        resopgen = ResOpGen(highlightops)
+    def compute(self, graphs, errmsg=None):
+        resopgen = ResOpGen()
         for graph in graphs:
             resopgen.add_graph(graph)
         if errmsg:
@@ -20,11 +38,10 @@
     CLUSTERING = True
     BOX_COLOR = (128, 0, 96)
 
-    def __init__(self, highlightops):
+    def __init__(self):
         self.graphs = []
         self.block_starters = {}    # {graphindex: {set-of-operation-indices}}
         self.all_operations = {}
-        self.highlightops = highlightops
         self.errmsg = None
 
     def op_name(self, graphindex, opindex):
@@ -43,18 +60,9 @@
         for graphindex in range(len(self.graphs)):
             self.block_starters[graphindex] = {0: True}
         for graphindex, graph in enumerate(self.graphs):
-            prevop = None
             for i, op in enumerate(graph.get_operations()):
-                for attrname, delta in [('jump_target', 0),
-                                        ('_jump_target_prev', 1)]:
-                    tgt = getattr(op, attrname, None)
-                    if tgt is not None and tgt in self.all_operations:
-                        tgt_g, tgt_i = self.all_operations[tgt]
-                        self.mark_starter(tgt_g, tgt_i+delta)
-                        self.mark_starter(graphindex, i+1)
-                if (op in self.highlightops) != (prevop in self.highlightops):
-                    self.mark_starter(graphindex, i)
-                prevop = op
+                if op.is_guard():
+                    self.mark_starter(graphindex, i+1)
 
     def set_errmsg(self, errmsg):
         self.errmsg = errmsg
@@ -68,11 +76,7 @@
         _prev = Box._extended_display
         try:
             Box._extended_display = False
-            if len(self.graphs) > 1:
-                graphs = self.graphs[1:]
-            else:
-                graphs = self.graphs
-            for i, graph in enumerate(graphs):
+            for i, graph in enumerate(self.graphs):
                 self.gengraph(graph, i)
         finally:
             Box._extended_display = _prev
@@ -99,17 +103,16 @@
         graphname = self.getgraphname(graphindex)
         if self.CLUSTERING:
             self.dotgen.emit('subgraph cluster%d {' % graphindex)
-        self.dotgen.emit_node(graphname, shape="octagon",
-                              label=graph.get_display_text(),
-                              fillcolor=graph.color)
-
-        operations = graph.get_operations()
-        if operations:
+        label = graph.get_display_text()
+        if label is not None:
+            self.dotgen.emit_node(graphname, shape="octagon",
+                                  label=label, fillcolor='#f084c2')
             self.pendingedges.append((graphname,
                                       self.op_name(graphindex, 0),
                                       {}))
-            for opindex in self.block_starters[graphindex]:
-                self.genblock(operations, graphindex, opindex)
+        operations = graph.get_operations()
+        for opindex in self.block_starters[graphindex]:
+            self.genblock(operations, graphindex, opindex)
         if self.CLUSTERING:
             self.dotgen.emit('}')   # closes the subgraph
 
@@ -125,56 +128,35 @@
         block_starters = self.block_starters[graphindex]
         lines = []
         opindex = opstartindex
-        op = None
         while True:
             op = operations[opindex]
             lines.append(repr(op))
-            #if op.opname == 'jump':
-            #    self.genjump(blockname, op)
-            for attrname, delta in [('jump_target', 0),
-                                    ('_jump_target_prev', 1)]:
-                tgt = getattr(op, attrname, None)
-                if tgt is not None and tgt in self.all_operations:
-                    tgt_g, tgt_i = self.all_operations[tgt]
-                    kwds = {}
-                    #if op.opname == 'jump':
-                    #    #kwds['constraint'] = 'false'
-                    #    #kwds['headport'] = ':n'
-                    #    pass
-                    self.genedge((graphindex, opstartindex),
-                                 (tgt_g, tgt_i+delta),
-                                 color='red',
-                                 **kwds)
+            if op.is_guard():
+                tgt = op.suboperations[0]
+                tgt_g, tgt_i = self.all_operations[tgt]
+                self.genedge((graphindex, opstartindex),
+                             (tgt_g, tgt_i),
+                             color='red')
             opindex += 1
             if opindex >= len(operations):
                 break
             if opindex in block_starters:
-                kwds = {}
-                #if op.opname == 'jump':
-                #    kwds['color'] = '#d0d0ff'
                 self.genedge((graphindex, opstartindex),
-                             (graphindex, opindex), **kwds)
+                             (graphindex, opindex))
                 break
+        tgt = getattr(op, 'jump_target', None)
+        if tgt is not None and tgt in self.graphs:
+            tgt_g = self.graphs.index(tgt)
+            self.genedge((graphindex, opstartindex),
+                         (tgt_g, 0))
         lines.append("")
         label = "\\l".join(lines)
         kwds = {}
-        if op in self.highlightops:
-            kwds['color'] = 'red'
-            kwds['fillcolor'] = '#ffe8e8'
+        #if op in self.highlightops:
+        #    kwds['color'] = 'red'
+        #    kwds['fillcolor'] = '#ffe8e8'
         self.dotgen.emit_node(blockname, shape="box", label=label, **kwds)
 
-    def genjump(self, srcblockname, op):
-        graph1 = op.gettargetloop().graph
-        try:
-            graphindex = self.graphs.index(graph1)
-        except ValueError:
-            return
-        self.pendingedges.append((srcblockname,
-                                  self.op_name(graphindex, 0),
-                                  {'color': graph1.color,
-                                   #'headport': ':n',
-                                   }))
-
     def getlinks(self):
         boxes = {}
         for op in self.all_operations:

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/history.py	Mon Mar 23 13:29:10 2009
@@ -320,65 +320,74 @@
 
 # ____________________________________________________________
 
-# The Graph class is to store a loop or a bridge.
-# Unclear if it's really useful any more; just the list of operations
-# is enough in most cases.
+# The Loop class contains a loop or a generalized loop, i.e. a tree
+# of operations.  Each branch ends in a jump which can go either to
+# the top of the same loop, or to another loop.
+
+class Loop(object):
+    inputargs = None
+    operations = None
 
-class Graph(object):
-
-    def __init__(self, name, color):
+    def __init__(self, name):
         self.name = name
-        self.color = color
-        self.operations = []
+        # self.inputargs = list of distinct Boxes
+        # self.operations = ops of the kind 'guard_xxx' contain a further
+        #                   list of operations, which may itself contain
+        #                   'guard_xxx' and so on, making a tree.
 
-    def get_operations(self):
-        return self.operations
+    def _all_operations(self):
+        "NOT_RPYTHON"
+        oplist = list(self.operations)
+        for op in oplist:
+            if op.is_guard():
+                oplist += op.suboperations
+        return oplist
 
     def summary(self, adding_insns={}):    # for debugging
+        "NOT_RPYTHON"
         insns = adding_insns.copy()
-        for op in self.operations:
+        for op in self._all_operations():
             opname = op.getopname()
             insns[opname] = insns.get(opname, 0) + 1
         return insns
 
+    def get_operations(self):
+        return self.operations
+
     def get_display_text(self):    # for graphpage.py
-        return self.name
+        return self.name + '\n' + repr(self.inputargs)
 
-    def show(self, in_stats=None, errmsg=None, highlightops={}):
-        if in_stats is None:
-            from pypy.jit.metainterp.graphpage import ResOpGraphPage
-            ResOpGraphPage([self], errmsg, highlightops).display()
-        else:
-            h = dict.fromkeys(self.operations)
-            h.update(highlightops)
-            in_stats.view(errmsg=errmsg, extragraphs=[self],
-                          highlightops=h)
-
-    def copy(self):    # for testing only
-        g = Graph(self.name, self.color)
-        g.operations = self.operations[:]
-        return g
+    def show(self, errmsg=None):
+        "NOT_RPYTHON"
+        from pypy.jit.metainterp.graphpage import display_loops
+        display_loops([self], errmsg)
 
     def check_consistency(self):     # for testing
         "NOT_RPYTHON"
-        operations = self.operations
-        op = operations[0]
-        assert op.opnum in (rop.MERGE_POINT, rop.CATCH)
-        seen = dict.fromkeys(op.args)
+        for box in self.inputargs:
+            assert isinstance(box, Box), "Loop.inputargs contains %r" % (box,)
+        seen = dict.fromkeys(self.inputargs)
+        assert len(seen) == len(self.inputargs), (
+               "duplicate Box in the Loop.inputargs")
+        self.check_consistency_of_branch(self.operations, seen)
+
+    def check_consistency_of_branch(self, operations, seen):
+        "NOT_RPYTHON"
         for op in operations:
             for box in op.args:
                 if isinstance(box, Box):
                     assert box in seen
-                elif isinstance(box, Const):
-                    assert op.opnum != rop.MERGE_POINT, (
-                        "no Constant arguments allowed in: %s" % (op,))
+            assert (op.suboperations is not None) == op.is_guard()
+            if op.is_guard():
+                self.check_consistency_of_branch(op.suboperations, seen.copy())
             box = op.result
             if box is not None:
                 assert isinstance(box, Box)
                 assert box not in seen
                 seen[box] = True
-        assert operations[-1].opnum == rop.JUMP
-        assert operations[-1].jump_target.opnum == rop.MERGE_POINT
+        assert operations[-1].is_final()
+        if operations[-1].opnum == rop.JUMP:
+            assert isinstance(operations[-1].jump_target, Loop)
 
     def __repr__(self):
         return '<%s>' % (self.name,)
@@ -386,12 +395,10 @@
 # ____________________________________________________________
 
 
-class Matcher(object):
-    pass
-
-class RunningMatcher(Matcher):
+class RunningMatcher(object):
     def __init__(self, cpu):
         self.cpu = cpu
+        self.inputargs = None
         self.operations = []
     def record(self, opnum, argboxes, resbox, descr=None):
         raise NotImplementedError
@@ -406,6 +413,7 @@
     def record(self, opnum, argboxes, resbox, descr=None):
         return None
 
+
 def mp_eq(greenkey1, greenkey2):
     assert len(greenkey1) == len(greenkey2)
     for i in range(len(greenkey1)):
@@ -428,21 +436,10 @@
     """For tests."""
 
     def __init__(self):
-        self.history_graph = Graph('History', '#8080ff')
         self.loops = []
 
-    def get_all_graphs(self):
-        graphs = [self.history_graph] + self.loops
-        return graphs
-
-    def check_history(self, expected=None, **check):
-        insns = self.history_graph.summary()
-        if expected is not None:
-            expected.setdefault('catch', 1)   # it always starts with a catch
-            assert insns == expected
-        for insn, expected_count in check.items():
-            assert insns.get(insn, 0) == expected_count
-        return insns
+    def get_all_loops(self):
+        return self.loops
 
     def check_loops(self, expected=None, **check):
         insns = {}
@@ -463,14 +460,14 @@
         if option.view:
             self.view()
 
-    def view(self, errmsg=None, extragraphs=[], highlightops={}):
-        from pypy.jit.metainterp.graphpage import ResOpGraphPage
-        graphs = self.get_all_graphs()
-        for graph in extragraphs:
-            if graph in graphs:
-                graphs.remove(graph)
-            graphs.append(graph)
-        ResOpGraphPage(graphs, errmsg, highlightops).display()
+    def view(self, errmsg=None, extraloops=[]):
+        from pypy.jit.metainterp.graphpage import display_loops
+        loops = self.get_all_loops()
+        for loop in extraloops:
+            if loop in loops:
+                loops.remove(loop)
+            loops.append(loop)
+        display_loops(loops, errmsg)
 
 
 class CrashInJIT(Exception):

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/pyjitpl.py	Mon Mar 23 13:29:10 2009
@@ -650,8 +650,9 @@
         if box is not None:
             extraargs = [box] + extraargs
         guard_op = self.metainterp.history.record(opnum, extraargs, None)
-        guard_op.liveboxes = liveboxes
-        guard_op.key = key
+        op = history.ResOperation(rop.FAIL, liveboxes, None)
+        op.key = key
+        guard_op.suboperations = [op]
         self.pc = saved_pc
         return guard_op
 
@@ -724,12 +725,8 @@
         self._codewriter = codewriter.CodeWriter(self, policy)
         self.portal_code = self._codewriter.make_portal_bytecode(
             self.portal_graph)
-        self.cpu.set_meta_interp(self)
         self.delete_history()
 
-    def enable_stats(self):
-        return not we_are_translated()
-
     def newframe(self, jitcode):
         if not we_are_translated():
             self._debug_history.append(['enter', jitcode, None])
@@ -764,8 +761,6 @@
 
     def create_empty_history(self):
         self.history = history.History(self.cpu)
-        if self.enable_stats():
-            self.stats.history_graph.operations = self.history.operations
 
     def delete_history(self):
         # XXX call me again later
@@ -803,24 +798,20 @@
     def interpret(self):
         # Execute the frames forward until we raise a DoneWithThisFrame,
         # a ContinueRunningNormally, or a GenerateMergePoint exception.
-        if isinstance(self.history, history.BlackHole):
-            text = ' (BlackHole)'
-        else:
-            text = ''
         if not we_are_translated():
-            history.log.event('ENTER' + text)
+            history.log.event('ENTER')
         else:
-            debug_print('ENTER' + text)
+            debug_print('~~~ ENTER')
         try:
             while True:
                 self.framestack[-1].run_one_step()
         finally:
             if not we_are_translated():
-                history.log.event('LEAVE' + text)
+                history.log.event('LEAVE')
             else:
-                debug_print('LEAVE' + text)
+                debug_print('~~~ LEAVE')
 
-    def compile_and_run(self, *args):
+    def compile_and_run_once(self, *args):
         orig_boxes = self.initialize_state_from_start(*args)
         try:
             self.interpret()
@@ -864,11 +855,9 @@
             if not box1.equals(box2):
                 # not a valid loop
                 raise self.ContinueRunningNormally(live_arg_boxes)
-        mp = history.ResOperation(rop.MERGE_POINT,
-                                  original_boxes[num_green_args:], None)
-        mp.greenkey = original_boxes[:num_green_args]
-        self.history.operations.insert(0, mp)
-        old_loops = self.compiled_merge_points.setdefault(mp.greenkey, [])
+        self.history.inputargs = original_boxes[num_green_args:]
+        greenkey = original_boxes[:num_green_args]
+        old_loops = self.compiled_merge_points.setdefault(greenkey, [])
         loop = compile_new_loop(self, old_loops,
                                 live_arg_boxes[num_green_args:])
         if not loop:
@@ -879,6 +868,7 @@
         return loop
 
     def compile_bridge(self, guard_failure, original_boxes, live_arg_boxes):
+        XXX
         num_green_args = self.num_green_args
         mp = history.ResOperation(rop.CATCH, original_boxes, None)
         mp.coming_from = guard_failure.guard_op

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/resoperation.py	Mon Mar 23 13:29:10 2009
@@ -2,18 +2,14 @@
 class ResOperation(object):
     """The central ResOperation class, representing one operation."""
 
-    # for 'merge_point'
-    specnodes = None
-    key = None
-
-    # for 'jump' and 'guard_*'
+    # for 'jump': points to the target loop
     jump_target = None
 
+    # for 'fail'
+    key = None
+
     # for 'guard_*'
-    counter = 0
-    liveboxes = None
-    rebuild_ops = None
-    unoptboxes = None
+    suboperations = None
 
     # for 'guard_nonvirtualizable'
     vdesc = None
@@ -36,10 +32,7 @@
         self.descr = descr
 
     def __repr__(self):
-        result = self.repr()
-        if self.liveboxes is not None:
-            result = '%s [%s]' % (result, ', '.join(map(repr, self.liveboxes)))
-        return result
+        return self.repr()
 
     def repr(self):
         # RPython-friendly version
@@ -80,17 +73,28 @@
     def is_comparison(self):
         return rop._COMPARISON_FIRST <= self.opnum <= rop._COMPARISON_LAST
 
+    def is_final(self):
+        return rop._FINAL_FIRST <= self.opnum <= rop._FINAL_LAST
+
+# ____________________________________________________________
+
+
+class GuardFailed(Exception):
+    def __init__(self, key, currentboxes):
+        self.key = key
+        self.currentboxes = currentboxes
+
 # ____________________________________________________________
 
 
 class rop(object):
     """The possible names of the ResOperations."""
 
-    _SPECIAL_FIRST = 1
-    MERGE_POINT            = 1
-    CATCH                  = 2
-    JUMP                   = 3
-    _SPECIAL_LAST = 9
+    _FINAL_FIRST = 1
+    JUMP                   = 1
+    FAIL                   = 2
+    #RAISE                  = 3
+    _FINAL_LAST = 9
 
     _GUARD_FIRST = 10 # ----- start of guard operations -----
     GUARD_TRUE             = 10

Modified: pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/warmspot.py
==============================================================================
--- pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/warmspot.py	(original)
+++ pypy/branch/pyjitpl5-simplify/pypy/jit/metainterp/warmspot.py	Mon Mar 23 13:29:10 2009
@@ -11,6 +11,7 @@
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.rlib.jit import PARAMETERS
 from pypy.rlib.rarithmetic import r_uint
+from pypy.rlib.debug import debug_print
 from pypy.rpython.lltypesystem.lloperation import llop
 
 from pypy.jit.metainterp import support, history, pyjitpl
@@ -146,12 +147,14 @@
         self.state = state
 
         def crash_in_jit(e):
-            print "Crash in JIT!"
             if not we_are_translated():
-                print '%s: %s' % (e.__class__, e)
-                import sys, pdb; pdb.post_mortem(sys.exc_info()[2])
-            else:
-                print e
+                print "~~~ Crash in JIT!"
+                print '~~~ %s: %s' % (e.__class__, e)
+                if sys.stdout == sys.__stdout__:
+                    import pdb; pdb.post_mortem(sys.exc_info()[2])
+                raise
+            debug_print('~~~ Crash in JIT!')
+            debug_print('~~~ %s' % (e,))
             raise history.CrashInJIT("crash in JIT")
         crash_in_jit._dont_inline_ = True
 
@@ -492,7 +495,7 @@
         getkeyhash._always_inline_ = True
 
         def compile_and_run(self, argshash, *args):
-            loop, boxes = warmrunnerdesc.metainterp.compile_and_run(*args)
+            loop, boxes = warmrunnerdesc.metainterp.compile_and_run_once(*args)
             if loop:
                 cpu = warmrunnerdesc.metainterp.cpu
                 operations = loop.operations



More information about the Pypy-commit mailing list