Author: Carl Friedrich Bolz <[email protected]>
Branch: 
Changeset: r73830:63f7e728d745
Date: 2014-10-06 23:17 +0200
http://bitbucket.org/pypy/pypy/changeset/63f7e728d745/

Log:    optimize quasi-immutable fields during tracing

        this reduces the warmup. still missing to do the same thing for
        quasi-immutable arrays.

        the commit removes the previous support for changing the quasi-
        immutable field during tracing (which was rather obscure anyway)

diff --git a/rpython/jit/codewriter/jtransform.py 
b/rpython/jit/codewriter/jtransform.py
--- a/rpython/jit/codewriter/jtransform.py
+++ b/rpython/jit/codewriter/jtransform.py
@@ -785,6 +785,8 @@
             raise Exception("getfield_raw_r (without _pure) not supported")
         #
         if immut in (IR_QUASIIMMUTABLE, IR_QUASIIMMUTABLE_ARRAY):
+            if immut is IR_QUASIIMMUTABLE:
+                op1.opname += "_pure"
             descr1 = self.cpu.fielddescrof(
                 v_inst.concretetype.TO,
                 quasiimmut.get_mutate_field_name(c_fieldname.value))
diff --git a/rpython/jit/metainterp/optimizeopt/heap.py 
b/rpython/jit/metainterp/optimizeopt/heap.py
--- a/rpython/jit/metainterp/optimizeopt/heap.py
+++ b/rpython/jit/metainterp/optimizeopt/heap.py
@@ -6,6 +6,7 @@
 from rpython.jit.metainterp.jitexc import JitException
 from rpython.jit.metainterp.optimizeopt.optimizer import Optimization, 
MODE_ARRAY, LEVEL_KNOWNCLASS, REMOVED
 from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method
+from rpython.jit.metainterp.optimize import InvalidLoop
 from rpython.jit.metainterp.resoperation import rop, ResOperation
 from rpython.rlib.objectmodel import we_are_translated
 
@@ -544,12 +545,10 @@
         qmutdescr = op.getdescr()
         assert isinstance(qmutdescr, QuasiImmutDescr)
         # check that the value is still correct; it could have changed
-        # already between the tracing and now.  In this case, we are
-        # simply ignoring the QUASIIMMUT_FIELD hint and compiling it
-        # as a regular getfield.
+        # already between the tracing and now.  In this case, we mark the loop
+        # as invalid
         if not qmutdescr.is_still_valid_for(structvalue.get_key_box()):
-            self._remove_guard_not_invalidated = True
-            return
+            raise InvalidLoop('quasi immutable field changed during tracing')
         # record as an out-of-line guard
         if self.optimizer.quasi_immutable_deps is None:
             self.optimizer.quasi_immutable_deps = {}
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py 
b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
@@ -8253,13 +8253,7 @@
         setfield_gc(p106, p108, descr=nextdescr) # inst_storage
         jump(p106)
         """
-        expected = """
-        []
-        p72 = getfield_gc(ConstPtr(myptr2), descr=quasifielddescr)
-        guard_value(p72, -4247) []
-        jump()
-        """
-        self.optimize_loop(ops, expected)
+        self.raises(InvalidLoop, self.optimize_loop, ops, ops)
 
     def test_issue1080_infinitie_loop_simple(self):
         ops = """
@@ -8270,13 +8264,7 @@
         guard_value(p71, -4247) []
         jump(ConstPtr(myptr))
         """
-        expected = """
-        []
-        p72 = getfield_gc(ConstPtr(myptr), descr=quasifielddescr)
-        guard_value(p72, -4247) []
-        jump()
-        """
-        self.optimize_loop(ops, expected)
+        self.raises(InvalidLoop, self.optimize_loop, ops, ops)
 
     def test_only_strengthen_guard_if_class_matches(self):
         ops = """
diff --git a/rpython/jit/metainterp/test/test_quasiimmut.py 
b/rpython/jit/metainterp/test/test_quasiimmut.py
--- a/rpython/jit/metainterp/test/test_quasiimmut.py
+++ b/rpython/jit/metainterp/test/test_quasiimmut.py
@@ -81,6 +81,27 @@
             assert len(loop.quasi_immutable_deps) == 1
             assert isinstance(loop.quasi_immutable_deps.keys()[0], QuasiImmut)
 
+    def test_simple_optimize_during_tracing(self):
+        myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total'])
+        class Foo:
+            _immutable_fields_ = ['a?']
+            def __init__(self, a):
+                self.a = a
+        def f(a, x):
+            foo = Foo(a)
+            total = 0
+            while x > 0:
+                myjitdriver.jit_merge_point(foo=foo, x=x, total=total)
+                # read a quasi-immutable field out of a Constant
+                total += foo.a
+                x -= 1
+            return total
+        #
+        res = self.meta_interp(f, [100, 7], enable_opts="")
+        assert res == 700
+        # there should be no getfields, even though optimizations are turned 
off
+        self.check_resops(guard_not_invalidated=1, getfield_gc=0)
+
     def test_nonopt_1(self):
         myjitdriver = JitDriver(greens=[], reds=['x', 'total', 'lst'])
         class Foo:
@@ -102,7 +123,7 @@
         assert f(100, 7) == 721
         res = self.meta_interp(f, [100, 7])
         assert res == 721
-        self.check_resops(guard_not_invalidated=0, getfield_gc=3)
+        self.check_resops(guard_not_invalidated=0, getfield_gc=1, 
getfield_gc_pure=2)
         #
         from rpython.jit.metainterp.warmspot import get_stats
         loops = get_stats().loops
@@ -154,11 +175,12 @@
                 residual_call(foo)
                 x -= 1
             return total
-        #
+
         assert f(100, 7) == 721
         res = self.meta_interp(f, [100, 7])
         assert res == 721
-        self.check_resops(guard_not_invalidated=0, getfield_gc=2)
+        # the loop is invalid, so nothing is traced
+        self.check_aborted_count(2)
 
     def test_change_during_tracing_2(self):
         myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total'])
@@ -184,7 +206,7 @@
         assert f(100, 7) == 700
         res = self.meta_interp(f, [100, 7])
         assert res == 700
-        self.check_resops(guard_not_invalidated=0, getfield_gc=2)
+        self.check_resops(guard_not_invalidated=0, getfield_gc=0)
 
     def test_change_invalidate_reentering(self):
         myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total'])
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to