[pypy-svn] pypy out-of-line-guards-2: First test passing on the front-end.

arigo commits-noreply at bitbucket.org
Sat Apr 2 20:17:34 CEST 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: out-of-line-guards-2
Changeset: r43115:78ddcf590d26
Date: 2011-04-02 18:35 +0200
http://bitbucket.org/pypy/pypy/changeset/78ddcf590d26/

Log:	First test passing on the front-end.

diff --git a/pypy/jit/metainterp/quasiimmut.py b/pypy/jit/metainterp/quasiimmut.py
--- a/pypy/jit/metainterp/quasiimmut.py
+++ b/pypy/jit/metainterp/quasiimmut.py
@@ -1,5 +1,6 @@
 from pypy.rpython.rclass import IR_QUASI_IMMUTABLE
 from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
+from pypy.jit.metainterp.history import AbstractDescr
 
 
 def is_quasi_immutable(STRUCT, fieldname):
@@ -40,3 +41,14 @@
     def show(cpu, mutate_gcref):
         mutate_ptr = cpu.ts.cast_to_baseclass(mutate_gcref)
         return cast_base_ptr_to_instance(SlowMutate, mutate_ptr)
+
+
+class SlowMutateDescr(AbstractDescr):
+    def __init__(self, cpu, gcref,
+                 constantfieldbox, fielddescr, mutatefielddescr):
+        self.cpu = cpu
+        self.gcref = gcref
+        self.constantfieldbox = constantfieldbox
+        self.fielddescr = fielddescr
+        self.mutatefielddescr = mutatefielddescr
+        self.mutate = get_current_mutate_instance(cpu, gcref, mutatefielddescr)

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
@@ -555,6 +555,19 @@
     opimpl_setfield_raw_r = _opimpl_setfield_raw_any
     opimpl_setfield_raw_f = _opimpl_setfield_raw_any
 
+    @arguments("box", "descr", "descr")
+    def opimpl_record_quasiimmut_field(self, box, fielddescr,
+                                       mutatefielddescr):
+        from pypy.jit.metainterp.quasiimmut import SlowMutateDescr
+        cpu = self.metainterp.cpu
+        fieldbox = executor.execute(cpu, self.metainterp, rop.GETFIELD_GC,
+                                    fielddescr, box)
+        fieldbox = fieldbox.constbox()
+        descr = SlowMutateDescr(cpu, box.getref_base(), fieldbox,
+                                fielddescr, mutatefielddescr)
+        self.metainterp.history.record(rop.QUASIIMMUT_FIELD, [box],
+                                       None, descr=descr)
+
     def _nonstandard_virtualizable(self, pc, box):
         # returns True if 'box' is actually not the "standard" virtualizable
         # that is stored in metainterp.virtualizable_boxes[-1]

diff --git a/pypy/jit/codewriter/test/test_jtransform.py b/pypy/jit/codewriter/test/test_jtransform.py
--- a/pypy/jit/codewriter/test/test_jtransform.py
+++ b/pypy/jit/codewriter/test/test_jtransform.py
@@ -962,9 +962,10 @@
         tr = Transformer(FakeCPU())
         [op1, op2] = tr.rewrite_operation(op)
         assert op1.opname == 'record_quasiimmut_field'
-        assert len(op1.args) == 2
+        assert len(op1.args) == 3
         assert op1.args[0] == v_x
-        assert op1.args[1] == ('fielddescr', STRUCT, 'mutate_x')
+        assert op1.args[1] == ('fielddescr', STRUCT, 'inst_x')
+        assert op1.args[2] == ('fielddescr', STRUCT, 'mutate_x')
         assert op1.result is None
         assert op2.opname == 'getfield_gc_i'
         assert len(op2.args) == 2

diff --git a/pypy/jit/metainterp/test/test_quasiimmut.py b/pypy/jit/metainterp/test/test_quasiimmut.py
--- a/pypy/jit/metainterp/test/test_quasiimmut.py
+++ b/pypy/jit/metainterp/test/test_quasiimmut.py
@@ -3,6 +3,8 @@
 from pypy.jit.metainterp import typesystem
 from pypy.jit.metainterp.quasiimmut import SlowMutate
 from pypy.jit.metainterp.quasiimmut import get_current_mutate_instance
+from pypy.jit.metainterp.test.test_basic import LLJitMixin
+from pypy.rlib.jit import JitDriver
 
 
 def test_get_current_mutate_instance():
@@ -38,3 +40,30 @@
     assert isinstance(sm1, SlowMutate)
     sm2 = get_current_mutate_instance(cpu, foo_gcref, mutatefielddescr)
     assert sm1 is sm2
+
+
+class QuasiImmutTests:
+
+    def test_simple_1(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])
+        assert res == 700
+        self.check_loops(getfield_gc=0, everywhere=True)
+
+
+class TestLLtypeGreenFieldsTests(QuasiImmutTests, LLJitMixin):
+    pass

diff --git a/pypy/jit/metainterp/optimizeopt/heap.py b/pypy/jit/metainterp/optimizeopt/heap.py
--- a/pypy/jit/metainterp/optimizeopt/heap.py
+++ b/pypy/jit/metainterp/optimizeopt/heap.py
@@ -378,6 +378,23 @@
         self.cache_arrayitem_value(op.getdescr(), value, indexvalue, fieldvalue,
                                    write=True)
 
+    def optimize_QUASIIMMUT_FIELD(self, op):
+        # Pattern: QUASIIMMUT_FIELD(s, descr=SlowMutateDescr)
+        #          x = GETFIELD_GC(s, descr='inst_x')
+        # If 's' is a constant (after optimizations), then we make 's.inst_x'
+        # a constant too, and we rely on the rest of the optimizations to
+        # constant-fold the following getfield_gc.
+        structvalue = self.getvalue(op.getarg(0))
+        if structvalue.is_constant():
+            from pypy.jit.metainterp.quasiimmut import SlowMutateDescr
+            # XXX check that the value is still correct!
+            # XXX record as an out-of-line guard!
+            smdescr = op.getdescr()
+            assert isinstance(smdescr, SlowMutateDescr)
+            fieldvalue = self.getvalue(smdescr.constantfieldbox)
+            cf = self.field_cache(smdescr.fielddescr)
+            cf.remember_field_value(structvalue, fieldvalue)
+
     def propagate_forward(self, op):
         opnum = op.getopnum()
         for value, func in optimize_ops:

diff --git a/pypy/jit/metainterp/optimizeopt/simplify.py b/pypy/jit/metainterp/optimizeopt/simplify.py
--- a/pypy/jit/metainterp/optimizeopt/simplify.py
+++ b/pypy/jit/metainterp/optimizeopt/simplify.py
@@ -20,6 +20,9 @@
         op = ResOperation(rop.SAME_AS, [op.getarg(0)], op.result)
         self.emit_operation(op)
 
+    def optimize_QUASIIMMUT_FIELD(self, op):
+        pass
+
     def propagate_forward(self, op):
         opnum = op.getopnum()
         for value, func in optimize_ops:

diff --git a/pypy/jit/metainterp/executor.py b/pypy/jit/metainterp/executor.py
--- a/pypy/jit/metainterp/executor.py
+++ b/pypy/jit/metainterp/executor.py
@@ -312,6 +312,7 @@
                          rop.DEBUG_MERGE_POINT,
                          rop.JIT_DEBUG,
                          rop.SETARRAYITEM_RAW,
+                         rop.QUASIIMMUT_FIELD,
                          ):      # list of opcodes never executed by pyjitpl
                 continue
             raise AssertionError("missing %r" % (key,))

diff --git a/pypy/jit/metainterp/blackhole.py b/pypy/jit/metainterp/blackhole.py
--- a/pypy/jit/metainterp/blackhole.py
+++ b/pypy/jit/metainterp/blackhole.py
@@ -1166,6 +1166,11 @@
     def bhimpl_setfield_raw_f(cpu, struct, fielddescr, newvalue):
         cpu.bh_setfield_raw_f(struct, fielddescr, newvalue)
 
+    @arguments("cpu", "r", "d", "d")
+    def bhimpl_record_quasiimmut_field(self, struct, fielddescr,
+                                       mutatefielddescr):
+        pass
+
     @arguments("cpu", "d", returns="r")
     def bhimpl_new(cpu, descr):
         return cpu.bh_new(descr)

diff --git a/pypy/jit/codewriter/jtransform.py b/pypy/jit/codewriter/jtransform.py
--- a/pypy/jit/codewriter/jtransform.py
+++ b/pypy/jit/codewriter/jtransform.py
@@ -584,7 +584,7 @@
                 v_inst.concretetype.TO,
                 quasiimmut.get_mutate_field_name(c_fieldname.value))
             op1 = [SpaceOperation('record_quasiimmut_field',
-                                  [v_inst, descr1], None),
+                                  [v_inst, descr, descr1], None),
                    op1]
         return op1
 

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
@@ -41,7 +41,8 @@
                 # during preamble but to keep it during the loop
                 optimizations.append(o)
 
-    if 'rewrite' not in enable_opts or 'virtualize' not in enable_opts:
+    if ('rewrite' not in enable_opts or 'virtualize' not in enable_opts
+        or 'heap' not in enable_opts):
         optimizations.append(OptSimplify())
 
     if inline_short_preamble:

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
@@ -475,6 +475,7 @@
     'VIRTUAL_REF_FINISH/2',   # removed before it's passed to the backend
     'COPYSTRCONTENT/5',       # src, dst, srcstart, dststart, length
     'COPYUNICODECONTENT/5',
+    'QUASIIMMUT_FIELD/1d',    # [objptr], descr=SlowMutateDescr
 
     '_CANRAISE_FIRST', # ----- start of can_raise operations -----
     '_CALL_FIRST',


More information about the Pypy-commit mailing list