Author: Carl Friedrich Bolz <cfb...@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) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit