[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