[pypy-svn] pypy default: During optimization, we can actually detect and complain if we see

arigo commits-noreply at bitbucket.org
Sun Mar 6 01:38:59 CET 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r42430:8bf27ae115d3
Date: 2011-03-05 10:48 -0800
http://bitbucket.org/pypy/pypy/changeset/8bf27ae115d3/

Log:	During optimization, we can actually detect and complain if we see a
	getfield_gc_pure() followed by a setfield_gc() on the same field of
	the same object. This should help tracking down the issue of bogus
	_immutable_fields_ declarations.

diff --git a/pypy/jit/metainterp/test/test_optimizeopt.py b/pypy/jit/metainterp/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/test/test_optimizeopt.py
@@ -163,7 +163,10 @@
 
     def optimize_loop(self, ops, optops, expected_preamble=None):
         loop = self.parse(ops)
-        expected = self.parse(optops)
+        if optops != "crash!":
+            expected = self.parse(optops)
+        else:
+            expected = "crash!"
         if expected_preamble:
             expected_preamble = self.parse(expected_preamble)
         #
@@ -195,7 +198,8 @@
         print loop.inputargs
         print '\n'.join([str(o) for o in loop.operations])
         print
-        
+
+        assert expected != "crash!", "should have raised an exception"
         self.assert_equal(loop, expected)
         if expected_preamble:
             self.assert_equal(loop.preamble, expected_preamble,
@@ -1346,6 +1350,26 @@
         self.node.value = 5
         self.optimize_loop(ops, expected)
 
+    def test_getfield_gc_pure_3(self):
+        ops = """
+        []
+        p1 = escape()
+        p2 = getfield_gc_pure(p1, descr=nextdescr)
+        escape(p2)
+        p3 = getfield_gc_pure(p1, descr=nextdescr)
+        escape(p3)
+        jump()
+        """
+        expected = """
+        []
+        p1 = escape()
+        p2 = getfield_gc_pure(p1, descr=nextdescr)
+        escape(p2)
+        escape(p2)
+        jump()
+        """
+        self.optimize_loop(ops, expected)
+
     def test_getfield_gc_nonpure_2(self):
         ops = """
         [i]
@@ -3806,6 +3830,47 @@
         self.node.value = 5
         self.optimize_loop(ops, expected)
 
+    def test_complains_getfieldpure_setfield(self):
+        from pypy.jit.metainterp.optimizeopt.heap import BogusPureField
+        ops = """
+        [p3]
+        p1 = escape()
+        p2 = getfield_gc_pure(p1, descr=nextdescr)
+        setfield_gc(p1, p3, descr=nextdescr)
+        jump(p3)
+        """
+        py.test.raises(BogusPureField, self.optimize_loop, ops, "crash!")
+
+    def test_dont_complains_different_field(self):
+        ops = """
+        [p3]
+        p1 = escape()
+        p2 = getfield_gc_pure(p1, descr=nextdescr)
+        setfield_gc(p1, p3, descr=otherdescr)
+        escape(p2)
+        jump(p3)
+        """
+        expected = """
+        [p3]
+        p1 = escape()
+        p2 = getfield_gc_pure(p1, descr=nextdescr)
+        setfield_gc(p1, p3, descr=otherdescr)
+        escape(p2)
+        jump(p3)
+        """
+        self.optimize_loop(ops, expected)
+
+    def test_dont_complains_different_object(self):
+        ops = """
+        []
+        p1 = escape()
+        p2 = getfield_gc_pure(p1, descr=nextdescr)
+        p3 = escape()
+        setfield_gc(p3, p1, descr=nextdescr)
+        jump()
+        """
+        self.optimize_loop(ops, ops)
+
     def test_getfield_guard_const(self):
         ops = """
         [p0]

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
@@ -1,6 +1,8 @@
+import os
 from pypy.jit.metainterp.optimizeutil import _findall
 from pypy.jit.metainterp.resoperation import rop, ResOperation
 from pypy.rlib.objectmodel import we_are_translated
+from pypy.jit.metainterp.jitexc import JitException
 
 from pypy.jit.metainterp.optimizeopt.optimizer import Optimization
 
@@ -10,6 +12,9 @@
         self.var_index_item = None
         self.var_index_indexvalue = None
 
+class BogusPureField(JitException):
+    pass
+
 
 class OptHeap(Optimization):
     """Cache repeated heap accesses"""
@@ -298,6 +303,12 @@
         d[value] = fieldvalue
 
     def optimize_SETFIELD_GC(self, op):
+        if self.has_pure_result(rop.GETFIELD_GC_PURE, [op.getarg(0)],
+                                op.getdescr()):
+            os.write(2, '[bogus _immutable_field_ declaration: %s]\n' %
+                     (op.getdescr().repr_of_descr()))
+            raise BogusPureField
+        #
         value = self.getvalue(op.getarg(0))
         fieldvalue = self.getvalue(op.getarg(1))
         cached_fieldvalue = self.read_cached_field(op.getdescr(), value)

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
@@ -216,6 +216,14 @@
         op = ResOperation(opnum, args, result)
         self.optimizer.pure_operations[self.optimizer.make_args_key(op)] = op
 
+    def has_pure_result(self, opnum, args, descr):
+        op = ResOperation(opnum, args, None)
+        key = self.optimizer.make_args_key(op)
+        op = self.optimizer.pure_operations.get(key, None)
+        if op is None:
+            return False
+        return op.getdescr() is descr
+
     def setup(self):
         pass
 


More information about the Pypy-commit mailing list