[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