[pypy-commit] pypy remove-getfield-pure: adapt protect_speculative_operation to getfield being handled by heap.py

cfbolz noreply at buildbot.pypy.org
Mon Nov 23 15:31:59 EST 2015


Author: Carl Friedrich Bolz <cfbolz at gmx.de>
Branch: remove-getfield-pure
Changeset: r80868:c8e4c1dce446
Date: 2015-11-23 21:31 +0100
http://bitbucket.org/pypy/pypy/changeset/c8e4c1dce446/

Log:	adapt protect_speculative_operation to getfield being handled by
	heap.py

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
@@ -600,12 +600,12 @@
 
     def optimize_QUASIIMMUT_FIELD(self, op):
         # Pattern: QUASIIMMUT_FIELD(s, descr=QuasiImmutDescr)
-        #          x = GETFIELD_GC_PURE(s, descr='inst_x')
+        #          x = GETFIELD_GC(s, descr='inst_x') # pure
         # If 's' is a constant (after optimizations) we rely on the rest of the
-        # optimizations to constant-fold the following getfield_gc_pure.
+        # optimizations to constant-fold the following pure getfield_gc.
         # in addition, we record the dependency here to make invalidation work
         # correctly.
-        # NB: emitting the GETFIELD_GC_PURE is only safe because the
+        # NB: emitting the pure GETFIELD_GC is only safe because the
         # QUASIIMMUT_FIELD is also emitted to make sure the dependency is
         # registered.
         structvalue = self.ensure_ptr_info_arg0(op)
diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py b/rpython/jit/metainterp/optimizeopt/optimizer.py
--- a/rpython/jit/metainterp/optimizeopt/optimizer.py
+++ b/rpython/jit/metainterp/optimizeopt/optimizer.py
@@ -5,11 +5,12 @@
      ConstIntBound, MININT, MAXINT, IntUnbounded
 from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method
 from rpython.jit.metainterp.resoperation import rop, AbstractResOp, GuardResOp,\
-     OpHelpers, ResOperation
+     OpHelpers, ResOperation, is_pure_getfield
 from rpython.jit.metainterp.optimizeopt import info
 from rpython.jit.metainterp.typesystem import llhelper
 from rpython.rlib.objectmodel import specialize, we_are_translated
 from rpython.rlib.debug import debug_print
+from rpython.jit.metainterp.optimize import SpeculativeError
 
 
 
@@ -736,12 +737,64 @@
         self.emit_operation(op)
 
     def constant_fold(self, op):
+        self.protect_speculative_operation(op)
         argboxes = [self.get_constant_box(op.getarg(i))
                     for i in range(op.numargs())]
         return execute_nonspec_const(self.cpu, None,
                                        op.getopnum(), argboxes,
                                        op.getdescr(), op.type)
 
+    def protect_speculative_operation(self, op):
+        """When constant-folding a pure operation that reads memory from
+        a gcref, make sure that the gcref is non-null and of a valid type.
+        Otherwise, raise SpeculativeError.  This should only occur when
+        unrolling and optimizing the unrolled loop.  Note that if
+        cpu.supports_guard_gc_type is false, we can't really do this
+        check at all, but then we don't unroll in that case.
+        """
+        opnum = op.getopnum()
+        cpu = self.cpu
+
+        if is_pure_getfield(opnum, op.getdescr()):
+            fielddescr = op.getdescr()
+            ref = self.get_constant_box(op.getarg(0)).getref_base()
+            cpu.protect_speculative_field(ref, fielddescr)
+            return
+
+        elif (opnum == rop.GETARRAYITEM_GC_PURE_I or
+              opnum == rop.GETARRAYITEM_GC_PURE_R or
+              opnum == rop.GETARRAYITEM_GC_PURE_F or
+              opnum == rop.ARRAYLEN_GC):
+            arraydescr = op.getdescr()
+            array = self.get_constant_box(op.getarg(0)).getref_base()
+            cpu.protect_speculative_array(array, arraydescr)
+            if opnum == rop.ARRAYLEN_GC:
+                return
+            arraylength = cpu.bh_arraylen_gc(array, arraydescr)
+
+        elif (opnum == rop.STRGETITEM or
+              opnum == rop.STRLEN):
+            string = self.get_constant_box(op.getarg(0)).getref_base()
+            cpu.protect_speculative_string(string)
+            if opnum == rop.STRLEN:
+                return
+            arraylength = cpu.bh_strlen(string)
+
+        elif (opnum == rop.UNICODEGETITEM or
+              opnum == rop.UNICODELEN):
+            unicode = self.get_constant_box(op.getarg(0)).getref_base()
+            cpu.protect_speculative_unicode(unicode)
+            if opnum == rop.UNICODELEN:
+                return
+            arraylength = cpu.bh_unicodelen(unicode)
+
+        else:
+            return
+
+        index = self.get_constant_box(op.getarg(1)).getint()
+        if not (0 <= index < arraylength):
+            raise SpeculativeError
+
     def is_virtual(self, op):
         if op.type == 'r':
             opinfo = self.getptrinfo(op)
diff --git a/rpython/jit/metainterp/optimizeopt/pure.py b/rpython/jit/metainterp/optimizeopt/pure.py
--- a/rpython/jit/metainterp/optimizeopt/pure.py
+++ b/rpython/jit/metainterp/optimizeopt/pure.py
@@ -94,7 +94,6 @@
                     break
             else:
                 # all constant arguments: constant-fold away
-                self.protect_speculative_operation(op)
                 resbox = self.optimizer.constant_fold(op)
                 # note that INT_xxx_OVF is not done from here, and the
                 # overflows in the INT_xxx operations are ignored
@@ -119,59 +118,6 @@
         if nextop:
             self.emit_operation(nextop)
 
-    def protect_speculative_operation(self, op):
-        """When constant-folding a pure operation that reads memory from
-        a gcref, make sure that the gcref is non-null and of a valid type.
-        Otherwise, raise SpeculativeError.  This should only occur when
-        unrolling and optimizing the unrolled loop.  Note that if
-        cpu.supports_guard_gc_type is false, we can't really do this
-        check at all, but then we don't unroll in that case.
-        """
-        opnum = op.getopnum()
-        cpu = self.optimizer.cpu
-
-        if   (opnum == rop.GETFIELD_GC_PURE_I or
-              opnum == rop.GETFIELD_GC_PURE_R or
-              opnum == rop.GETFIELD_GC_PURE_F):
-            fielddescr = op.getdescr()
-            ref = self.get_constant_box(op.getarg(0)).getref_base()
-            cpu.protect_speculative_field(ref, fielddescr)
-            return
-
-        elif (opnum == rop.GETARRAYITEM_GC_PURE_I or
-              opnum == rop.GETARRAYITEM_GC_PURE_R or
-              opnum == rop.GETARRAYITEM_GC_PURE_F or
-              opnum == rop.ARRAYLEN_GC):
-            arraydescr = op.getdescr()
-            array = self.get_constant_box(op.getarg(0)).getref_base()
-            cpu.protect_speculative_array(array, arraydescr)
-            if opnum == rop.ARRAYLEN_GC:
-                return
-            arraylength = cpu.bh_arraylen_gc(array, arraydescr)
-
-        elif (opnum == rop.STRGETITEM or
-              opnum == rop.STRLEN):
-            string = self.get_constant_box(op.getarg(0)).getref_base()
-            cpu.protect_speculative_string(string)
-            if opnum == rop.STRLEN:
-                return
-            arraylength = cpu.bh_strlen(string)
-
-        elif (opnum == rop.UNICODEGETITEM or
-              opnum == rop.UNICODELEN):
-            unicode = self.get_constant_box(op.getarg(0)).getref_base()
-            cpu.protect_speculative_unicode(unicode)
-            if opnum == rop.UNICODELEN:
-                return
-            arraylength = cpu.bh_unicodelen(unicode)
-
-        else:
-            return
-
-        index = self.get_constant_box(op.getarg(1)).getint()
-        if not (0 <= index < arraylength):
-            raise SpeculativeError
-
     def getrecentops(self, opnum):
         if rop._OVF_FIRST <= opnum <= rop._OVF_LAST:
             opnum = opnum - rop._OVF_FIRST
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_dependency.py b/rpython/jit/metainterp/optimizeopt/test/test_dependency.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_dependency.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_dependency.py
@@ -520,8 +520,8 @@
     def test_getfield(self):
         graph = self.build_dependency("""
         [p0, p1] # 0: 1,2,5
-        p2 = getfield_gc_r(p0) # 1: 3,5
-        p3 = getfield_gc_r(p0) # 2: 4
+        p2 = getfield_gc_r(p0, descr=valuedescr) # 1: 3,5
+        p3 = getfield_gc_r(p0, descr=valuedescr) # 2: 4
         guard_nonnull(p2) [p2] # 3: 4,5
         guard_nonnull(p3) [p3] # 4: 5
         jump(p0,p2) # 5:
@@ -531,10 +531,10 @@
     def test_cyclic(self):
         graph = self.build_dependency("""
         [p0, p1, p5, p6, p7, p9, p11, p12] # 0: 1,6
-        p13 = getfield_gc_r(p9) # 1: 2,5
+        p13 = getfield_gc_r(p9, descr=valuedescr) # 1: 2,5
         guard_nonnull(p13) [] # 2: 4,5
-        i14 = getfield_gc_i(p9) # 3: 5
-        p15 = getfield_gc_r(p13) # 4: 5
+        i14 = getfield_gc_i(p9, descr=valuedescr) # 3: 5
+        p15 = getfield_gc_r(p13, descr=valuedescr) # 4: 5
         guard_class(p15, 14073732) [p1, p0, p9, i14, p15, p13, p5, p6, p7] # 5: 6
         jump(p0,p1,p5,p6,p7,p9,p11,p12) # 6:
         """)
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
@@ -1408,7 +1408,7 @@
         """
         self.optimize_loop(ops, expected)
 
-    def test_getfield_gc_pure_1(self):
+    def test_pure_getfield_gc_1(self):
         ops = """
         [i]
         p1 = new_with_vtable(descr=nodesize)
@@ -1422,7 +1422,7 @@
         """
         self.optimize_loop(ops, expected)
 
-    def test_getfield_gc_pure_2(self):
+    def test_pure_getfield_gc_2(self):
         ops = """
         [i]
         i1 = getfield_gc_i(ConstPtr(myptr3), descr=valuedescr3)
@@ -1435,7 +1435,7 @@
         self.node.value = 5
         self.optimize_loop(ops, expected)
 
-    def test_getfield_gc_pure_3(self):
+    def test_pure_getfield_gc_3(self):
         ops = """
         []
         p1 = escape_r()
@@ -9030,7 +9030,7 @@
         [p0, i1]
         i2 = int_gt(i1, 0)
         guard_true(i2) []
-        getfield_gc_pure_i(p0, descr=valuedescr)
+        getfield_gc_i(p0, descr=valuedescr3)
         i3 = int_sub(i1, 1)
         jump(NULL, i3)
         """
@@ -9041,9 +9041,9 @@
         [p0, i1]
         i2 = int_gt(i1, 0)
         guard_true(i2) []
-        getfield_gc_pure_i(p0, descr=valuedescr)
+        getfield_gc_i(p0, descr=valuedescr3)
         i3 = int_sub(i1, 1)
-        jump(ConstPtr(myptr4), i3)
+        jump(ConstPtr(myptr2), i3)
         """
         py.test.raises(InvalidLoop, self.optimize_loop, ops, ops)
 
diff --git a/rpython/jit/metainterp/test/test_virtual.py b/rpython/jit/metainterp/test/test_virtual.py
--- a/rpython/jit/metainterp/test/test_virtual.py
+++ b/rpython/jit/metainterp/test/test_virtual.py
@@ -1077,7 +1077,7 @@
         res = self.meta_interp(f, [], repeat=7)
         assert res == f()
 
-    def test_getfield_gc_pure_nobug(self):
+    def test_pure_getfield_gc_nobug(self):
         mydriver = JitDriver(reds=['i', 's', 'a'], greens=[])
 
         class A(object):


More information about the pypy-commit mailing list