Author: Carl Friedrich Bolz <cfb...@gmx.de> Branch: guard-compatible Changeset: r85359:497da7b013d3 Date: 2016-06-23 14:49 +0200 http://bitbucket.org/pypy/pypy/changeset/497da7b013d3/
Log: a test for a bridge that jumps to the loop. causes all kinds of problems. 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 @@ -131,6 +131,10 @@ def emit_conditions(self, op, short, optimizer): """ re-emit the conditions about variable op into the short preamble """ + from rpython.jit.metainterp.resoperation import rop, ResOperation + short.append( + ResOperation(rop.GUARD_COMPATIBLE, [ + op, self.known_valid])) for cond in self.conditions: cond.emit_condition(op, short, optimizer) @@ -140,13 +144,22 @@ do nothing. If it is not, check whether ref matches the condition. If not return False, otherwise emit guards for the condition. Return True at the end. """ + from rpython.jit.metainterp.resoperation import rop, ResOperation + have_guard = False for cond in self.conditions: if other is None or not other.contains_condition(cond): if const is None: return False ref = const.getref_base() if cond.check(cpu, ref): - cond.emit_condition(op, short, optimizer) + if not have_guard: + # NB: the guard_compatible here needs to use const, + # otherwise the optimizer will just complain + extra_guards.append(ResOperation( + rop.GUARD_COMPATIBLE, + [op, const])) + have_guard = True + cond.emit_condition(op, extra_guards, optimizer, const) else: return False return True @@ -185,7 +198,7 @@ def repr(self): return "" - def emit_condition(self, op, short, optimizer): + def emit_condition(self, op, short, optimizer, const=None): raise NotImplementedError("abstract base class") def _repr_const(self, arg): @@ -263,7 +276,7 @@ return False return True - def emit_condition(self, op, short, optimizer): + def emit_condition(self, op, short, optimizer, const=None): from rpython.jit.metainterp.history import INT, REF, FLOAT, VOID from rpython.jit.metainterp.resoperation import rop, ResOperation # woah, mess @@ -283,6 +296,11 @@ call_op = ResOperation(rop.CALL_PURE_R, args, descr) short.append(call_op) return + # add result to call_pure_results + if const is not None: + args = args[:] + args[1] = const + optimizer.call_pure_results[args] = self.res short.append(call_op) short.append(ResOperation(rop.GUARD_VALUE, [call_op, self.res])) @@ -375,7 +393,7 @@ return False return True - def emit_condition(self, op, short, optimizer): + def emit_condition(self, op, short, optimizer, const=None): from rpython.jit.metainterp.resoperation import rop, ResOperation # more mess fielddescr = self.fielddescr @@ -395,12 +413,18 @@ rop.GUARD_NOT_INVALIDATED, []), getfield_op]) index = len(short) - PureCallCondition.emit_condition(self, op, short, optimizer) + PureCallCondition.emit_condition(self, op, short, optimizer, const) call_op = short[index] + # puh, not pretty + args = call_op.getarglist() + if const is not None: + del optimizer.call_pure_results[args] assert call_op.opnum in ( rop.CALL_PURE_I, rop.CALL_PURE_R, rop.CALL_PURE_F, rop.CALL_PURE_N) call_op.setarg(2, getfield_op) + if const is not None: + optimizer.call_pure_results[call_op.getarglist()] = self.res def repr(self, argrepr="?"): addr = self.args[0].getaddr() diff --git a/rpython/jit/metainterp/optimizeopt/info.py b/rpython/jit/metainterp/optimizeopt/info.py --- a/rpython/jit/metainterp/optimizeopt/info.py +++ b/rpython/jit/metainterp/optimizeopt/info.py @@ -81,9 +81,6 @@ compat_cond = self._compatibility_conditions if compat_cond is None: return - short.append( - ResOperation(rop.GUARD_COMPATIBLE, [ - op, compat_cond.known_valid])) compat_cond.emit_conditions(op, short, optimizer) @specialize.arg(2) diff --git a/rpython/jit/metainterp/optimizeopt/unroll.py b/rpython/jit/metainterp/optimizeopt/unroll.py --- a/rpython/jit/metainterp/optimizeopt/unroll.py +++ b/rpython/jit/metainterp/optimizeopt/unroll.py @@ -310,7 +310,10 @@ for guard in extra_guards.extra_guards: if isinstance(guard, GuardResOp): guard.rd_resume_position = patchguardop.rd_resume_position - guard.setdescr(compile.ResumeAtPositionDescr()) + if guard.opnum == rop.GUARD_COMPATIBLE: + guard.setdescr(compile.GuardCompatibleDescr()) + else: + guard.setdescr(compile.ResumeAtPositionDescr()) self.send_extra_operation(guard) except VirtualStatesCantMatch: continue @@ -375,8 +378,12 @@ sop = short[i] arglist = self._map_args(mapping, sop.getarglist()) if sop.is_guard(): + if sop.opnum == rop.GUARD_COMPATIBLE: + descr = compile.GuardCompatibleDescr() + else: + descr = compile.ResumeAtPositionDescr() op = sop.copy_and_change(sop.getopnum(), arglist, - descr=compile.ResumeAtPositionDescr()) + descr=descr) assert isinstance(op, GuardResOp) op.rd_resume_position = patchguardop.rd_resume_position else: diff --git a/rpython/jit/metainterp/optimizeopt/virtualstate.py b/rpython/jit/metainterp/optimizeopt/virtualstate.py --- a/rpython/jit/metainterp/optimizeopt/virtualstate.py +++ b/rpython/jit/metainterp/optimizeopt/virtualstate.py @@ -355,7 +355,7 @@ if type == 'i': return NotVirtualStateInfoInt(cpu, type, info) if type == 'r': - if info._compatibility_conditions is not None: + if info is not None and info._compatibility_conditions is not None: return NotVirtualStateInfoPtrCompatible(cpu, type, info) return NotVirtualStateInfoPtr(cpu, type, info) return NotVirtualStateInfo(cpu, type, info) 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 @@ -319,5 +319,46 @@ x = self.meta_interp(main, []) # trace, two bridges, a finish bridge + self.check_trace_count(3) + assert x < 30 + + def test_merge(self): + S = lltype.GcStruct('S', ('x', lltype.Signed)) + p1 = lltype.malloc(S) + p1.x = 1 + + p2 = lltype.malloc(S) + p2.x = 1 + + driver = jit.JitDriver(greens = [], reds = ['n', 'x']) + + class A(object): + pass + + c = A() + c.count = 0 + @jit.elidable_compatible() + def g(s, ignored): + c.count += 1 + return s.x + + def f(n, x): + while n > 0: + driver.can_enter_jit(n=n, x=x) + driver.jit_merge_point(n=n, x=x) + n -= g(x, "abc") + if n & 2: + n -= 2 + + def main(): + g(p1, "def") # make annotator not make argument constant + f(1000, p1) + f(1000, p2) + return c.count + + x = self.meta_interp(main, []) + + assert x < 30 + # trace, two bridges, a finish bridge self.check_trace_count(4) - assert x < 50 + _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit