[pypy-commit] pypy result-in-resops: more work on resops

fijal noreply at buildbot.pypy.org
Wed Jul 25 01:03:44 CEST 2012


Author: Maciej Fijalkowski <fijall at 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


More information about the pypy-commit mailing list