Author: Carl Friedrich Bolz <cfb...@gmx.de> Branch: guard-compatible Changeset: r87246:70a901ab0437 Date: 2016-08-18 15:41 +0200 http://bitbucket.org/pypy/pypy/changeset/70a901ab0437/
Log: somewhat obscure: if there is a condition on the "version" (ie second argument of a elidable_compatible call) then that condition was emmitted *after* the guard_compatible in the short preamble. that's nonsense, fix it with a hack for now. 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 @@ -146,11 +146,13 @@ """ re-emit the conditions about variable op into the short preamble """ from rpython.jit.metainterp.resoperation import rop, ResOperation - short.append( + localshort = [] + localshort.append( ResOperation(rop.GUARD_COMPATIBLE, [ op, self.known_valid])) for cond in self.conditions: - cond.emit_condition(op, short, optimizer) + cond.emit_condition(op, localshort, short, optimizer) + short.extend(localshort) def emit_needed_conditions_if_const_matches( self, other, const, op, extra_guards, optimizer, cpu): @@ -160,6 +162,7 @@ at the end. """ from rpython.jit.metainterp.resoperation import rop, ResOperation have_guard = False + local_extra_guards = [] for cond in self.conditions: if other is None or not other.contains_condition(cond): if const is None: @@ -169,13 +172,16 @@ if not have_guard: # NB: the guard_compatible here needs to use const, # otherwise the optimizer will just complain - extra_guards.append(ResOperation( + local_extra_guards.append(ResOperation( rop.GUARD_COMPATIBLE, [op, const])) have_guard = True - cond.emit_condition(op, extra_guards, optimizer, const) + cond.emit_condition( + op, local_extra_guards, + extra_guards, optimizer, const) else: return False + extra_guards.extend(local_extra_guards) return True def attach_to_descr(self, descr, guard_value_op, optimizer): @@ -263,7 +269,7 @@ def repr(self): return "" - def emit_condition(self, op, short, optimizer, const=None): + def emit_condition(self, op, guards, pre_guards, optimizer, const=None): raise NotImplementedError("abstract base class") def _repr_const(self, arg): @@ -341,7 +347,7 @@ return False return True - def emit_condition(self, op, short, optimizer, const=None): + def emit_condition(self, op, short, pre_short, optimizer, const=None): from rpython.jit.metainterp.history import INT, REF, FLOAT, VOID from rpython.jit.metainterp.resoperation import rop, ResOperation # woah, mess @@ -387,11 +393,14 @@ res = self.debug_mp_str + "\n" + res return res +class UnsupportedInfoInGuardCompatibleError(Exception): + pass class QuasiimmutGetfieldAndPureCallCondition(PureCallCondition): const_args_start_at = 3 def __init__(self, op, qmutdescr, optimizer): + from rpython.jit.metainterp.optimizeopt import info PureCallCondition.__init__(self, op, optimizer) self.args[2] = None # XXX not 100% sure whether it's save to store the whole descr @@ -399,6 +408,17 @@ self.qmut = qmutdescr.qmut self.mutatefielddescr = qmutdescr.mutatefielddescr self.fielddescr = qmutdescr.fielddescr + self.need_nonnull_arg2 = False + if self.fielddescr.is_pointer_field(): + fieldinfo = optimizer.getptrinfo(op.getarg(2)) + if fieldinfo is not None: + if type(fieldinfo) != info.NonNullPtrInfo: + # XXX PyPy only needs non-null versions. if another + # interpreter needs something more specific we need to + # generalize this code + raise UnsupportedInfoInGuardCompatible() + else: + self.need_nonnull_arg2 = True def activate(self, ref, optimizer): # record the quasi-immutable @@ -458,7 +478,7 @@ return False return True - def emit_condition(self, op, short, optimizer, const=None): + def emit_condition(self, op, short, pre_short, optimizer, const=None): from rpython.jit.metainterp.resoperation import rop, ResOperation from rpython.jit.metainterp.quasiimmut import QuasiImmutDescr # more mess @@ -466,6 +486,13 @@ if fielddescr.is_pointer_field(): getfield_op = ResOperation( rop.GETFIELD_GC_R, [op], fielddescr) + if self.need_nonnull_arg2: + # XXX atm it's emmitted n times + getfield_op2 = ResOperation( + rop.GETFIELD_GC_R, [op], fielddescr) + guard_nonnull = ResOperation(rop.GUARD_NONNULL, [getfield_op2]) + pre_short.append(getfield_op2) + pre_short.append(guard_nonnull) elif fielddescr.is_float_field(): getfield_op = ResOperation( rop.GETFIELD_GC_F, [op], fielddescr) @@ -485,7 +512,7 @@ rop.GUARD_NOT_INVALIDATED, []), getfield_op]) index = len(short) - PureCallCondition.emit_condition(self, op, short, optimizer, const) + PureCallCondition.emit_condition(self, op, short, pre_short, optimizer, const) call_op = short[index] # puh, not pretty args = call_op.getarglist()[:] 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 @@ -696,5 +696,7 @@ main(False) self.meta_interp(main, [True], backendopt=True) - self.check_trace_count(2) + # XXX this should be 3, but hard to achieve without propagating more + # information across bridges + self.check_trace_count(4) self.check_resops(call_i=0) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit