Author: Maciej Fijalkowski <fij...@gmail.com> Branch: optresult Changeset: r77565:b5d3b92eec4c Date: 2015-05-26 11:42 +0200 http://bitbucket.org/pypy/pypy/changeset/b5d3b92eec4c/
Log: start passing the merge-guards kind of tests 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 @@ -49,11 +49,27 @@ class NonNullPtrInfo(PtrInfo): - _attrs_ = () - + _attrs_ = ('last_guard_pos',) + last_guard_pos = -1 + def is_nonnull(self): return True + def get_known_class(self, cpu): + return None + + def get_last_guard(self, optimizer): + if self.last_guard_pos == -1: + return None + return optimizer._newoperations[self.last_guard_pos] + + def reset_last_guard_pos(self): + self.last_guard_pos = -1 + + def mark_last_guard(self, optimizer): + self.last_guard_pos = len(optimizer._newoperations) - 1 + assert self.get_last_guard(optimizer).is_guard() + class AbstractVirtualPtrInfo(NonNullPtrInfo): _attrs_ = ('flags',) @@ -111,7 +127,7 @@ return count class InstancePtrInfo(AbstractStructPtrInfo): - _attrs_ = ('_known_class') + _attrs_ = ('_known_class',) _fields = None def __init__(self, known_class=None, is_virtual=False): @@ -121,7 +137,7 @@ def get_known_class(self, cpu): return self._known_class - + class StructPtrInfo(AbstractStructPtrInfo): def __init__(self, is_virtual=False): if is_virtual: @@ -260,6 +276,9 @@ if not self._const.nonnull(): return None return cpu.ts.cls_of_box(self._const) + + def get_last_guard(self, optimizer): + return None class XPtrOptInfo(AbstractInfo): _attrs_ = ('_tag', 'known_class', 'last_guard_pos', 'lenbound') diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py b/rpython/jit/metainterp/optimizeopt/optimizer.py --- a/rpython/jit/metainterp/optimizeopt/optimizer.py +++ b/rpython/jit/metainterp/optimizeopt/optimizer.py @@ -295,12 +295,11 @@ return ptrinfo.getnullness() assert False - def make_constant_class(self, op, class_const): + def make_constant_class(self, op, class_const, update_last_guard=True): op = self.get_box_replacement(op) - opinfo = op.get_forwarded() - if opinfo is not None: - return opinfo opinfo = info.InstancePtrInfo(class_const) + if update_last_guard: + opinfo.mark_last_guard(self.optimizer) op.set_forwarded(opinfo) return opinfo @@ -466,7 +465,7 @@ self.optimizations = optimizations def replace_guard(self, op, value): - assert isinstance(value, PtrOptValue) + assert isinstance(value, info.InstancePtrInfo) if value.last_guard_pos == -1: return self.replaces_guard[op] = value.last_guard_pos @@ -598,6 +597,10 @@ opinfo = arg0.get_forwarded() if isinstance(opinfo, info.AbstractVirtualPtrInfo): return opinfo + elif opinfo is not None: + last_guard_pos = opinfo.last_guard_pos + else: + last_guard_pos = -1 assert opinfo is None or opinfo.__class__ is info.NonNullPtrInfo if op.is_getfield() or op.getopnum() == rop.SETFIELD_GC: is_object = op.getdescr().parent_descr.is_object() @@ -608,8 +611,11 @@ opinfo.init_fields(op.getdescr().parent_descr) elif op.is_getarrayitem() or op.getopnum() == rop.SETARRAYITEM_GC: opinfo = info.ArrayPtrInfo(op.getdescr()) + elif op.getopnum() == rop.GUARD_CLASS: + opinfo = info.InstancePtrInfo() else: - zzz + xxx + opinfo.last_guard_pos = last_guard_pos arg0.set_forwarded(opinfo) return opinfo diff --git a/rpython/jit/metainterp/optimizeopt/pure.py b/rpython/jit/metainterp/optimizeopt/pure.py --- a/rpython/jit/metainterp/optimizeopt/pure.py +++ b/rpython/jit/metainterp/optimizeopt/pure.py @@ -12,6 +12,7 @@ self.next_index = 0 def add(self, op): + assert isinstance(op, AbstractResOp) next_index = self.next_index self.next_index = (next_index + 1) % self.REMEMBER_LIMIT self.lst[next_index] = op @@ -180,7 +181,6 @@ self.optimizer.optpure = self def pure(self, opnum, op): - op = self.get_box_replacement(op) recentops = self.getrecentops(opnum) recentops.add(op) diff --git a/rpython/jit/metainterp/optimizeopt/rewrite.py b/rpython/jit/metainterp/optimizeopt/rewrite.py --- a/rpython/jit/metainterp/optimizeopt/rewrite.py +++ b/rpython/jit/metainterp/optimizeopt/rewrite.py @@ -287,52 +287,49 @@ 'fail' % r) self.emit_operation(op) self.make_nonnull(op.getarg(0)) + self.getptrinfo(op.getarg(0)).mark_last_guard(self.optimizer) def optimize_GUARD_VALUE(self, op): - ## value = self.getvalue(op.getarg(0)) - ## if value.is_virtual(): - ## arg = value.get_constant_class(self.optimizer.cpu) - ## if arg: - ## addr = arg.getaddr() - ## name = self.optimizer.metainterp_sd.get_name_from_address(addr) - ## else: - ## name = "<unknown>" - ## raise InvalidLoop('A promote of a virtual %s (a recently allocated object) never makes sense!' % name) - ## old_guard_op = value.get_last_guard(self.optimizer) - ## if old_guard_op and not isinstance(old_guard_op.getdescr(), - ## compile.ResumeAtPositionDescr): - ## # there already has been a guard_nonnull or guard_class or - ## # guard_nonnull_class on this value, which is rather silly. - ## # replace the original guard with a guard_value - ## if old_guard_op.getopnum() != rop.GUARD_NONNULL: - ## # This is only safe if the class of the guard_value matches the - ## # class of the guard_*_class, otherwise the intermediate ops might - ## # be executed with wrong classes. - ## previous_classbox = value.get_constant_class(self.optimizer.cpu) - ## expected_classbox = self.optimizer.cpu.ts.cls_of_box(op.getarg(1)) - ## assert previous_classbox is not None - ## assert expected_classbox is not None - ## if not previous_classbox.same_constant(expected_classbox): - ## r = self.optimizer.metainterp_sd.logger_ops.repr_of_resop(op) - ## raise InvalidLoop('A GUARD_VALUE (%s) was proven to always fail' % r) - ## descr = compile.ResumeGuardValueDescr() - ## op = old_guard_op.copy_and_change(rop.GUARD_VALUE, - ## args = [old_guard_op.getarg(0), op.getarg(1)], - ## descr = descr) - ## # Note: we give explicitly a new descr for 'op'; this is why the - ## # old descr must not be ResumeAtPositionDescr (checked above). - ## # Better-safe-than-sorry but it should never occur: we should - ## # not put in short preambles guard_xxx and guard_value - ## # on the same box. - ## self.optimizer.replace_guard(op, value) - ## descr.make_a_counter_per_value(op) - ## # to be safe - ## if isinstance(value, PtrOptValue): - ## value.last_guard_pos = -1 + arg0 = op.getarg(0) + if arg0.type == 'r': + info = self.getptrinfo(arg0) + if info: + if info.is_virtual(): + xxx + old_guard_op = info.get_last_guard(self.optimizer) + if old_guard_op is not None: + op = self.replace_guard_class_with_guard_value(op, info, + old_guard_op) constbox = op.getarg(1) assert isinstance(constbox, Const) self.optimize_guard(op, constbox) + def replace_guard_class_with_guard_value(self, op, info, old_guard_op): + if old_guard_op.opnum != rop.GUARD_NONNULL: + previous_classbox = info.get_known_class(self.optimizer.cpu) + expected_classbox = self.optimizer.cpu.ts.cls_of_box(op.getarg(1)) + assert previous_classbox is not None + assert expected_classbox is not None + if not previous_classbox.same_constant( + expected_classbox): + r = self.optimizer.metainterp_sd.logger_ops.repr_of_resop(op) + raise InvalidLoop('A GUARD_VALUE (%s) was proven to ' + 'always fail' % r) + descr = compile.ResumeGuardValueDescr() + op = old_guard_op.copy_and_change(rop.GUARD_VALUE, + args = [old_guard_op.getarg(0), op.getarg(1)], + descr = descr) + # Note: we give explicitly a new descr for 'op'; this is why the + # old descr must not be ResumeAtPositionDescr (checked above). + # Better-safe-than-sorry but it should never occur: we should + # not put in short preambles guard_xxx and guard_value + # on the same box. + self.optimizer.replace_guard(op, info) + descr.make_a_counter_per_value(op) + # to be safe + info.reset_last_guard_pos() + return op + def optimize_GUARD_TRUE(self, op): self.optimize_guard(op, CONST_1) @@ -351,42 +348,39 @@ def optimize_GUARD_CLASS(self, op): expectedclassbox = op.getarg(1) - info = self.getptrinfo(op.getarg(0)) + info = self.ensure_ptr_info_arg0(op) assert isinstance(expectedclassbox, Const) - if info is not None: - realclassbox = info.get_known_class(self.optimizer.cpu) - if realclassbox is not None: - if realclassbox.same_constant(expectedclassbox): - return - r = self.optimizer.metainterp_sd.logger_ops.repr_of_resop(op) - raise InvalidLoop('A GUARD_CLASS (%s) was proven to always fail' - % r) - old_guard_op = info.get_last_guard(self.optimizer) - if old_guard_op and not isinstance(old_guard_op.getdescr(), - compile.ResumeAtPositionDescr): - xxx - # there already has been a guard_nonnull or guard_class or - # guard_nonnull_class on this value. - if old_guard_op.getopnum() == rop.GUARD_NONNULL: - # it was a guard_nonnull, which we replace with a - # guard_nonnull_class. - descr = compile.ResumeGuardNonnullClassDescr() - op = old_guard_op.copy_and_change (rop.GUARD_NONNULL_CLASS, - args = [old_guard_op.getarg(0), op.getarg(1)], - descr=descr) - # Note: we give explicitly a new descr for 'op'; this is why the - # old descr must not be ResumeAtPositionDescr (checked above). - # Better-safe-than-sorry but it should never occur: we should - # not put in short preambles guard_nonnull and guard_class - # on the same box. - self.optimizer.replace_guard(op, value) - # not emitting the guard, so we have to pass None to - # make_constant_class, so last_guard_pos is not updated - self.emit_operation(op) - value.make_constant_class(None, expectedclassbox) - return + realclassbox = info.get_known_class(self.optimizer.cpu) + if realclassbox is not None: + if realclassbox.same_constant(expectedclassbox): + return + r = self.optimizer.metainterp_sd.logger_ops.repr_of_resop(op) + raise InvalidLoop('A GUARD_CLASS (%s) was proven to always fail' + % r) + old_guard_op = info.get_last_guard(self.optimizer) + if old_guard_op and not isinstance(old_guard_op.getdescr(), + compile.ResumeAtPositionDescr): + # there already has been a guard_nonnull or guard_class or + # guard_nonnull_class on this value. + if old_guard_op.getopnum() == rop.GUARD_NONNULL: + # it was a guard_nonnull, which we replace with a + # guard_nonnull_class. + descr = compile.ResumeGuardNonnullClassDescr() + op = old_guard_op.copy_and_change (rop.GUARD_NONNULL_CLASS, + args = [old_guard_op.getarg(0), op.getarg(1)], + descr=descr) + # Note: we give explicitly a new descr for 'op'; this is why the + # old descr must not be ResumeAtPositionDescr (checked above). + # Better-safe-than-sorry but it should never occur: we should + # not put in short preambles guard_nonnull and guard_class + # on the same box. + self.optimizer.replace_guard(op, info) + self.emit_operation(op) + self.make_constant_class(op.getarg(0), expectedclassbox, + False) + return + self.emit_operation(op) self.make_constant_class(op.getarg(0), expectedclassbox) - self.emit_operation(op) def optimize_GUARD_NONNULL_CLASS(self, op): value = self.getvalue(op.getarg(0)) diff --git a/rpython/jit/metainterp/test/test_resume.py b/rpython/jit/metainterp/test/test_resume.py --- a/rpython/jit/metainterp/test/test_resume.py +++ b/rpython/jit/metainterp/test/test_resume.py @@ -2,9 +2,6 @@ import py import sys from rpython.rtyper.lltypesystem import lltype, llmemory, rffi -from rpython.jit.metainterp.optimizeopt.optimizer import OptValue -from rpython.jit.metainterp.optimizeopt.virtualize import VirtualValue, VArrayValue -from rpython.jit.metainterp.optimizeopt.virtualize import VStructValue, AbstractVirtualValue from rpython.jit.metainterp.resume import * from rpython.jit.metainterp.history import BoxInt, BoxPtr, ConstInt from rpython.jit.metainterp.history import ConstPtr, ConstFloat _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit