[pypy-commit] pypy guard-compatible: try to implement the backend/guard_compatible interface
cfbolz
pypy.commits at gmail.com
Fri May 20 06:03:01 EDT 2016
Author: Carl Friedrich Bolz <cfbolz at gmx.de>
Branch: guard-compatible
Changeset: r84524:b4c9f5681460
Date: 2016-05-20 12:01 +0200
http://bitbucket.org/pypy/pypy/changeset/b4c9f5681460/
Log: try to implement the backend/guard_compatible interface
(needs new code in the graph viewer, because of the different ways
that bridges can be attached now).
diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py
--- a/rpython/jit/backend/llgraph/runner.py
+++ b/rpython/jit/backend/llgraph/runner.py
@@ -24,6 +24,7 @@
def __init__(self, lltrace):
self.ops_offset = None
self.lltrace = lltrace
+ self.asmaddr = lltrace
class LLTrace(object):
has_been_freed = False
@@ -356,10 +357,13 @@
def compile_bridge(self, faildescr, inputargs, operations,
original_loop_token, log=True, logger=None):
+ from rpython.jit.metainterp.compile import GuardCompatibleDescr
clt = original_loop_token.compiled_loop_token
clt.compiling_a_bridge()
lltrace = LLTrace(inputargs, operations)
- faildescr._llgraph_bridge = lltrace
+ if not isinstance(faildescr, GuardCompatibleDescr):
+ # don't patch GuardCompatibleDescr
+ faildescr._llgraph_bridge = lltrace
clt._llgraph_alltraces.append(lltrace)
self._record_labels(lltrace)
return LLAsmInfo(lltrace)
@@ -470,12 +474,6 @@
assert deadframe._saved_data is not None
return deadframe._saved_data
- def grow_guard_compatible_switch(self, compiled_loop_token, descr, ref):
- assert isinstance(compiled_loop_token, model.CompiledLoopToken)
- if not hasattr(descr, '_guard_compatible_llgraph_lst'):
- descr._guard_compatible_llgraph_lst = []
- descr._guard_compatible_llgraph_lst.append(ref)
-
# ------------------------------------------------------------
@@ -1292,9 +1290,19 @@
if arg1 != arg2:
if hasattr(descr, '_guard_compatible_llgraph_lst'):
lst = descr._guard_compatible_llgraph_lst
- for ref in lst:
+ for ref, target in lst:
if ref == arg1:
- return
+ if target == -1:
+ return
+ XXX
+ else:
+ descr._guard_compatible_llgraph_lst = []
+ target = descr.find_compatible(self.cpu, arg1)
+ if target:
+ descr._guard_compatible_llgraph_lst.append((arg1, target))
+ if target == -1:
+ return
+ XXX
self.fail_guard(descr, extra_value=arg1)
def execute_int_add_ovf(self, _, x, y):
diff --git a/rpython/jit/metainterp/compatible.py b/rpython/jit/metainterp/compatible.py
--- a/rpython/jit/metainterp/compatible.py
+++ b/rpython/jit/metainterp/compatible.py
@@ -30,6 +30,8 @@
self.known_valid = ptr
self.conditions = []
self.last_quasi_immut_field_op = None
+ # -1 means "stay on the original trace"
+ self.jump_target = -1
def record_condition(self, cond, res, optimizer):
for oldcond in self.conditions:
@@ -43,7 +45,7 @@
def register_quasi_immut_field(self, op):
self.last_quasi_immut_field_op = op
- def check_compat(self, cpu, ref, loop_token):
+ def check_compat_and_activate(self, cpu, ref, loop_token):
for cond in self.conditions:
if not cond.check(cpu, ref):
return False
diff --git a/rpython/jit/metainterp/compile.py b/rpython/jit/metainterp/compile.py
--- a/rpython/jit/metainterp/compile.py
+++ b/rpython/jit/metainterp/compile.py
@@ -797,13 +797,14 @@
new_loop.original_jitcell_token = metainterp.resumekey_original_loop_token
inputargs = new_loop.inputargs
if not we_are_translated():
- self._debug_subinputargs = new_loop.inputargs
- self._debug_suboperations = new_loop.operations
+ if not hasattr(self, "_debug_bridges"):
+ self._debug_bridges = []
+ self._debug_bridges.append((new_loop.inputargs, new_loop.operations))
propagate_original_jitcell_token(new_loop)
- send_bridge_to_backend(metainterp.jitdriver_sd, metainterp.staticdata,
- self, inputargs, new_loop.operations,
- new_loop.original_jitcell_token,
- metainterp.box_names_memo)
+ return send_bridge_to_backend(metainterp.jitdriver_sd, metainterp.staticdata,
+ self, inputargs, new_loop.operations,
+ new_loop.original_jitcell_token,
+ metainterp.box_names_memo)
def make_a_counter_per_value(self, guard_value_op, index):
assert guard_value_op.getopnum() in (rop.GUARD_VALUE, rop.GUARD_COMPATIBLE)
@@ -1084,37 +1085,27 @@
# XXX think about what is being kept alive here
self._compatibility_conditions = None
self.failarg_index = -1
- # list of descrs about the same variable, potentially shared with
- # subsequent guards in bridges
- self.guard_descrs_list = [self]
+ # list of compatibility conditions about the same variable, with
+ # bridges attached to them
+ self.other_compat_conditions = []
- def handle_fail(self, deadframe, metainterp_sd, jitdriver_sd):
- index = intmask(self.status >> self.ST_SHIFT)
- typetag = intmask(self.status & self.ST_TYPE_MASK)
- assert typetag == self.TY_REF # for now
- refval = metainterp_sd.cpu.get_value_direct(deadframe, 'r', index)
- if not we_are_translated():
- assert self in self.guard_descrs_list
+ def find_compatible(self, cpu, ref):
+ """ callback for the CPU: given a value ref, it returns:
+ -1 to stay on the trace
+ 0 to say that there isn't one
+ the address of the compatible bridge to jump to
+ """
# need to do the checking oldest to newest, to check the most specific
# condition first
- for curr in self.guard_descrs_list:
- if curr.is_compatible(metainterp_sd.cpu, refval):
- from rpython.jit.metainterp.blackhole import resume_in_blackhole
- metainterp_sd.cpu.grow_guard_compatible_switch(
- curr.rd_loop_token, curr, refval)
- resume_in_blackhole(metainterp_sd, jitdriver_sd, self, deadframe)
- return
- # a real failure
- return ResumeGuardDescr.handle_fail(self, deadframe, metainterp_sd, jitdriver_sd)
-
- def is_compatible(self, cpu, ref):
- const = history.newconst(ref)
if self._compatibility_conditions:
- if self._compatibility_conditions.check_compat(
+ if self._compatibility_conditions.check_compat_and_activate(
cpu, ref, self.rd_loop_token):
- return True
- return False
- return True # no conditions, everything works
+ return self._compatibility_conditions.jump_target
+ for _compatibility_conditions in self.other_compat_conditions:
+ if _compatibility_conditions.check_compat_and_activate(
+ cpu, ref, self.rd_loop_token):
+ return self._compatibility_conditions.jump_target
+ return 0
def compile_and_attach(self, metainterp, new_loop, orig_inputargs):
# if new_loop starts with another guard_compatible on the same argument
@@ -1123,15 +1114,21 @@
assert self.failarg_index != -1
arg = new_loop.inputargs[self.failarg_index]
firstop = new_loop.operations[0]
+ compat_cond = None
if (firstop.getopnum() == rop.GUARD_COMPATIBLE and
firstop.getarg(0) is arg):
# a guard_compatible about the same box
+ # remove it, it doesn't have to be checked in the bridge
+ del new_loop.operations[0]
newdescr = firstop.getdescr()
assert isinstance(newdescr, GuardCompatibleDescr)
- newdescr.guard_descrs_list = self.guard_descrs_list
- self.guard_descrs_list.append(newdescr)
- ResumeGuardDescr.compile_and_attach(
+ compat_cond = newdescr._compatibility_conditions
+ self.other_compat_conditions.append(compat_cond)
+ asminfo = ResumeGuardDescr.compile_and_attach(
self, metainterp, new_loop, orig_inputargs)
+ if compat_cond:
+ compat_cond.jump_target = asminfo.asmaddr
+ return asminfo
def make_a_counter_per_value(self, guard_value_op, index):
self.failarg_index = guard_value_op.getfailargs().index(
diff --git a/rpython/jit/metainterp/graphpage.py b/rpython/jit/metainterp/graphpage.py
--- a/rpython/jit/metainterp/graphpage.py
+++ b/rpython/jit/metainterp/graphpage.py
@@ -4,10 +4,10 @@
from rpython.jit.metainterp.resoperation import rop
class SubGraph:
- def __init__(self, op):
+ def __init__(self, op, inputargs, suboperations):
self.failargs = op.getfailargs()
- self.subinputargs = op.getdescr()._debug_subinputargs
- self.suboperations = op.getdescr()._debug_suboperations
+ self.subinputargs = inputargs
+ self.suboperations = suboperations
def get_operations(self):
return self.suboperations
def get_display_text(self, memo):
@@ -26,13 +26,14 @@
for procedure in procedures]
for graph, highlight in graphs:
for op in graph.get_operations():
- if is_interesting_guard(op):
- graphs.append((SubGraph(op), highlight))
+ bridges = getattr(op.getdescr(), '_debug_bridges', [])
+ for inputargs, suboperations in bridges:
+ graphs.append((SubGraph(op, inputargs, suboperations), highlight))
graphpage = ResOpGraphPage(graphs, errmsg, metainterp_sd)
graphpage.display()
def is_interesting_guard(op):
- return hasattr(op.getdescr(), '_debug_suboperations')
+ return hasattr(op.getdescr(), '_debug_bridges')
def getdescr(op):
if op._descr is not None:
@@ -178,8 +179,9 @@
s = s.replace(',', '.') # we use comma for argument splitting
op_repr = "debug_merge_point(%d, %d, '%s')" % (op.getarg(1).getint(), op.getarg(2).getint(), s)
lines.append(op_repr)
- if is_interesting_guard(op):
- tgt = op.getdescr()._debug_suboperations[0]
+ bridges = getattr(op.getdescr(), '_debug_bridges', [])
+ for inputargs, suboperations in bridges:
+ tgt = suboperations[0]
tgt_g, tgt_i = self.all_operations[tgt]
self.genedge((graphindex, opstartindex),
(tgt_g, tgt_i),
diff --git a/rpython/jit/metainterp/history.py b/rpython/jit/metainterp/history.py
--- a/rpython/jit/metainterp/history.py
+++ b/rpython/jit/metainterp/history.py
@@ -548,9 +548,9 @@
assert box in seen
if op.is_guard() and check_descr:
assert op.getdescr() is not None
- if hasattr(op.getdescr(), '_debug_suboperations'):
- ops = op.getdescr()._debug_suboperations
- TreeLoop.check_consistency_of_branch(ops, seen.copy())
+ if hasattr(op.getdescr(), '_debug_bridges'):
+ for _, ops in op.getdescr()._debug_bridges:
+ TreeLoop.check_consistency_of_branch(ops, seen.copy())
for box in op.getfailargs() or []:
if box is not None:
assert not isinstance(box, Const)
@@ -600,9 +600,9 @@
result.extend(operations)
for op in operations:
if op.is_guard() and op.getdescr():
- if hasattr(op.getdescr(), '_debug_suboperations'):
- ops = op.getdescr()._debug_suboperations
- _list_all_operations(result, ops, omit_finish)
+ if hasattr(op.getdescr(), '_debug_bridges'):
+ for _, ops in op.getdescr()._debug_bridges:
+ _list_all_operations(result, ops, omit_finish)
# ____________________________________________________________
diff --git a/rpython/jit/metainterp/test/test_compatible.py b/rpython/jit/metainterp/test/test_compatible.py
--- a/rpython/jit/metainterp/test/test_compatible.py
+++ b/rpython/jit/metainterp/test/test_compatible.py
@@ -41,7 +41,7 @@
x = self.meta_interp(main, [])
- assert x < 25
+ assert x < 30
# trace, two bridges, a finish bridge
self.check_trace_count(4)
More information about the pypy-commit
mailing list