Author: Maciej Fijalkowski <fij...@gmail.com> Branch: result-in-resops Changeset: r56440:bb55929a3751 Date: 2012-07-25 01:03 +0200 http://bitbucket.org/pypy/pypy/changeset/bb55929a3751/
Log: more work on resops diff --git a/pypy/jit/metainterp/optimizeopt/__init__.py b/pypy/jit/metainterp/optimizeopt/__init__.py --- a/pypy/jit/metainterp/optimizeopt/__init__.py +++ b/pypy/jit/metainterp/optimizeopt/__init__.py @@ -58,9 +58,6 @@ def optimize_trace(metainterp_sd, loop, enable_opts, inline_short_preamble=True): """Optimize loop.operations to remove internal overheadish operations. """ - - return - debug_start("jit-optimize") try: loop.logops = metainterp_sd.logger_noopt.log_loop(loop.inputargs, diff --git a/pypy/jit/metainterp/optimizeopt/optimizer.py b/pypy/jit/metainterp/optimizeopt/optimizer.py --- a/pypy/jit/metainterp/optimizeopt/optimizer.py +++ b/pypy/jit/metainterp/optimizeopt/optimizer.py @@ -521,18 +521,19 @@ self.bool_boxes[self.getvalue(op)] = None self._emit_operation(op) + def get_value_replacement(self, v): + try: + value = self.values[v] + except KeyError: + return None + else: + self.ensure_imported(value) + return value.force_box(self) + @specialize.argtype(0) def _emit_operation(self, op): assert op.getopnum() not in opgroups.CALL_PURE - for i in range(op.numargs()): - arg = op.getarg(i) - try: - value = self.values[arg] - except KeyError: - pass - else: - self.ensure_imported(value) - op.setarg(i, value.force_box(self)) + op = op.copy_if_modified_by_optimization(self) self.metainterp_sd.profiler.count(jitprof.Counters.OPT_OPS) if op.is_guard(): self.metainterp_sd.profiler.count(jitprof.Counters.OPT_GUARDS) diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py --- a/pypy/jit/metainterp/pyjitpl.py +++ b/pypy/jit/metainterp/pyjitpl.py @@ -9,7 +9,8 @@ from pypy.jit.metainterp import history, compile, resume from pypy.jit.metainterp.history import Const, ConstInt, ConstPtr, ConstFloat from pypy.jit.metainterp.history import Box, TargetToken -from pypy.jit.metainterp.resoperation import rop, create_resop +from pypy.jit.metainterp.resoperation import rop, create_resop, create_resop_0,\ + create_resop_1, create_resop_2 from pypy.jit.metainterp import resoperation from pypy.jit.metainterp import executor from pypy.jit.metainterp.logger import Logger @@ -952,7 +953,7 @@ promoted_box = resbox.constbox() # This is GUARD_VALUE because GUARD_TRUE assumes the existance # of a label when computing resumepc - self.generate_guard(rop.GUARD_VALUE, resbox, [promoted_box], + self.generate_guard(rop.GUARD_VALUE, resbox, promoted_box, resumepc=orgpc) self.metainterp.replace_box(box, constbox) return constbox @@ -965,7 +966,7 @@ def opimpl_guard_class(self, orgpc, box): clsbox = self.cls_of_box(box) if not self.metainterp.heapcache.is_class_known(box): - self.generate_guard(rop.GUARD_CLASS, box, [clsbox], resumepc=orgpc) + self.generate_guard(rop.GUARD_CLASS, box, clsbox, resumepc=orgpc) self.metainterp.heapcache.class_now_known(box) return clsbox @@ -1064,7 +1065,7 @@ def opimpl_raise(self, orgpc, exc_value_box): # xxx hack clsbox = self.cls_of_box(exc_value_box) - self.generate_guard(rop.GUARD_CLASS, exc_value_box, [clsbox], + self.generate_guard(rop.GUARD_CLASS, exc_value_box, clsbox, resumepc=orgpc) self.metainterp.class_of_last_exc_is_const = True self.metainterp.last_exc_value_box = exc_value_box @@ -1239,14 +1240,10 @@ except ChangeFrame: pass - def generate_guard(self, opnum, box=None, extraargs=[], resumepc=-1): - if isinstance(box, Const): # no need for a guard + def generate_guard(self, opnum, box1=None, box2=None, resumepc=-1): + if isinstance(box1, Const): # no need for a guard return metainterp = self.metainterp - if box is not None: - moreargs = [box] + extraargs - else: - moreargs = list(extraargs) metainterp_sd = metainterp.staticdata if opnum == rop.GUARD_NOT_FORCED: resumedescr = compile.ResumeGuardForcedDescr(metainterp_sd, @@ -1255,8 +1252,14 @@ resumedescr = compile.ResumeGuardNotInvalidated() else: resumedescr = compile.ResumeGuardDescr() - guard_op = metainterp.history.record(opnum, moreargs, None, - descr=resumedescr) + if box1 is None: + guard_op = create_resop_0(opnum, None, descr=resumedescr) + elif box2 is None: + guard_op = create_resop_1(opnum, None, box1, descr=resumedescr) + else: + guard_op = create_resop_2(opnum, None, box1, box2, + descr=resumedescr) + metainterp.history.record(guard_op) self.capture_resumedata(resumedescr, resumepc) self.metainterp.staticdata.profiler.count_ops(opnum, Counters.GUARDS) # count @@ -2645,18 +2648,19 @@ if self.debug: print '-> %s!' % e.__class__.__name__ raise - if self.debug: - print resultop - assert argcodes[next_argcode] == '>' - result_argcode = argcodes[next_argcode + 1] - assert resultop.type == {'i': resoperation.INT, - 'r': resoperation.REF, - 'f': resoperation.FLOAT, - 'v': resoperation.VOID}[result_argcode] + if resultop is not None: + if self.debug: + print resultop.getresult() + assert argcodes[next_argcode] == '>' + result_argcode = argcodes[next_argcode + 1] + assert resultop.type == {'i': resoperation.INT, + 'r': resoperation.REF, + 'f': resoperation.FLOAT}[result_argcode] else: resultop = unboundmethod(self, *args) # - self.make_result_of_lastop(resultop) + if resultop is not None: + self.make_result_of_lastop(resultop) # unboundmethod = getattr(MIFrame, 'opimpl_' + name).im_func argtypes = unrolling_iterable(unboundmethod.argtypes) diff --git a/pypy/jit/metainterp/resoperation.py b/pypy/jit/metainterp/resoperation.py --- a/pypy/jit/metainterp/resoperation.py +++ b/pypy/jit/metainterp/resoperation.py @@ -2,7 +2,7 @@ from pypy.rpython.lltypesystem.llmemory import GCREF from pypy.rpython.lltypesystem.lltype import typeOf from pypy.jit.codewriter import longlong -from pypy.rlib.objectmodel import compute_identity_hash +from pypy.rlib.objectmodel import compute_identity_hash, newlist_hint INT = 'i' REF = 'r' @@ -206,9 +206,6 @@ def getarg(self, i): raise NotImplementedError - def setarg(self, i, box): - raise NotImplementedError - def numargs(self): raise NotImplementedError @@ -438,6 +435,8 @@ # backend provides it with cpu.fielddescrof(), cpu.arraydescrof(), # cpu.calldescrof(), and cpu.typedescrof(). self._check_descr(descr) + if self._descr is not None: + raise Exception("descr already set!") self._descr = descr def cleardescr(self): @@ -458,6 +457,8 @@ return self._fail_args def setfailargs(self, fail_args): + if self._fail_args is not None: + raise Exception("Setting fail args on a resop already constructed!") self._fail_args = fail_args # ============ @@ -481,9 +482,6 @@ def getarg(self, i): raise IndexError - def setarg(self, i, box): - raise IndexError - def foreach_arg(self, func): pass @@ -493,6 +491,9 @@ r.setfailargs(self.getfailargs()) return r + def copy_if_modified_by_optimization(self, opt): + return self + class UnaryOp(object): _mixin_ = True _arg0 = None @@ -515,12 +516,6 @@ else: raise IndexError - def setarg(self, i, box): - if i == 0: - self._arg0 = box - else: - raise IndexError - @specialize.arg(1) def foreach_arg(self, func): func(self.getopnum(), 0, self._arg0) @@ -532,6 +527,13 @@ r.setfailargs(self.getfailargs()) return r + def copy_if_modified_by_optimization(self, opt): + new_arg = opt.get_value_replacement(self._arg0) + if new_arg is None: + return self + return create_resop_1(self.opnum, self.getresult(), new_arg, + self.getdescrclone()) + class BinaryOp(object): _mixin_ = True _arg0 = None @@ -554,14 +556,6 @@ else: raise IndexError - def setarg(self, i, box): - if i == 0: - self._arg0 = box - elif i == 1: - self._arg1 = box - else: - raise IndexError - def getarglist(self): return [self._arg0, self._arg1] @@ -577,6 +571,16 @@ r.setfailargs(self.getfailargs()) return r + def copy_if_modified_by_optimization(self, opt): + new_arg0 = opt.get_value_replacement(self._arg0) + new_arg1 = opt.get_value_replacement(self._arg1) + if new_arg0 is None and new_arg1 is None: + return self + return create_resop_2(self.opnum, self.getresult(), + new_arg0 or self._arg0, + new_arg1 or self._arg1, + self.getdescrclone()) + class TernaryOp(object): _mixin_ = True @@ -606,16 +610,6 @@ else: raise IndexError - def setarg(self, i, box): - if i == 0: - self._arg0 = box - elif i == 1: - self._arg1 = box - elif i == 2: - self._arg2 = box - else: - raise IndexError - @specialize.arg(1) def foreach_arg(self, func): func(self.getopnum(), 0, self._arg0) @@ -626,7 +620,19 @@ assert not self.is_guard() return create_resop_3(self.opnum, self.getresult(), self._arg0, self._arg1, self._arg2, self.getdescrclone()) - + + def copy_if_modified_by_optimization(self, opt): + new_arg0 = opt.get_value_replacement(self._arg0) + new_arg1 = opt.get_value_replacement(self._arg1) + new_arg2 = opt.get_value_replacement(self._arg2) + if new_arg0 is None and new_arg1 is None and new_arg2 is None: + return self + return create_resop_3(self.opnum, self.getresult(), + new_arg0 or self._arg0, + new_arg1 or self._arg1, + new_arg2 or self._arg2, + self.getdescrclone()) + class N_aryOp(object): _mixin_ = True @@ -646,9 +652,6 @@ def getarg(self, i): return self._args[i] - def setarg(self, i, box): - self._args[i] = box - @specialize.arg(1) def foreach_arg(self, func): for i, arg in enumerate(self._args): @@ -659,6 +662,23 @@ return create_resop(self.opnum, self.getresult(), self._args[:], self.getdescrclone()) + def copy_if_modified_by_optimization(self, opt): + newargs = None + for i, arg in enumerate(self._args): + new_arg = opt.get_value_replacement(arg) + if new_arg is not None: + if newargs is None: + newargs = newlist_hint(len(self._args)) + for k in range(i): + newargs.append(self._args[k]) + self._args[:i] + newargs.append(new_arg) + elif newargs is not None: + newargs.append(arg) + if newargs is None: + return self + return create_resop(self.opnum, self.getresult(), + newargs, self.getdescrclone()) # ____________________________________________________________ diff --git a/pypy/jit/metainterp/test/test_resoperation.py b/pypy/jit/metainterp/test/test_resoperation.py --- a/pypy/jit/metainterp/test/test_resoperation.py +++ b/pypy/jit/metainterp/test/test_resoperation.py @@ -12,6 +12,9 @@ def __ne__(self, other): return not self == other + def __hash__(self): + return hash(self.v) + def __str__(self): return self.v @@ -35,13 +38,10 @@ obj = cls() obj.initarglist(range(n)) assert obj.getarglist() == range(n) - for i in range(n): - obj.setarg(i, i*2) assert obj.numargs() == n for i in range(n): - assert obj.getarg(i) == i*2 + assert obj.getarg(i) == i py.test.raises(IndexError, obj.getarg, n+1) - py.test.raises(IndexError, obj.setarg, n+1, 0) for n, cls in cases: test_case(n, cls) @@ -104,14 +104,6 @@ assert not rop.create_resop_2(rop.rop.INT_ADD, 3, FakeBox('a'), FakeBox('b')).can_malloc() -def test_get_deep_immutable_oplist(): - ops = [rop.create_resop_2(rop.rop.INT_ADD, 3, FakeBox('a'), FakeBox('b'))] - newops = rop.get_deep_immutable_oplist(ops) - py.test.raises(TypeError, "newops.append('foobar')") - py.test.raises(TypeError, "newops[0] = 'foobar'") - py.test.raises(AssertionError, "newops[0].setarg(0, 'd')") - py.test.raises(AssertionError, "newops[0].setdescr('foobar')") - def test_clone(): mydescr = AbstractDescr() op = rop.create_resop_0(rop.rop.GUARD_NO_EXCEPTION, None, descr=mydescr) @@ -152,3 +144,43 @@ assert repr(op) == 'guard_no_exception(, descr=descr)' op = rop.create_resop_2(rop.rop.INT_ADD, 3, FakeBox("a"), FakeBox("b")) assert repr(op) == '3 = int_add(a, b)' + # XXX more tests once we decide what we actually want to print + +class MockOpt(object): + def __init__(self, replacements): + self.d = replacements + + def get_value_replacement(self, v): + if v in self.d: + return FakeBox('rrr') + return None + +def test_copy_if_modified_by_optimization(): + mydescr = FakeDescr() + op = rop.create_resop_0(rop.rop.GUARD_NO_EXCEPTION, None, descr=mydescr) + assert op.copy_if_modified_by_optimization(MockOpt({})) is op + op = rop.create_resop_1(rop.rop.INT_IS_ZERO, 1, FakeBox('a')) + assert op.copy_if_modified_by_optimization(MockOpt({})) is op + op2 = op.copy_if_modified_by_optimization(MockOpt(set([FakeBox('a')]))) + assert op2 is not op + assert op2.getarg(0) == FakeBox('rrr') + op = rop.create_resop_2(rop.rop.INT_ADD, 3, FakeBox("a"), FakeBox("b")) + op2 = op.copy_if_modified_by_optimization(MockOpt(set([FakeBox('c')]))) + assert op2 is op + op2 = op.copy_if_modified_by_optimization(MockOpt(set([FakeBox('b')]))) + assert op2 is not op + assert op2._arg0 is op._arg0 + assert op2._arg1 != op._arg1 + assert op2.getint() == op.getint() + op = rop.create_resop_3(rop.rop.STRSETITEM, None, FakeBox('a'), + FakeBox('b'), FakeBox('c')) + op2 = op.copy_if_modified_by_optimization(MockOpt(set([FakeBox('b')]))) + assert op2 is not op + op = rop.create_resop(rop.rop.CALL_i, 13, [FakeBox('a'), FakeBox('b'), + FakeBox('c')], descr=mydescr) + op2 = op.copy_if_modified_by_optimization(MockOpt(set([FakeBox('aa')]))) + assert op2 is op + op2 = op.copy_if_modified_by_optimization(MockOpt(set([FakeBox('b')]))) + assert op2 is not op + assert op2.getarglist() == [FakeBox("a"), FakeBox("rrr"), FakeBox("c")] + assert op2.getdescr() == mydescr _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit