[pypy-svn] pypy out-of-line-guards-2: On getfields of quasi-immutable fields, write in the jitcodes a

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


Author: Armin Rigo <arigo at tunes.org>
Branch: out-of-line-guards-2
Changeset: r43111:cdc159d28520
Date: 2011-04-02 17:14 +0200
http://bitbucket.org/pypy/pypy/changeset/cdc159d28520/

Log:	On getfields of quasi-immutable fields, write in the jitcodes a
	'record_quasiimmut_field' operation in addition to the
	getfield_gc_*. As for setfields of quasi-immutable fields, they are
	hidden from the JIT; for now this is done by making the whole
	function containing them as don't-look-inside.

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
@@ -7,8 +7,9 @@
 from pypy.jit.codewriter.flatten import ListOfKind, IndirectCallTargets
 from pypy.jit.codewriter import support, heaptracker, longlong
 from pypy.jit.codewriter.effectinfo import EffectInfo
-from pypy.jit.codewriter.policy import log
+from pypy.jit.codewriter.policy import log, check_skip_operation
 from pypy.jit.metainterp.typesystem import deref, arrayItem
+from pypy.jit.metainterp import quasiimmut
 from pypy.rlib import objectmodel
 from pypy.rlib.jit import _we_are_jitted
 from pypy.translator.simplify import get_funcobj
@@ -561,7 +562,8 @@
                                                 arraydescr)
             return []
         # check for _immutable_fields_ hints
-        if v_inst.concretetype.TO._immutable_field(c_fieldname.value):
+        immut = v_inst.concretetype.TO._immutable_field(c_fieldname.value)
+        if immut:
             if (self.callcontrol is not None and
                 self.callcontrol.could_be_green_field(v_inst.concretetype.TO,
                                                       c_fieldname.value)):
@@ -574,10 +576,20 @@
         descr = self.cpu.fielddescrof(v_inst.concretetype.TO,
                                       c_fieldname.value)
         kind = getkind(RESULT)[0]
-        return SpaceOperation('getfield_%s_%s%s' % (argname, kind, pure),
-                              [v_inst, descr], op.result)
+        op1 = SpaceOperation('getfield_%s_%s%s' % (argname, kind, pure),
+                             [v_inst, descr], op.result)
+        #
+        if immut is quasiimmut.IR_QUASI_IMMUTABLE:
+            descr1 = self.cpu.fielddescrof(
+                v_inst.concretetype.TO,
+                quasiimmut.get_mutate_field_name(c_fieldname.value))
+            op1 = [SpaceOperation('record_quasiimmut_field',
+                                  [v_inst, descr1], None),
+                   op1]
+        return op1
 
     def rewrite_op_setfield(self, op):
+        check_skip_operation(op)        # just to check it doesn't raise
         if self.is_typeptr_getset(op):
             # ignore the operation completely -- instead, it's done by 'new'
             return

diff --git a/pypy/jit/codewriter/effectinfo.py b/pypy/jit/codewriter/effectinfo.py
--- a/pypy/jit/codewriter/effectinfo.py
+++ b/pypy/jit/codewriter/effectinfo.py
@@ -171,7 +171,8 @@
 class VirtualizableAnalyzer(BoolGraphAnalyzer):
     def analyze_simple_operation(self, op, graphinfo):
         return op.opname in ('jit_force_virtualizable',
-                             'jit_force_virtual')
+                             'jit_force_virtual',
+                             'jit_force_quasi_immutable')
 
 # ____________________________________________________________
 

diff --git a/pypy/jit/codewriter/policy.py b/pypy/jit/codewriter/policy.py
--- a/pypy/jit/codewriter/policy.py
+++ b/pypy/jit/codewriter/policy.py
@@ -1,5 +1,5 @@
 from pypy.translator.simplify import get_funcobj
-from pypy.jit.metainterp import history
+from pypy.jit.metainterp import history, quasiimmut
 from pypy.rpython.lltypesystem import lltype, rclass
 from pypy.tool.udir import udir
 
@@ -85,12 +85,20 @@
                     getkind(v.concretetype, supports_floats, supports_longlong)
                 v = op.result
                 getkind(v.concretetype, supports_floats, supports_longlong)
+                check_skip_operation(op)
     except NotImplementedError, e:
         log.WARNING('%s, ignoring graph' % (e,))
         log.WARNING('  %s' % (graph,))
         return True
     return False
 
+def check_skip_operation(op):
+    if op.opname == 'setfield':
+        if quasiimmut.is_quasi_immutable(op.args[0].concretetype.TO,
+                                         op.args[1].value):
+            raise NotImplementedError("write to quasi-immutable field %r"
+                                      % (op.args[1].value,))
+
 # ____________________________________________________________
 
 class StopAtXPolicy(JitPolicy):

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
@@ -947,3 +947,42 @@
     assert op1.args[1] == 'calldescr-%d' % effectinfo.EffectInfo.OS_ARRAYCOPY
     assert op1.args[2] == ListOfKind('int', [v3, v4, v5])
     assert op1.args[3] == ListOfKind('ref', [v1, v2])
+
+def test_quasi_immutable():
+    from pypy.rpython.rclass import FieldListAccessor, IR_QUASI_IMMUTABLE
+    accessor = FieldListAccessor()
+    accessor.initialize(None, {'inst_x': IR_QUASI_IMMUTABLE})
+    v2 = varoftype(lltype.Signed)
+    STRUCT = lltype.GcStruct('struct', ('inst_x', lltype.Signed),
+                             ('mutate_x', rclass.OBJECTPTR),
+                             hints={'immutable_fields': accessor})
+    for v_x in [const(lltype.malloc(STRUCT)), varoftype(lltype.Ptr(STRUCT))]:
+        op = SpaceOperation('getfield', [v_x, Constant('inst_x', lltype.Void)],
+                            v2)
+        tr = Transformer(FakeCPU())
+        [op1, op2] = tr.rewrite_operation(op)
+        assert op1.opname == 'record_quasiimmut_field'
+        assert len(op1.args) == 2
+        assert op1.args[0] == v_x
+        assert op1.args[1] == ('fielddescr', STRUCT, 'mutate_x')
+        assert op1.result is None
+        assert op2.opname == 'getfield_gc_i'
+        assert len(op2.args) == 2
+        assert op2.args[0] == v_x
+        assert op2.args[1] == ('fielddescr', STRUCT, 'inst_x')
+        assert op2.result is op.result
+
+def test_quasi_immutable_setfield():
+    from pypy.rpython.rclass import FieldListAccessor, IR_QUASI_IMMUTABLE
+    accessor = FieldListAccessor()
+    accessor.initialize(None, {'inst_x': IR_QUASI_IMMUTABLE})
+    v1 = varoftype(lltype.Signed)
+    STRUCT = lltype.GcStruct('struct', ('inst_x', lltype.Signed),
+                             ('mutate_x', rclass.OBJECTPTR),
+                             hints={'immutable_fields': accessor})
+    for v_x in [const(lltype.malloc(STRUCT)), varoftype(lltype.Ptr(STRUCT))]:
+        op = SpaceOperation('setfield',
+                            [v_x, Constant('inst_x', lltype.Void), v1],
+                            varoftype(lltype.Void))
+        tr = Transformer(FakeCPU())
+        raises(NotImplementedError, tr.rewrite_operation, op)


More information about the Pypy-commit mailing list