[pypy-commit] pypy default: Merge latest changes
sbauman
pypy.commits at gmail.com
Thu Jan 21 16:05:58 EST 2016
Author: Spenser Bauman <sabauma at gmail.com>
Branch:
Changeset: r81898:ee7c705360c7
Date: 2016-01-21 16:05 -0500
http://bitbucket.org/pypy/pypy/changeset/ee7c705360c7/
Log: Merge latest changes
diff --git a/pypy/module/pypyjit/test_pypy_c/test_call.py b/pypy/module/pypyjit/test_pypy_c/test_call.py
--- a/pypy/module/pypyjit/test_pypy_c/test_call.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_call.py
@@ -83,9 +83,9 @@
p38 = call_r(ConstClass(_ll_1_threadlocalref_get__Ptr_GcStruct_objectLlT_Signed), #, descr=<Callr . i EF=1 OS=5>)
p39 = getfield_gc_r(p38, descr=<FieldP pypy.interpreter.executioncontext.ExecutionContext.inst_topframeref .*>)
i40 = force_token()
- p41 = getfield_gc_pure_r(p38, descr=<FieldP pypy.interpreter.executioncontext.ExecutionContext.inst_w_tracefunc .*>)
+ p41 = getfield_gc_r(p38, descr=<FieldP pypy.interpreter.executioncontext.ExecutionContext.inst_w_tracefunc .*>)
guard_value(p41, ConstPtr(ptr42), descr=...)
- i42 = getfield_gc_pure_i(p38, descr=<FieldU pypy.interpreter.executioncontext.ExecutionContext.inst_profilefunc .*>)
+ i42 = getfield_gc_i(p38, descr=<FieldU pypy.interpreter.executioncontext.ExecutionContext.inst_profilefunc .*>)
i43 = int_is_zero(i42)
guard_true(i43, descr=...)
i50 = force_token()
@@ -435,21 +435,21 @@
guard_isnull(p5, descr=...)
guard_nonnull_class(p12, ConstClass(W_IntObject), descr=...)
guard_value(p2, ConstPtr(ptr21), descr=...)
- i22 = getfield_gc_pure_i(p12, descr=<FieldS pypy.objspace.std.intobject.W_IntObject.inst_intval .*>)
+ i22 = getfield_gc_i(p12, descr=<FieldS pypy.objspace.std.intobject.W_IntObject.inst_intval .*>)
i24 = int_lt(i22, 5000)
guard_true(i24, descr=...)
guard_not_invalidated(descr=...)
p29 = call_r(ConstClass(_ll_1_threadlocalref_get__Ptr_GcStruct_objectLlT_Signed), #, descr=<Callr . i EF=1 OS=5>)
p30 = getfield_gc_r(p29, descr=<FieldP pypy.interpreter.executioncontext.ExecutionContext.inst_topframeref .*>)
p31 = force_token()
- p32 = getfield_gc_pure_r(p29, descr=<FieldP pypy.interpreter.executioncontext.ExecutionContext.inst_w_tracefunc .*>)
+ p32 = getfield_gc_r(p29, descr=<FieldP pypy.interpreter.executioncontext.ExecutionContext.inst_w_tracefunc .*>)
guard_value(p32, ConstPtr(ptr33), descr=...)
- i34 = getfield_gc_pure_i(p29, descr=<FieldU pypy.interpreter.executioncontext.ExecutionContext.inst_profilefunc .*>)
+ i34 = getfield_gc_i(p29, descr=<FieldU pypy.interpreter.executioncontext.ExecutionContext.inst_profilefunc .*>)
i35 = int_is_zero(i34)
guard_true(i35, descr=...)
p37 = getfield_gc_r(ConstPtr(ptr36), descr=<FieldP pypy.interpreter.nestedscope.Cell.inst_w_value .*>)
guard_nonnull_class(p37, ConstClass(W_IntObject), descr=...)
- i39 = getfield_gc_pure_i(p37, descr=<FieldS pypy.objspace.std.intobject.W_IntObject.inst_intval .*>)
+ i39 = getfield_gc_i(p37, descr=<FieldS pypy.objspace.std.intobject.W_IntObject.inst_intval .*>)
i40 = int_add_ovf(i22, i39)
guard_no_overflow(descr=...)
--TICK--
@@ -466,7 +466,7 @@
""", [])
loop, = log.loops_by_id('call')
assert loop.match("""
- i8 = getfield_gc_pure_i(p6, descr=<FieldS pypy.objspace.std.intobject.W_IntObject.inst_intval .*>)
+ i8 = getfield_gc_i(p6, descr=<FieldS pypy.objspace.std.intobject.W_IntObject.inst_intval .*>)
i10 = int_lt(i8, 5000)
guard_true(i10, descr=...)
guard_not_invalidated?
diff --git a/pypy/module/pypyjit/test_pypy_c/test_containers.py b/pypy/module/pypyjit/test_pypy_c/test_containers.py
--- a/pypy/module/pypyjit/test_pypy_c/test_containers.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_containers.py
@@ -84,7 +84,7 @@
guard_no_exception(descr=...)
p20 = new_with_vtable(descr=...)
call_n(ConstClass(_ll_dict_setitem_lookup_done_trampoline), p13, p10, p20, i12, i17, descr=<Callv 0 rrrii EF=5>)
- setfield_gc(p20, i5, descr=<FieldS .*W_IntObject.inst_intval .*>)
+ setfield_gc(p20, i5, descr=<FieldS .*W_IntObject.inst_intval .* pure>)
guard_no_exception(descr=...)
i23 = call_i(ConstClass(ll_call_lookup_function), p13, p10, i12, 0, descr=<Calli . rrii EF=5 OS=4>)
guard_no_exception(descr=...)
@@ -93,7 +93,7 @@
p28 = getfield_gc_r(p13, descr=<FieldP dicttable.entries .*>)
p29 = getinteriorfield_gc_r(p28, i23, descr=<InteriorFieldDescr <FieldP odictentry.value .*>>)
guard_nonnull_class(p29, ConstClass(W_IntObject), descr=...)
- i31 = getfield_gc_pure_i(p29, descr=<FieldS .*W_IntObject.inst_intval .*>)
+ i31 = getfield_gc_i(p29, descr=<FieldS .*W_IntObject.inst_intval .* pure>)
i32 = int_sub_ovf(i31, i5)
guard_no_overflow(descr=...)
i34 = int_add_ovf(i32, 1)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py b/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
--- a/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
@@ -101,13 +101,13 @@
loop = log._filter(log.loops[0])
assert loop.match("""
guard_class(p1, #, descr=...)
- p4 = getfield_gc_pure_r(p1, descr=<FieldP pypy.module.micronumpy.iterators.ArrayIter.inst_array \d+>)
+ p4 = getfield_gc_r(p1, descr=<FieldP pypy.module.micronumpy.iterators.ArrayIter.inst_array \d+ pure>)
i5 = getfield_gc_i(p0, descr=<FieldS pypy.module.micronumpy.iterators.IterState.inst_offset \d+>)
- p6 = getfield_gc_pure_r(p4, descr=<FieldP pypy.module.micronumpy.concrete.BaseConcreteArray.inst_dtype \d+>)
- p7 = getfield_gc_pure_r(p6, descr=<FieldP pypy.module.micronumpy.descriptor.W_Dtype.inst_itemtype \d+>)
+ p6 = getfield_gc_r(p4, descr=<FieldP pypy.module.micronumpy.concrete.BaseConcreteArray.inst_dtype \d+ pure>)
+ p7 = getfield_gc_r(p6, descr=<FieldP pypy.module.micronumpy.descriptor.W_Dtype.inst_itemtype \d+ pure>)
guard_class(p7, ConstClass(Float64), descr=...)
- i9 = getfield_gc_pure_i(p4, descr=<FieldU pypy.module.micronumpy.concrete.BaseConcreteArray.inst_storage \d+>)
- i10 = getfield_gc_pure_i(p6, descr=<FieldU pypy.module.micronumpy.descriptor.W_Dtype.inst_byteorder \d+>)
+ i9 = getfield_gc_i(p4, descr=<FieldU pypy.module.micronumpy.concrete.BaseConcreteArray.inst_storage \d+ pure>)
+ i10 = getfield_gc_i(p6, descr=<FieldU pypy.module.micronumpy.descriptor.W_Dtype.inst_byteorder \d+ pure>)
i12 = int_eq(i10, 61)
i14 = int_eq(i10, 60)
i15 = int_or(i12, i14)
@@ -117,28 +117,28 @@
i18 = float_ne(f16, 0.000000)
guard_true(i18, descr=...)
guard_nonnull_class(p2, ConstClass(W_BoolBox), descr=...)
- i20 = getfield_gc_pure_i(p2, descr=<FieldU pypy.module.micronumpy.boxes.W_BoolBox.inst_value \d+>)
+ i20 = getfield_gc_i(p2, descr=<FieldU pypy.module.micronumpy.boxes.W_BoolBox.inst_value \d+ pure>)
i21 = int_is_true(i20)
guard_false(i21, descr=...)
i22 = getfield_gc_i(p0, descr=<FieldS pypy.module.micronumpy.iterators.IterState.inst_index \d+>)
- i23 = getfield_gc_pure_i(p1, descr=<FieldU pypy.module.micronumpy.iterators.ArrayIter.inst_track_index \d+>)
+ i23 = getfield_gc_i(p1, descr=<FieldU pypy.module.micronumpy.iterators.ArrayIter.inst_track_index \d+ pure>)
guard_true(i23, descr=...)
i25 = int_add(i22, 1)
- p26 = getfield_gc_pure_r(p0, descr=<FieldP pypy.module.micronumpy.iterators.IterState.inst__indices \d+>)
- i27 = getfield_gc_pure_i(p1, descr=<FieldS pypy.module.micronumpy.iterators.ArrayIter.inst_contiguous \d+>)
+ p26 = getfield_gc_r(p0, descr=<FieldP pypy.module.micronumpy.iterators.IterState.inst__indices \d+ pure>)
+ i27 = getfield_gc_i(p1, descr=<FieldS pypy.module.micronumpy.iterators.ArrayIter.inst_contiguous \d+ pure>)
i28 = int_is_true(i27)
guard_true(i28, descr=...)
- i29 = getfield_gc_pure_i(p6, descr=<FieldS pypy.module.micronumpy.descriptor.W_Dtype.inst_elsize \d+>)
+ i29 = getfield_gc_i(p6, descr=<FieldS pypy.module.micronumpy.descriptor.W_Dtype.inst_elsize \d+ pure>)
guard_value(i29, 8, descr=...)
i30 = int_add(i5, 8)
- i31 = getfield_gc_pure_i(p1, descr=<FieldS pypy.module.micronumpy.iterators.ArrayIter.inst_size \d+>)
+ i31 = getfield_gc_i(p1, descr=<FieldS pypy.module.micronumpy.iterators.ArrayIter.inst_size \d+ pure>)
i32 = int_ge(i25, i31)
guard_false(i32, descr=...)
p34 = new_with_vtable(descr=...)
{{{
- setfield_gc(p34, p1, descr=<FieldP pypy.module.micronumpy.iterators.IterState.inst_iterator \d+>)
+ setfield_gc(p34, p1, descr=<FieldP pypy.module.micronumpy.iterators.IterState.inst_iterator \d+ pure>)
setfield_gc(p34, i25, descr=<FieldS pypy.module.micronumpy.iterators.IterState.inst_index \d+>)
- setfield_gc(p34, p26, descr=<FieldP pypy.module.micronumpy.iterators.IterState.inst__indices \d+>)
+ setfield_gc(p34, p26, descr=<FieldP pypy.module.micronumpy.iterators.IterState.inst__indices \d+ pure>)
setfield_gc(p34, i30, descr=<FieldS pypy.module.micronumpy.iterators.IterState.inst_offset \d+>)
}}}
jump(..., descr=...)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_min_max.py b/pypy/module/pypyjit/test_pypy_c/test_min_max.py
--- a/pypy/module/pypyjit/test_pypy_c/test_min_max.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_min_max.py
@@ -54,7 +54,7 @@
i19 = int_add(i11, 1)
setfield_gc(p2, i19, descr=...)
guard_nonnull_class(p18, ConstClass(W_IntObject), descr=...)
- i20 = getfield_gc_pure_i(p18, descr=...)
+ i20 = getfield_gc_i(p18, descr=...)
i21 = int_gt(i20, i14)
guard_true(i21, descr=...)
jump(..., descr=...)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_misc.py b/pypy/module/pypyjit/test_pypy_c/test_misc.py
--- a/pypy/module/pypyjit/test_pypy_c/test_misc.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_misc.py
@@ -113,7 +113,7 @@
i12 = int_is_true(i4)
guard_true(i12, descr=...)
guard_not_invalidated(descr=...)
- i10p = getfield_gc_pure_i(p10, descr=...)
+ i10p = getfield_gc_i(p10, descr=...)
i10 = int_mul_ovf(2, i10p)
guard_no_overflow(descr=...)
i14 = int_add_ovf(i13, i10)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_string.py b/pypy/module/pypyjit/test_pypy_c/test_string.py
--- a/pypy/module/pypyjit/test_pypy_c/test_string.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_string.py
@@ -82,7 +82,7 @@
strsetitem(p25, 0, i23)
p93 = call_r(ConstClass(fromstr), p25, 16, descr=<Callr . ri EF=4>)
guard_no_exception(descr=...)
- i95 = getfield_gc_pure_i(p93, descr=<FieldS rpython.rlib.rbigint.rbigint.inst_size .*>)
+ i95 = getfield_gc_i(p93, descr=<FieldS rpython.rlib.rbigint.rbigint.inst_size .*>)
i96 = int_gt(i95, #)
guard_false(i96, descr=...)
i94 = call_i(ConstClass(rbigint._toint_helper), p93, descr=<Calli . r EF=4>)
diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py
--- a/rpython/jit/backend/llgraph/runner.py
+++ b/rpython/jit/backend/llgraph/runner.py
@@ -152,7 +152,7 @@
self.fieldname = fieldname
self.FIELD = getattr(S, fieldname)
self.index = heaptracker.get_fielddescr_index_in(S, fieldname)
- self._is_pure = S._immutable_field(fieldname)
+ self._is_pure = S._immutable_field(fieldname) != False
def is_always_pure(self):
return self._is_pure
@@ -608,9 +608,6 @@
p = support.cast_arg(lltype.Ptr(descr.S), p)
return support.cast_result(descr.FIELD, getattr(p, descr.fieldname))
- bh_getfield_gc_pure_i = bh_getfield_gc
- bh_getfield_gc_pure_r = bh_getfield_gc
- bh_getfield_gc_pure_f = bh_getfield_gc
bh_getfield_gc_i = bh_getfield_gc
bh_getfield_gc_r = bh_getfield_gc
bh_getfield_gc_f = bh_getfield_gc
diff --git a/rpython/jit/backend/llsupport/descr.py b/rpython/jit/backend/llsupport/descr.py
--- a/rpython/jit/backend/llsupport/descr.py
+++ b/rpython/jit/backend/llsupport/descr.py
@@ -180,7 +180,8 @@
return self.offset
def repr_of_descr(self):
- return '<Field%s %s %s>' % (self.flag, self.name, self.offset)
+ ispure = " pure" if self._is_pure else ""
+ return '<Field%s %s %s%s>' % (self.flag, self.name, self.offset, ispure)
def get_parent_descr(self):
return self.parent_descr
@@ -200,7 +201,7 @@
flag = get_type_flag(FIELDTYPE)
name = '%s.%s' % (STRUCT._name, fieldname)
index_in_parent = heaptracker.get_fielddescr_index_in(STRUCT, fieldname)
- is_pure = bool(STRUCT._immutable_field(fieldname))
+ is_pure = STRUCT._immutable_field(fieldname) != False
fielddescr = FieldDescr(name, offset, size, flag, index_in_parent,
is_pure)
cachedict = cache.setdefault(STRUCT, {})
diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py
--- a/rpython/jit/backend/x86/assembler.py
+++ b/rpython/jit/backend/x86/assembler.py
@@ -1477,9 +1477,6 @@
genop_getfield_gc_f = _genop_getfield
genop_getfield_raw_i = _genop_getfield
genop_getfield_raw_f = _genop_getfield
- genop_getfield_gc_pure_i = _genop_getfield
- genop_getfield_gc_pure_r = _genop_getfield
- genop_getfield_gc_pure_f = _genop_getfield
def _genop_gc_load(self, op, arglocs, resloc):
base_loc, ofs_loc, size_loc, sign_loc = arglocs
diff --git a/rpython/jit/metainterp/heapcache.py b/rpython/jit/metainterp/heapcache.py
--- a/rpython/jit/metainterp/heapcache.py
+++ b/rpython/jit/metainterp/heapcache.py
@@ -168,9 +168,6 @@
elif (opnum != rop.GETFIELD_GC_R and
opnum != rop.GETFIELD_GC_I and
opnum != rop.GETFIELD_GC_F and
- opnum != rop.GETFIELD_GC_PURE_R and
- opnum != rop.GETFIELD_GC_PURE_I and
- opnum != rop.GETFIELD_GC_PURE_F and
opnum != rop.PTR_EQ and
opnum != rop.PTR_NE and
opnum != rop.INSTANCE_PTR_EQ and
diff --git a/rpython/jit/metainterp/history.py b/rpython/jit/metainterp/history.py
--- a/rpython/jit/metainterp/history.py
+++ b/rpython/jit/metainterp/history.py
@@ -816,9 +816,6 @@
if 'getfield_gc' in check:
assert check.pop('getfield_gc') == 0
check['getfield_gc_i'] = check['getfield_gc_r'] = check['getfield_gc_f'] = 0
- if 'getfield_gc_pure' in check:
- assert check.pop('getfield_gc_pure') == 0
- check['getfield_gc_pure_i'] = check['getfield_gc_pure_r'] = check['getfield_gc_pure_f'] = 0
if 'getarrayitem_gc_pure' in check:
assert check.pop('getarrayitem_gc_pure') == 0
check['getarrayitem_gc_pure_i'] = check['getarrayitem_gc_pure_r'] = check['getarrayitem_gc_pure_f'] = 0
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
@@ -183,6 +183,8 @@
return res
def invalidate(self, descr):
+ if descr.is_always_pure():
+ return
for opinfo in self.cached_infos:
assert isinstance(opinfo, info.AbstractStructPtrInfo)
opinfo._fields[descr.get_index()] = None
@@ -515,9 +517,14 @@
return pendingfields
def optimize_GETFIELD_GC_I(self, op):
+ descr = op.getdescr()
+ if descr.is_always_pure() and self.get_constant_box(op.getarg(0)) is not None:
+ resbox = self.optimizer.constant_fold(op)
+ self.optimizer.make_constant(op, resbox)
+ return
structinfo = self.ensure_ptr_info_arg0(op)
- cf = self.field_cache(op.getdescr())
- field = cf.getfield_from_cache(self, structinfo, op.getdescr())
+ cf = self.field_cache(descr)
+ field = cf.getfield_from_cache(self, structinfo, descr)
if field is not None:
self.make_equal_to(op, field)
return
@@ -525,23 +532,10 @@
self.make_nonnull(op.getarg(0))
self.emit_operation(op)
# then remember the result of reading the field
- structinfo.setfield(op.getdescr(), op.getarg(0), op, optheap=self, cf=cf)
+ structinfo.setfield(descr, op.getarg(0), op, optheap=self, cf=cf)
optimize_GETFIELD_GC_R = optimize_GETFIELD_GC_I
optimize_GETFIELD_GC_F = optimize_GETFIELD_GC_I
- def optimize_GETFIELD_GC_PURE_I(self, op):
- structinfo = self.ensure_ptr_info_arg0(op)
- cf = self.field_cache(op.getdescr())
- field = cf.getfield_from_cache(self, structinfo, op.getdescr())
- if field is not None:
- self.make_equal_to(op, field)
- return
- # default case: produce the operation
- self.make_nonnull(op.getarg(0))
- self.emit_operation(op)
- optimize_GETFIELD_GC_PURE_R = optimize_GETFIELD_GC_PURE_I
- optimize_GETFIELD_GC_PURE_F = optimize_GETFIELD_GC_PURE_I
-
def optimize_SETFIELD_GC(self, op):
self.setfield(op)
#opnum = OpHelpers.getfield_pure_for_descr(op.getdescr())
@@ -631,12 +625,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
@@ -10,6 +10,7 @@
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
@@ -374,6 +375,7 @@
if (box.type == 'i' and box.get_forwarded() and
box.get_forwarded().is_constant()):
return ConstInt(box.get_forwarded().getint())
+ return None
#self.ensure_imported(value)
def get_newoperations(self):
@@ -736,12 +738,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 OpHelpers.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
@@ -521,8 +521,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:
@@ -532,10 +532,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_optimizebasic.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
@@ -955,12 +955,12 @@
"""
self.optimize_loop(ops, expected)
- def test_getfield_gc_pure_1(self):
+ def test_getfield_gc_1(self):
ops = """
[i]
- p1 = new_with_vtable(descr=nodesize)
- setfield_gc(p1, i, descr=valuedescr)
- i1 = getfield_gc_pure_i(p1, descr=valuedescr)
+ p1 = new_with_vtable(descr=nodesize3)
+ setfield_gc(p1, i, descr=valuedescr3)
+ i1 = getfield_gc_i(p1, descr=valuedescr3)
jump(i1)
"""
expected = """
@@ -969,17 +969,16 @@
"""
self.optimize_loop(ops, expected)
- def test_getfield_gc_pure_2(self):
+ def test_getfield_gc_2(self):
ops = """
[i]
- i1 = getfield_gc_pure_i(ConstPtr(myptr), descr=valuedescr)
+ i1 = getfield_gc_i(ConstPtr(myptr3), descr=valuedescr3)
jump(i1)
"""
expected = """
[i]
- jump(5)
- """
- self.node.value = 5
+ jump(7)
+ """
self.optimize_loop(ops, expected)
def test_getfield_gc_nonpure_2(self):
@@ -1343,7 +1342,7 @@
setfield_gc(p1, i1, descr=valuedescr)
#
# some operations on which the above setfield_gc cannot have effect
- i3 = getarrayitem_gc_pure_i(p3, 1, descr=arraydescr)
+ i3 = getarrayitem_gc_i(p3, 1, descr=arraydescr)
i4 = getarrayitem_gc_i(p3, i3, descr=arraydescr)
i5 = int_add(i3, i4)
setarrayitem_gc(p3, 0, i5, descr=arraydescr)
@@ -1355,7 +1354,7 @@
expected = """
[p1, i1, i2, p3]
#
- i3 = getarrayitem_gc_pure_i(p3, 1, descr=arraydescr)
+ i3 = getarrayitem_gc_i(p3, 1, descr=arraydescr)
i4 = getarrayitem_gc_i(p3, i3, descr=arraydescr)
i5 = int_add(i3, i4)
#
@@ -1597,7 +1596,7 @@
ops = """
[p1, p2]
p3 = getarrayitem_gc_r(p1, 0, descr=arraydescr2)
- i4 = getfield_gc_pure_i(ConstPtr(myptr), descr=valuedescr)
+ i4 = getfield_gc_i(ConstPtr(myptr3), descr=valuedescr3)
p5 = getarrayitem_gc_r(p1, 0, descr=arraydescr2)
escape_n(p3)
escape_n(i4)
@@ -1608,7 +1607,7 @@
[p1, p2]
p3 = getarrayitem_gc_r(p1, 0, descr=arraydescr2)
escape_n(p3)
- escape_n(5)
+ escape_n(7)
escape_n(p3)
jump(p1, p2)
"""
@@ -5076,7 +5075,7 @@
[]
quasiimmut_field(ConstPtr(quasiptr), descr=quasiimmutdescr)
guard_not_invalidated() []
- i0 = getfield_gc_pure_i(ConstPtr(quasiptr), descr=quasifielddescr)
+ i0 = getfield_gc_i(ConstPtr(quasiptr), descr=quasifielddescr)
i1 = call_pure_i(123, i0, descr=nonwritedescr)
finish(i1)
"""
@@ -5462,15 +5461,15 @@
def test_getarrayitem_gc_pure_not_invalidated(self):
ops = """
[p0]
- i1 = getarrayitem_gc_pure_i(p0, 1, descr=arraydescr)
+ i1 = getarrayitem_gc_pure_i(p0, 1, descr=arrayimmutdescr)
escape_n(p0)
- i2 = getarrayitem_gc_pure_i(p0, 1, descr=arraydescr)
+ i2 = getarrayitem_gc_pure_i(p0, 1, descr=arrayimmutdescr)
escape_n(i2)
jump(p0)
"""
expected = """
[p0]
- i1 = getarrayitem_gc_pure_i(p0, 1, descr=arraydescr)
+ i1 = getarrayitem_gc_pure_i(p0, 1, descr=arrayimmutdescr)
escape_n(p0)
escape_n(i1)
jump(p0)
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
@@ -1409,12 +1409,12 @@
"""
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)
setfield_gc(p1, i, descr=valuedescr)
- i1 = getfield_gc_pure_i(p1, descr=valuedescr)
+ i1 = getfield_gc_i(p1, descr=valuedescr)
jump(i1)
"""
expected = """
@@ -1423,10 +1423,10 @@
"""
self.optimize_loop(ops, expected)
- def test_getfield_gc_pure_2(self):
+ def test_pure_getfield_gc_2(self):
ops = """
[i]
- i1 = getfield_gc_pure_i(ConstPtr(myptr), descr=valuedescr)
+ i1 = getfield_gc_i(ConstPtr(myptr3), descr=valuedescr3)
jump(i1)
"""
expected = """
@@ -1436,20 +1436,20 @@
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()
- p2 = getfield_gc_pure_r(p1, descr=nextdescr)
+ p2 = getfield_gc_r(p1, descr=nextdescr3)
escape_n(p2)
- p3 = getfield_gc_pure_r(p1, descr=nextdescr)
+ p3 = getfield_gc_r(p1, descr=nextdescr3)
escape_n(p3)
jump()
"""
expected = """
[]
p1 = escape_r()
- p2 = getfield_gc_pure_r(p1, descr=nextdescr)
+ p2 = getfield_gc_r(p1, descr=nextdescr3)
escape_n(p2)
escape_n(p2)
jump()
@@ -2319,7 +2319,7 @@
setfield_gc(p1, i1, descr=valuedescr)
#
# some operations on which the above setfield_gc cannot have effect
- i3 = getarrayitem_gc_pure_i(p3, 1, descr=arraydescr)
+ i3 = getarrayitem_gc_i(p3, 1, descr=arraydescr)
i4 = getarrayitem_gc_i(p3, i3, descr=arraydescr)
i5 = int_add(i3, i4)
setarrayitem_gc(p3, 0, i5, descr=arraydescr)
@@ -2332,7 +2332,7 @@
preamble = """
[p1, i1, i2, p3]
#
- i3 = getarrayitem_gc_pure_i(p3, 1, descr=arraydescr)
+ i3 = getarrayitem_gc_i(p3, 1, descr=arraydescr)
i4 = getarrayitem_gc_i(p3, i3, descr=arraydescr)
i5 = int_add(i3, i4)
#
@@ -2340,11 +2340,12 @@
setfield_gc(p1, i4, descr=nextdescr)
setarrayitem_gc(p3, 0, i5, descr=arraydescr)
escape_n()
- jump(p1, i1, i2, p3, i3)
- """
- expected = """
- [p1, i1, i2, p3, i3]
+ jump(p1, i1, i2, p3)
+ """
+ expected = """
+ [p1, i1, i2, p3]
#
+ i3 = getarrayitem_gc_i(p3, 1, descr=arraydescr)
i4 = getarrayitem_gc_i(p3, i3, descr=arraydescr)
i5 = int_add(i3, i4)
#
@@ -2352,8 +2353,7 @@
setfield_gc(p1, i4, descr=nextdescr)
setarrayitem_gc(p3, 0, i5, descr=arraydescr)
escape_n()
- ifoo = arraylen_gc(p3, descr=arraydescr) # killed by the backend
- jump(p1, i1, i2, p3, i3)
+ jump(p1, i1, i2, p3)
"""
self.optimize_loop(ops, expected, preamble)
@@ -2669,7 +2669,7 @@
ops = """
[p1, p2]
p3 = getarrayitem_gc_r(p1, 0, descr=arraydescr2)
- i4 = getfield_gc_pure_i(ConstPtr(myptr), descr=valuedescr)
+ i4 = getfield_gc_i(ConstPtr(myptr3), descr=valuedescr3)
p5 = getarrayitem_gc_r(p1, 0, descr=arraydescr2)
escape_n(p3)
escape_n(i4)
@@ -2680,7 +2680,7 @@
[p1, p2]
p3 = getarrayitem_gc_r(p1, 0, descr=arraydescr2)
escape_n(p3)
- escape_n(5)
+ escape_n(7)
escape_n(p3)
jump(p1, p2)
"""
@@ -3302,8 +3302,8 @@
[p8, p11, i24]
p26 = new(descr=ssize)
setfield_gc(p26, i24, descr=adescr)
- i34 = getfield_gc_pure_i(p11, descr=abisdescr)
- i35 = getfield_gc_pure_i(p26, descr=adescr)
+ i34 = getfield_gc_i(p11, descr=abisdescr)
+ i35 = getfield_gc_i(p26, descr=adescr)
i36 = int_add_ovf(i34, i35)
guard_no_overflow() []
jump(p8, p11, i35)
@@ -3330,8 +3330,8 @@
setfield_gc(p26, i24, descr=adescr)
i28 = int_add(i17, 1)
setfield_gc(p8, i28, descr=valuedescr)
- i34 = getfield_gc_pure_i(p11, descr=valuedescr3)
- i35 = getfield_gc_pure_i(p26, descr=adescr)
+ i34 = getfield_gc_i(p11, descr=valuedescr3)
+ i35 = getfield_gc_i(p26, descr=adescr)
guard_nonnull(p12) []
i36 = int_add_ovf(i34, i35)
guard_no_overflow() []
@@ -3522,14 +3522,14 @@
def test_residual_call_does_not_invalidate_immutable_caches(self):
ops = """
[p1]
- i1 = getfield_gc_pure_i(p1, descr=valuedescr3)
+ i1 = getfield_gc_i(p1, descr=valuedescr3)
i2 = call_i(i1, descr=writevalue3descr)
- i3 = getfield_gc_pure_i(p1, descr=valuedescr3)
+ i3 = getfield_gc_i(p1, descr=valuedescr3)
jump(p1)
"""
expected_preamble = """
[p1]
- i1 = getfield_gc_pure_i(p1, descr=valuedescr3)
+ i1 = getfield_gc_i(p1, descr=valuedescr3)
i2 = call_i(i1, descr=writevalue3descr)
jump(p1, i1)
"""
@@ -4878,11 +4878,11 @@
def test_add_sub_ovf_virtual_unroll(self):
ops = """
[p15]
- i886 = getfield_gc_pure_i(p15, descr=valuedescr)
+ i886 = getfield_gc_i(p15, descr=valuedescr)
i888 = int_sub_ovf(i886, 1)
guard_no_overflow() []
escape_n(i888)
- i4360 = getfield_gc_pure_i(p15, descr=valuedescr)
+ i4360 = getfield_gc_i(p15, descr=valuedescr)
i4362 = int_add_ovf(i4360, 1)
guard_no_overflow() []
i4360p = int_sub_ovf(i4362, 1)
@@ -4972,18 +4972,16 @@
def test_pure(self):
ops = """
[p42]
- p53 = getfield_gc_r(ConstPtr(myptr), descr=nextdescr)
- p59 = getfield_gc_pure_r(p53, descr=valuedescr)
+ p53 = getfield_gc_r(ConstPtr(myptr3), descr=nextdescr3)
+ p59 = getfield_gc_r(p53, descr=valuedescr3)
i61 = call_i(1, p59, descr=nonwritedescr)
jump(p42)
"""
expected = """
- [p42, p59]
- i61 = call_i(1, p59, descr=nonwritedescr)
- jump(p42, p59)
-
- """
- self.node.value = 5
+ [p42]
+ i61 = call_i(1, 7, descr=nonwritedescr)
+ jump(p42)
+ """
self.optimize_loop(ops, expected)
def test_complains_getfieldpure_setfield(self):
@@ -4992,7 +4990,7 @@
ops = """
[p3]
p1 = escape_r()
- p2 = getfield_gc_pure_r(p1, descr=nextdescr)
+ p2 = getfield_gc_r(p1, descr=nextdescr)
setfield_gc(p1, p3, descr=nextdescr)
jump(p3)
"""
@@ -5002,7 +5000,7 @@
ops = """
[p3]
p1 = escape_r()
- p2 = getfield_gc_pure_r(p1, descr=nextdescr)
+ p2 = getfield_gc_r(p1, descr=nextdescr3)
setfield_gc(p1, p3, descr=otherdescr)
escape_n(p2)
jump(p3)
@@ -5010,7 +5008,7 @@
expected = """
[p3]
p1 = escape_r()
- p2 = getfield_gc_pure_r(p1, descr=nextdescr)
+ p2 = getfield_gc_r(p1, descr=nextdescr3)
setfield_gc(p1, p3, descr=otherdescr)
escape_n(p2)
jump(p3)
@@ -5021,7 +5019,7 @@
ops = """
[]
p1 = escape_r()
- p2 = getfield_gc_pure_r(p1, descr=nextdescr)
+ p2 = getfield_gc_r(p1, descr=nextdescr)
p3 = escape_r()
setfield_gc(p3, p1, descr=nextdescr)
jump()
@@ -6167,14 +6165,14 @@
def test_bug_unroll_with_immutables(self):
ops = """
[p0]
- i2 = getfield_gc_pure_i(p0, descr=immut_intval)
+ i2 = getfield_gc_i(p0, descr=immut_intval)
p1 = new_with_vtable(descr=immut_descr)
setfield_gc(p1, 1242, descr=immut_intval)
jump(p1)
"""
preamble = """
[p0]
- i2 = getfield_gc_pure_i(p0, descr=immut_intval)
+ i2 = getfield_gc_i(p0, descr=immut_intval)
jump()
"""
expected = """
@@ -7229,13 +7227,13 @@
[p0, p1, i0]
quasiimmut_field(p0, descr=quasiimmutdescr)
guard_not_invalidated() []
- i1 = getfield_gc_pure_i(p0, descr=quasifielddescr)
+ i1 = getfield_gc_i(p0, descr=quasifielddescr)
escape_n(i1)
jump(p1, p0, i1)
"""
expected = """
[p0, p1, i0]
- i1 = getfield_gc_pure_i(p0, descr=quasifielddescr)
+ i1 = getfield_gc_i(p0, descr=quasifielddescr)
escape_n(i1)
jump(p1, p0, i1)
"""
@@ -7246,7 +7244,7 @@
[]
quasiimmut_field(ConstPtr(quasiptr), descr=quasiimmutdescr)
guard_not_invalidated() []
- i1 = getfield_gc_pure_i(ConstPtr(quasiptr), descr=quasifielddescr)
+ i1 = getfield_gc_i(ConstPtr(quasiptr), descr=quasifielddescr)
escape_n(i1)
jump()
"""
@@ -7298,11 +7296,11 @@
[i0a, i0b]
quasiimmut_field(ConstPtr(quasiptr), descr=quasiimmutdescr)
guard_not_invalidated() []
- i1 = getfield_gc_pure_i(ConstPtr(quasiptr), descr=quasifielddescr)
+ i1 = getfield_gc_i(ConstPtr(quasiptr), descr=quasifielddescr)
call_may_force_n(i0b, descr=mayforcevirtdescr)
quasiimmut_field(ConstPtr(quasiptr), descr=quasiimmutdescr)
guard_not_invalidated() []
- i2 = getfield_gc_pure_i(ConstPtr(quasiptr), descr=quasifielddescr)
+ i2 = getfield_gc_i(ConstPtr(quasiptr), descr=quasifielddescr)
i3 = escape_i(i1)
i4 = escape_i(i2)
jump(i3, i4)
@@ -7325,11 +7323,11 @@
setfield_gc(p, 421, descr=quasifielddescr)
quasiimmut_field(p, descr=quasiimmutdescr)
guard_not_invalidated() []
- i1 = getfield_gc_pure_i(p, descr=quasifielddescr)
+ i1 = getfield_gc_i(p, descr=quasifielddescr)
call_may_force_n(i0b, descr=mayforcevirtdescr)
quasiimmut_field(p, descr=quasiimmutdescr)
guard_not_invalidated() []
- i2 = getfield_gc_pure_i(p, descr=quasifielddescr)
+ i2 = getfield_gc_i(p, descr=quasifielddescr)
i3 = escape_i(i1)
i4 = escape_i(i2)
jump(i3, i4)
@@ -7568,7 +7566,7 @@
def test_forced_virtual_pure_getfield(self):
ops = """
[p0]
- p1 = getfield_gc_pure_r(p0, descr=valuedescr)
+ p1 = getfield_gc_r(p0, descr=valuedescr3)
jump(p1)
"""
self.optimize_loop(ops, ops)
@@ -7578,7 +7576,7 @@
p1 = new_with_vtable(descr=nodesize3)
setfield_gc(p1, p0, descr=valuedescr3)
escape_n(p1)
- p2 = getfield_gc_pure_r(p1, descr=valuedescr3)
+ p2 = getfield_gc_r(p1, descr=valuedescr3)
escape_n(p2)
jump(p0)
"""
@@ -7852,14 +7850,14 @@
def test_loopinvariant_getarrayitem_gc_pure(self):
ops = """
[p9, i1]
- i843 = getarrayitem_gc_pure_i(p9, i1, descr=arraydescr)
+ i843 = getarrayitem_gc_pure_i(p9, i1, descr=arrayimmutdescr)
call_n(i843, descr=nonwritedescr)
jump(p9, i1)
"""
expected = """
[p9, i1, i843]
call_n(i843, descr=nonwritedescr)
- ifoo = arraylen_gc(p9, descr=arraydescr)
+ ifoo = arraylen_gc(p9, descr=arrayimmutdescr)
jump(p9, i1, i843)
"""
self.optimize_loop(ops, expected)
@@ -7868,7 +7866,7 @@
ops = """
[p0]
p1 = getfield_gc_r(p0, descr=nextdescr)
- p2 = getarrayitem_gc_pure_r(p1, 7, descr=gcarraydescr)
+ p2 = getarrayitem_gc_r(p1, 7, descr=gcarraydescr)
call_n(p2, descr=nonwritedescr)
jump(p0)
"""
@@ -7883,14 +7881,14 @@
i1 = arraylen_gc(p1, descr=gcarraydescr)
i2 = int_ge(i1, 8)
guard_true(i2) []
- p2 = getarrayitem_gc_pure_r(p1, 7, descr=gcarraydescr)
- jump(p2, p1)
- """
- expected = """
- [p0, p2, p1]
+ p2 = getarrayitem_gc_r(p1, 7, descr=gcarraydescr)
+ jump(p1, p2)
+ """
+ expected = """
+ [p0, p1, p2]
call_n(p2, descr=nonwritedescr)
i3 = arraylen_gc(p1, descr=gcarraydescr) # Should be killed by backend
- jump(p0, p2, p1)
+ jump(p0, p1, p2)
"""
self.optimize_loop(ops, expected, expected_short=short)
@@ -8065,7 +8063,7 @@
def test_dont_mixup_equal_boxes(self):
ops = """
[p8]
- i9 = getfield_gc_pure_i(p8, descr=valuedescr)
+ i9 = getfield_gc_i(p8, descr=valuedescr3)
i10 = int_gt(i9, 0)
guard_true(i10) []
i29 = int_lshift(i9, 1)
@@ -8160,9 +8158,9 @@
py.test.skip("would be fixed by make heap optimizer aware of virtual setfields")
ops = """
[p5, p8]
- i9 = getfield_gc_pure_i(p5, descr=valuedescr)
+ i9 = getfield_gc_i(p5, descr=valuedescr)
call_n(i9, descr=nonwritedescr)
- i11 = getfield_gc_pure_i(p8, descr=valuedescr)
+ i11 = getfield_gc_i(p8, descr=valuedescr)
i13 = int_add_ovf(i11, 1)
guard_no_overflow() []
p22 = new_with_vtable(descr=nodesize)
@@ -8201,14 +8199,14 @@
ops = """
[p0]
p10 = getfield_gc_r(ConstPtr(myptr), descr=otherdescr)
- guard_value(p10, ConstPtr(myptr2)) []
+ guard_value(p10, ConstPtr(myptrb)) []
call_n(p10, descr=nonwritedescr)
- setfield_gc(ConstPtr(myptr), ConstPtr(myptr2), descr=otherdescr)
+ setfield_gc(ConstPtr(myptr), ConstPtr(myptrb), descr=otherdescr)
jump(p0)
"""
expected = """
[p0]
- call_n(ConstPtr(myptr2), descr=nonwritedescr)
+ call_n(ConstPtr(myptrb), descr=nonwritedescr)
jump(p0)
"""
self.optimize_loop(ops, expected)
@@ -8232,14 +8230,14 @@
ops = """
[p0]
p10 = getfield_gc_r(p0, descr=otherdescr)
- guard_value(p10, ConstPtr(myptr2)) []
+ guard_value(p10, ConstPtr(myptrb)) []
call_n(p10, descr=nonwritedescr)
- setfield_gc(p0, ConstPtr(myptr2), descr=otherdescr)
+ setfield_gc(p0, ConstPtr(myptrb), descr=otherdescr)
jump(p0)
"""
expected = """
[p0]
- call_n(ConstPtr(myptr2), descr=nonwritedescr)
+ call_n(ConstPtr(myptrb), descr=nonwritedescr)
jump(p0)
"""
self.optimize_loop(ops, expected)
@@ -8624,17 +8622,17 @@
[p10]
p52 = getfield_gc_r(p10, descr=nextdescr) # inst_storage
p54 = getarrayitem_gc_r(p52, 0, descr=arraydescr)
- p69 = getfield_gc_pure_r(p54, descr=otherdescr) # inst_w_function
+ p69 = getfield_gc_r(p54, descr=otherdescr) # inst_w_function
quasiimmut_field(p69, descr=quasiimmutdescr)
guard_not_invalidated() []
- p71 = getfield_gc_pure_r(p69, descr=quasifielddescr) # inst_code
+ p71 = getfield_gc_r(p69, descr=quasifielddescr) # inst_code
guard_value(p71, -4247) []
p106 = new_with_vtable(descr=nodesize)
p108 = new_array(3, descr=arraydescr)
p110 = new_with_vtable(descr=nodesize)
- setfield_gc(p110, ConstPtr(myptr2), descr=otherdescr) # inst_w_function
+ setfield_gc(p110, ConstPtr(myptrb), descr=otherdescr) # inst_w_function
setarrayitem_gc(p108, 0, p110, descr=arraydescr)
setfield_gc(p106, p108, descr=nextdescr) # inst_storage
jump(p106)
@@ -8650,7 +8648,7 @@
[p69]
quasiimmut_field(p69, descr=quasiimmutdescr)
guard_not_invalidated() []
- p71 = getfield_gc_pure_r(p69, descr=quasifielddescr) # inst_code
+ p71 = getfield_gc_r(p69, descr=quasifielddescr) # inst_code
guard_value(p71, -4247) []
jump(ConstPtr(myptr))
"""
@@ -8852,13 +8850,13 @@
def test_virtual_back_and_forth(self):
ops = """
[p0]
- p1 = getfield_gc_pure_r(p0, descr=bdescr)
+ p1 = getfield_gc_r(p0, descr=nextdescr3)
ptemp = new_with_vtable(descr=nodesize)
setfield_gc(ptemp, p1, descr=nextdescr)
p2 = getfield_gc_r(ptemp, descr=nextdescr)
- ix = getarrayitem_gc_pure_i(p2, 0, descr=arraydescr)
+ ix = getarrayitem_gc_pure_i(p2, 0, descr=arrayimmutdescr)
pfoo = getfield_gc_r(ptemp, descr=nextdescr)
- guard_value(pfoo, ConstPtr(myarray)) []
+ guard_value(pfoo, ConstPtr(immutarray)) []
ifoo = int_add(ix, 13)
escape_n(ix)
jump(p0)
@@ -8888,13 +8886,13 @@
def test_constant_float_pure(self):
ops = """
[p0]
- f0 = getarrayitem_gc_pure_f(p0, 3, descr=floatarraydescr)
+ f0 = getarrayitem_gc_pure_f(p0, 3, descr=floatarrayimmutdescr)
guard_value(f0, 1.03) []
jump(p0)
"""
expected = """
[p0]
- ifoo = arraylen_gc(p0, descr=floatarraydescr)
+ ifoo = arraylen_gc(p0, descr=floatarrayimmutdescr)
jump(p0)
"""
self.optimize_loop(ops, expected)
@@ -9102,7 +9100,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)
"""
@@ -9113,9 +9111,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)
@@ -9265,9 +9263,126 @@
guard_value(i1, 5) []
jump()
"""
- a = lltype.malloc(lltype.GcArray(lltype.Ptr(self.NODE)), 5, zero=True)
+ a = lltype.malloc(lltype.GcArray(lltype.Ptr(self.NODE3)), 5, zero=True)
self.optimize_loop(ops, expected, jump_values=[a])
+ def test_large_number_of_immutable_references(self):
+ ops = """
+ [p0]
+ i0 = getfield_gc_i(p0, descr=bigadescr)
+ i1 = getfield_gc_i(p0, descr=bigbdescr)
+ i2 = getfield_gc_i(p0, descr=bigcdescr)
+ i3 = getfield_gc_i(p0, descr=bigddescr)
+ i4 = getfield_gc_i(p0, descr=bigedescr)
+ i5 = getfield_gc_i(p0, descr=bigfdescr)
+ i6 = getfield_gc_i(p0, descr=biggdescr)
+ i7 = getfield_gc_i(p0, descr=bighdescr)
+ i8 = getfield_gc_i(p0, descr=bigidescr)
+ i9 = getfield_gc_i(p0, descr=bigjdescr)
+ i10 = getfield_gc_i(p0, descr=bigkdescr)
+ i11 = getfield_gc_i(p0, descr=bigldescr)
+ i12 = getfield_gc_i(p0, descr=bigmdescr)
+ i13 = getfield_gc_i(p0, descr=bigndescr)
+ i14 = getfield_gc_i(p0, descr=bigodescr)
+ i15 = getfield_gc_i(p0, descr=bigpdescr)
+ i16 = getfield_gc_i(p0, descr=bigqdescr)
+ i17 = getfield_gc_i(p0, descr=bigrdescr)
+ i18 = getfield_gc_i(p0, descr=bigsdescr)
+ i19 = getfield_gc_i(p0, descr=bigtdescr)
+ i20 = getfield_gc_i(p0, descr=bigudescr)
+ i21 = getfield_gc_i(p0, descr=bigvdescr)
+ i22 = getfield_gc_i(p0, descr=bigwdescr)
+ i23 = getfield_gc_i(p0, descr=bigxdescr)
+ i24 = getfield_gc_i(p0, descr=bigydescr)
+ i25 = getfield_gc_i(p0, descr=bigzdescr)
+ i27 = getfield_gc_i(p0, descr=bigbdescr)
+ i28 = getfield_gc_i(p0, descr=bigcdescr)
+ i29 = getfield_gc_i(p0, descr=bigddescr)
+ i30 = getfield_gc_i(p0, descr=bigedescr)
+ i31 = getfield_gc_i(p0, descr=bigfdescr)
+ i32 = getfield_gc_i(p0, descr=biggdescr)
+ i33 = getfield_gc_i(p0, descr=bighdescr)
+ i34 = getfield_gc_i(p0, descr=bigidescr)
+ i35 = getfield_gc_i(p0, descr=bigjdescr)
+ i36 = getfield_gc_i(p0, descr=bigkdescr)
+ i37 = getfield_gc_i(p0, descr=bigldescr)
+ i38 = getfield_gc_i(p0, descr=bigmdescr)
+ i39 = getfield_gc_i(p0, descr=bigndescr)
+ i40 = getfield_gc_i(p0, descr=bigodescr)
+ i41 = getfield_gc_i(p0, descr=bigpdescr)
+ i42 = getfield_gc_i(p0, descr=bigqdescr)
+ i43 = getfield_gc_i(p0, descr=bigrdescr)
+ i44 = getfield_gc_i(p0, descr=bigsdescr)
+ i45 = getfield_gc_i(p0, descr=bigtdescr)
+ i46 = getfield_gc_i(p0, descr=bigudescr)
+ i47 = getfield_gc_i(p0, descr=bigvdescr)
+ i48 = getfield_gc_i(p0, descr=bigwdescr)
+ i49 = getfield_gc_i(p0, descr=bigxdescr)
+ i50 = getfield_gc_i(p0, descr=bigydescr)
+ i51 = getfield_gc_i(p0, descr=bigzdescr)
+ i26 = getfield_gc_i(p0, descr=bigadescr)
+ i99 = int_add(i26, i51)
+ escape_i(i27)
+ escape_i(i28)
+ escape_i(i29)
+ escape_i(i30)
+ escape_i(i31)
+ escape_i(i32)
+ escape_i(i33)
+ escape_i(i34)
+ escape_i(i35)
+ escape_i(i36)
+ escape_i(i37)
+ escape_i(i38)
+ escape_i(i39)
+ escape_i(i40)
+ escape_i(i41)
+ escape_i(i42)
+ escape_i(i43)
+ escape_i(i44)
+ escape_i(i45)
+ escape_i(i46)
+ escape_i(i47)
+ escape_i(i48)
+ escape_i(i49)
+ escape_i(i50)
+ escape_i(i51)
+ escape_i(i26)
+ escape_i(i99)
+ jump(p0)
+ """
+ expected = """
+ [p0,i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15,i16,i17,i18,i19,i20,i21,i22,i23,i24,i25,i0,i99]
+ escape_i(i1)
+ escape_i(i2)
+ escape_i(i3)
+ escape_i(i4)
+ escape_i(i5)
+ escape_i(i6)
+ escape_i(i7)
+ escape_i(i8)
+ escape_i(i9)
+ escape_i(i10)
+ escape_i(i11)
+ escape_i(i12)
+ escape_i(i13)
+ escape_i(i14)
+ escape_i(i15)
+ escape_i(i16)
+ escape_i(i17)
+ escape_i(i18)
+ escape_i(i19)
+ escape_i(i20)
+ escape_i(i21)
+ escape_i(i22)
+ escape_i(i23)
+ escape_i(i24)
+ escape_i(i25)
+ escape_i(i0)
+ escape_i(i99)
+ jump(p0,i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15,i16,i17,i18,i19,i20,i21,i22,i23,i24,i25,i0,i99)
+ """
+ self.optimize_loop(ops, expected)
class TestLLtype(OptimizeOptTest, LLtypeMixin):
pass
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_unroll.py b/rpython/jit/metainterp/optimizeopt/test/test_unroll.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_unroll.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_unroll.py
@@ -220,16 +220,16 @@
def test_double_getfield_plus_pure(self):
loop = """
[p0]
- pc = getfield_gc_pure_r(p0, descr=nextdescr)
+ pc = getfield_gc_r(p0, descr=nextdescr3)
escape_n(p0) # that should flush the caches
- p1 = getfield_gc_r(pc, descr=nextdescr)
- i0 = getfield_gc_i(p1, descr=valuedescr)
+ p1 = getfield_gc_r(pc, descr=nextdescr3)
+ i0 = getfield_gc_i(p1, descr=valuedescr3)
jump(p0)
"""
es, loop, preamble = self.optimize(loop)
assert len(es.short_boxes) == 4
# both getfields are available as
- # well as getfield_gc_pure
+ # well as getfield_gc
def test_p123_anti_nested(self):
loop = """
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_util.py b/rpython/jit/metainterp/optimizeopt/test/test_util.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_util.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_util.py
@@ -1,4 +1,4 @@
-import py, random
+import py, random, string
from rpython.rlib.debug import debug_print
from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
@@ -122,7 +122,14 @@
('value', lltype.Signed),
('next', lltype.Ptr(NODE3)),
hints={'immutable': True}))
-
+
+ big_fields = [('big' + i, lltype.Signed) for i in string.ascii_lowercase]
+ BIG = lltype.GcForwardReference()
+ BIG.become(lltype.GcStruct('BIG', *big_fields, hints={'immutable': True}))
+
+ for field, _ in big_fields:
+ locals()[field + 'descr'] = cpu.fielddescrof(BIG, field)
+
node = lltype.malloc(NODE)
node.value = 5
node.next = node
@@ -133,16 +140,25 @@
node2.parent.parent.typeptr = node_vtable2
node2addr = lltype.cast_opaque_ptr(llmemory.GCREF, node2)
myptr = lltype.cast_opaque_ptr(llmemory.GCREF, node)
- mynode2 = lltype.malloc(NODE)
+ mynodeb = lltype.malloc(NODE)
myarray = lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(lltype.GcArray(lltype.Signed), 13, zero=True))
- mynode2.parent.typeptr = node_vtable
- myptr2 = lltype.cast_opaque_ptr(llmemory.GCREF, mynode2)
- mynode3 = lltype.malloc(NODE2)
- mynode3.parent.parent.typeptr = node_vtable2
+ mynodeb.parent.typeptr = node_vtable
+ myptrb = lltype.cast_opaque_ptr(llmemory.GCREF, mynodeb)
+ myptr2 = lltype.malloc(NODE2)
+ myptr2.parent.parent.typeptr = node_vtable2
+ myptr2 = lltype.cast_opaque_ptr(llmemory.GCREF, myptr2)
+ nullptr = lltype.nullptr(llmemory.GCREF.TO)
+
+ mynode3 = lltype.malloc(NODE3)
+ mynode3.parent.typeptr = node_vtable3
+ mynode3.value = 7
+ mynode3.next = mynode3
myptr3 = lltype.cast_opaque_ptr(llmemory.GCREF, mynode3) # a NODE2
mynode4 = lltype.malloc(NODE3)
mynode4.parent.typeptr = node_vtable3
myptr4 = lltype.cast_opaque_ptr(llmemory.GCREF, mynode4) # a NODE3
+
+
nullptr = lltype.nullptr(llmemory.GCREF.TO)
#nodebox2 = InputArgRef(lltype.cast_opaque_ptr(llmemory.GCREF, node2))
nodesize = cpu.sizeof(NODE, node_vtable)
@@ -203,7 +219,6 @@
arraydescr = cpu.arraydescrof(lltype.GcArray(lltype.Signed))
int32arraydescr = cpu.arraydescrof(lltype.GcArray(rffi.INT))
int16arraydescr = cpu.arraydescrof(lltype.GcArray(rffi.SHORT))
- floatarraydescr = cpu.arraydescrof(lltype.GcArray(lltype.Float))
float32arraydescr = cpu.arraydescrof(lltype.GcArray(lltype.SingleFloat))
arraydescr_tid = arraydescr.get_type_id()
array = lltype.malloc(lltype.GcArray(lltype.Signed), 15, zero=True)
@@ -212,6 +227,12 @@
array2ref = lltype.cast_opaque_ptr(llmemory.GCREF, array2)
gcarraydescr = cpu.arraydescrof(lltype.GcArray(llmemory.GCREF))
gcarraydescr_tid = gcarraydescr.get_type_id()
+ floatarraydescr = cpu.arraydescrof(lltype.GcArray(lltype.Float))
+
+ arrayimmutdescr = cpu.arraydescrof(lltype.GcArray(lltype.Signed, hints={"immutable": True}))
+ immutarray = lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(arrayimmutdescr.A, 13, zero=True))
+ gcarrayimmutdescr = cpu.arraydescrof(lltype.GcArray(llmemory.GCREF, hints={"immutable": True}))
+ floatarrayimmutdescr = cpu.arraydescrof(lltype.GcArray(lltype.Float, hints={"immutable": True}))
# a GcStruct not inheriting from OBJECT
tpl = lltype.malloc(S, zero=True)
@@ -244,7 +265,7 @@
tsize = cpu.sizeof(T, None)
cdescr = cpu.fielddescrof(T, 'c')
ddescr = cpu.fielddescrof(T, 'd')
- arraydescr3 = cpu.arraydescrof(lltype.GcArray(lltype.Ptr(NODE)))
+ arraydescr3 = cpu.arraydescrof(lltype.GcArray(lltype.Ptr(NODE3)))
U = lltype.GcStruct('U',
('parent', OBJECT),
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_virtualstate.py b/rpython/jit/metainterp/optimizeopt/test/test_virtualstate.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_virtualstate.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_virtualstate.py
@@ -1103,8 +1103,8 @@
jump(p0)
"""
self.optimize_bridge(loops, bridge, loops[0], 'Loop0', [self.myptr])
- self.optimize_bridge(loops, bridge, loops[1], 'Loop1', [self.myptr3])
- self.optimize_bridge(loops[0], bridge, 'RETRACE', [self.myptr3])
+ self.optimize_bridge(loops, bridge, loops[1], 'Loop1', [self.myptr2])
+ self.optimize_bridge(loops[0], bridge, 'RETRACE', [self.myptr2])
self.optimize_bridge(loops, loops[0], loops[0], 'Loop0', [self.nullptr])
self.optimize_bridge(loops, loops[1], loops[1], 'Loop1', [self.nullptr])
diff --git a/rpython/jit/metainterp/optimizeopt/virtualize.py b/rpython/jit/metainterp/optimizeopt/virtualize.py
--- a/rpython/jit/metainterp/optimizeopt/virtualize.py
+++ b/rpython/jit/metainterp/optimizeopt/virtualize.py
@@ -188,12 +188,6 @@
optimize_GETFIELD_GC_R = optimize_GETFIELD_GC_I
optimize_GETFIELD_GC_F = optimize_GETFIELD_GC_I
- # note: the following line does not mean that the two operations are
- # completely equivalent, because GETFIELD_GC_PURE is_always_pure().
- optimize_GETFIELD_GC_PURE_I = optimize_GETFIELD_GC_I
- optimize_GETFIELD_GC_PURE_R = optimize_GETFIELD_GC_I
- optimize_GETFIELD_GC_PURE_F = optimize_GETFIELD_GC_I
-
def optimize_SETFIELD_GC(self, op):
struct = op.getarg(0)
opinfo = self.getptrinfo(struct)
diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py
--- a/rpython/jit/metainterp/pyjitpl.py
+++ b/rpython/jit/metainterp/pyjitpl.py
@@ -653,46 +653,37 @@
@arguments("box", "descr")
def opimpl_getfield_gc_i(self, box, fielddescr):
+ if fielddescr.is_always_pure() and isinstance(box, ConstPtr):
+ # if 'box' is directly a ConstPtr, bypass the heapcache completely
+ resbox = executor.execute(self.metainterp.cpu, self.metainterp,
+ rop.GETFIELD_GC_I, fielddescr, box)
+ return ConstInt(resbox)
return self._opimpl_getfield_gc_any_pureornot(
rop.GETFIELD_GC_I, box, fielddescr, 'i')
+
+ @arguments("box", "descr")
+ def opimpl_getfield_gc_f(self, box, fielddescr):
+ if fielddescr.is_always_pure() and isinstance(box, ConstPtr):
+ # if 'box' is directly a ConstPtr, bypass the heapcache completely
+ resvalue = executor.execute(self.metainterp.cpu, self.metainterp,
+ rop.GETFIELD_GC_F, fielddescr, box)
+ return ConstFloat(resvalue)
+ return self._opimpl_getfield_gc_any_pureornot(
+ rop.GETFIELD_GC_F, box, fielddescr, 'f')
+
@arguments("box", "descr")
def opimpl_getfield_gc_r(self, box, fielddescr):
+ if fielddescr.is_always_pure() and isinstance(box, ConstPtr):
+ # if 'box' is directly a ConstPtr, bypass the heapcache completely
+ val = executor.execute(self.metainterp.cpu, self.metainterp,
+ rop.GETFIELD_GC_R, fielddescr, box)
+ return ConstPtr(val)
return self._opimpl_getfield_gc_any_pureornot(
rop.GETFIELD_GC_R, box, fielddescr, 'r')
- @arguments("box", "descr")
- def opimpl_getfield_gc_f(self, box, fielddescr):
- return self._opimpl_getfield_gc_any_pureornot(
- rop.GETFIELD_GC_F, box, fielddescr, 'f')
-
- @arguments("box", "descr")
- def opimpl_getfield_gc_i_pure(self, box, fielddescr):
- if isinstance(box, ConstPtr):
- # if 'box' is directly a ConstPtr, bypass the heapcache completely
- resbox = executor.execute(self.metainterp.cpu, self.metainterp,
- rop.GETFIELD_GC_PURE_I, fielddescr, box)
- return ConstInt(resbox)
- return self._opimpl_getfield_gc_any_pureornot(
- rop.GETFIELD_GC_PURE_I, box, fielddescr, 'i')
-
- @arguments("box", "descr")
- def opimpl_getfield_gc_f_pure(self, box, fielddescr):
- if isinstance(box, ConstPtr):
- # if 'box' is directly a ConstPtr, bypass the heapcache completely
- resvalue = executor.execute(self.metainterp.cpu, self.metainterp,
- rop.GETFIELD_GC_PURE_F, fielddescr, box)
- return ConstFloat(resvalue)
- return self._opimpl_getfield_gc_any_pureornot(
- rop.GETFIELD_GC_PURE_F, box, fielddescr, 'f')
-
- @arguments("box", "descr")
- def opimpl_getfield_gc_r_pure(self, box, fielddescr):
- if isinstance(box, ConstPtr):
- # if 'box' is directly a ConstPtr, bypass the heapcache completely
- val = executor.execute(self.metainterp.cpu, self.metainterp,
- rop.GETFIELD_GC_PURE_R, fielddescr, box)
- return ConstPtr(val)
- return self._opimpl_getfield_gc_any_pureornot(
- rop.GETFIELD_GC_PURE_R, box, fielddescr, 'r')
+
+ opimpl_getfield_gc_i_pure = opimpl_getfield_gc_i
+ opimpl_getfield_gc_r_pure = opimpl_getfield_gc_r
+ opimpl_getfield_gc_f_pure = opimpl_getfield_gc_f
@arguments("box", "box", "descr")
def opimpl_getinteriorfield_gc_i(self, array, index, descr):
@@ -733,7 +724,7 @@
@arguments("box", "descr", "orgpc")
def _opimpl_getfield_gc_greenfield_any(self, box, fielddescr, pc):
ginfo = self.metainterp.jitdriver_sd.greenfield_info
- opnum = OpHelpers.getfield_pure_for_descr(fielddescr)
+ opnum = OpHelpers.getfield_for_descr(fielddescr)
if (ginfo is not None and fielddescr in ginfo.green_field_descrs
and not self._nonstandard_virtualizable(pc, box, fielddescr)):
# fetch the result, but consider it as a Const box and don't
@@ -2104,17 +2095,7 @@
profiler = self.staticdata.profiler
profiler.count_ops(opnum)
resvalue = executor.execute(self.cpu, self, opnum, descr, *argboxes)
- #
- is_pure = rop._ALWAYS_PURE_FIRST <= opnum <= rop._ALWAYS_PURE_LAST
- if not is_pure:
- if (opnum == rop.GETFIELD_RAW_I or
- opnum == rop.GETFIELD_RAW_R or
- opnum == rop.GETFIELD_RAW_F or
- opnum == rop.GETARRAYITEM_RAW_I or
- opnum == rop.GETARRAYITEM_RAW_F):
- is_pure = descr.is_always_pure()
- #
- if is_pure:
+ if OpHelpers.is_pure_with_descr(opnum, descr):
return self._record_helper_pure(opnum, resvalue, descr, *argboxes)
if rop._OVF_FIRST <= opnum <= rop._OVF_LAST:
return self._record_helper_ovf(opnum, resvalue, descr, *argboxes)
diff --git a/rpython/jit/metainterp/resoperation.py b/rpython/jit/metainterp/resoperation.py
--- a/rpython/jit/metainterp/resoperation.py
+++ b/rpython/jit/metainterp/resoperation.py
@@ -231,7 +231,7 @@
class AbstractResOpOrInputArg(AbstractValue):
_attrs_ = ('_forwarded',)
- _forwarded = None # either another resop or OptInfo
+ _forwarded = None # either another resop or OptInfo
def get_forwarded(self):
return self._forwarded
@@ -412,6 +412,8 @@
return rop._JIT_DEBUG_FIRST <= self.getopnum() <= rop._JIT_DEBUG_LAST
def is_always_pure(self):
+ # Tells whether an operation is pure based solely on the opcode.
+ # Other operations (e.g. getfield ops) may be pure in some cases are well.
return rop._ALWAYS_PURE_FIRST <= self.getopnum() <= rop._ALWAYS_PURE_LAST
def has_no_side_effect(self):
@@ -434,9 +436,7 @@
return self.opnum in (rop.SAME_AS_I, rop.SAME_AS_F, rop.SAME_AS_R)
def is_getfield(self):
- return self.opnum in (rop.GETFIELD_GC_I, rop.GETFIELD_GC_F,
- rop.GETFIELD_GC_R, rop.GETFIELD_GC_PURE_I,
- rop.GETFIELD_GC_PURE_R, rop.GETFIELD_GC_PURE_F)
+ return self.opnum in (rop.GETFIELD_GC_I, rop.GETFIELD_GC_F, rop.GETFIELD_GC_R)
def is_getarrayitem(self):
return self.opnum in (rop.GETARRAYITEM_GC_I, rop.GETARRAYITEM_GC_F,
@@ -1602,14 +1602,6 @@
return rop.CALL_LOOPINVARIANT_N
@staticmethod
- def getfield_pure_for_descr(descr):
- if descr.is_pointer_field():
- return rop.GETFIELD_GC_PURE_R
- elif descr.is_float_field():
- return rop.GETFIELD_GC_PURE_F
- return rop.GETFIELD_GC_PURE_I
-
- @staticmethod
def getfield_for_descr(descr):
if descr.is_pointer_field():
return rop.GETFIELD_GC_R
@@ -1760,4 +1752,26 @@
opnum = rop.VEC_UNPACK_F
return VecOperationNew(opnum, args, datatype, bytesize, signed, count)
+ @staticmethod
+ def is_pure_getfield(opnum, descr):
+ if (opnum == rop.GETFIELD_GC_I or
+ opnum == rop.GETFIELD_GC_F or
+ opnum == rop.GETFIELD_GC_R):
+ return descr is not None and descr.is_always_pure()
+ return False
+ @staticmethod
+ def is_pure_with_descr(opnum, descr):
+ is_pure = rop._ALWAYS_PURE_FIRST <= opnum <= rop._ALWAYS_PURE_LAST
+ if not is_pure:
+ if (opnum == rop.GETFIELD_RAW_I or
+ opnum == rop.GETFIELD_RAW_R or
+ opnum == rop.GETFIELD_RAW_F or
+ opnum == rop.GETFIELD_GC_I or
+ opnum == rop.GETFIELD_GC_R or
+ opnum == rop.GETFIELD_GC_F or
+ opnum == rop.GETARRAYITEM_RAW_I or
+ opnum == rop.GETARRAYITEM_RAW_F):
+ is_pure = descr.is_always_pure()
+ return is_pure
+
diff --git a/rpython/jit/metainterp/test/test_ajit.py b/rpython/jit/metainterp/test/test_ajit.py
--- a/rpython/jit/metainterp/test/test_ajit.py
+++ b/rpython/jit/metainterp/test/test_ajit.py
@@ -320,7 +320,7 @@
assert res == 252
self.check_trace_count(1)
self.check_resops({'jump': 1, 'int_gt': 2, 'int_add': 2,
- 'getfield_gc_pure_i': 1, 'int_mul': 1,
+ 'getfield_gc_i': 1, 'int_mul': 1,
'guard_true': 2, 'int_sub': 2})
def test_loops_are_transient(self):
@@ -1405,7 +1405,7 @@
return tup[1]
res = self.interp_operations(f, [3, 5])
assert res == 5
- self.check_operations_history(setfield_gc=2, getfield_gc_pure_i=0)
+ self.check_operations_history(setfield_gc=2, getfield_gc_i=0)
def test_oosend_look_inside_only_one(self):
class A:
@@ -2522,7 +2522,7 @@
if counter > 10:
return 7
assert self.meta_interp(build, []) == 7
- self.check_resops(getfield_gc_pure_r=2)
+ self.check_resops(getfield_gc_r=2)
def test_args_becomming_equal(self):
myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'sa', 'a', 'b'])
diff --git a/rpython/jit/metainterp/test/test_immutable.py b/rpython/jit/metainterp/test/test_immutable.py
--- a/rpython/jit/metainterp/test/test_immutable.py
+++ b/rpython/jit/metainterp/test/test_immutable.py
@@ -19,7 +19,7 @@
return y.x + 5
res = self.interp_operations(f, [23])
assert res == 28
- self.check_operations_history(getfield_gc_i=0, getfield_gc_pure_i=1, int_add=1)
+ self.check_operations_history(getfield_gc_i=1, int_add=1)
def test_fields_subclass(self):
class X(object):
@@ -41,8 +41,7 @@
return z.x + z.y + 5
res = self.interp_operations(f, [23, 11])
assert res == 39
- self.check_operations_history(getfield_gc_i=0, getfield_gc_pure_i=2,
- int_add=2)
+ self.check_operations_history(getfield_gc_i=2, int_add=2)
def f(x, y):
# this time, the field 'x' only shows up on subclass 'Y'
@@ -50,8 +49,7 @@
return z.x + z.y + 5
res = self.interp_operations(f, [23, 11])
assert res == 39
- self.check_operations_history(getfield_gc_i=0, getfield_gc_pure_i=2,
- int_add=2)
+ self.check_operations_history(getfield_gc_i=2, int_add=2)
def test_array(self):
class X(object):
@@ -66,8 +64,7 @@
return a.y[index]
res = self.interp_operations(f, [2], listops=True)
assert res == 30
- self.check_operations_history(getfield_gc_r=0, getfield_gc_pure_r=1,
- getarrayitem_gc_i=0, getarrayitem_gc_pure_i=1)
+ self.check_operations_history(getfield_gc_r=1, getarrayitem_gc_i=0, getarrayitem_gc_pure_i=1)
def test_array_index_error(self):
class X(object):
@@ -89,8 +86,7 @@
return a.get(index)
res = self.interp_operations(f, [2], listops=True)
assert res == 30
- self.check_operations_history(getfield_gc_r=0, getfield_gc_pure_r=1,
- getarrayitem_gc_i=0, getarrayitem_gc_pure_i=1)
+ self.check_operations_history(getfield_gc_r=1, getarrayitem_gc_i=0, getarrayitem_gc_pure_i=1)
def test_array_in_immutable(self):
class X(object):
@@ -106,8 +102,7 @@
return y.lst[index] + y.y + 5
res = self.interp_operations(f, [23, 0], listops=True)
assert res == 23 + 24 + 5
- self.check_operations_history(getfield_gc_r=0, getfield_gc_pure_r=1,
- getfield_gc_pure_i=1,
+ self.check_operations_history(getfield_gc_r=1, getfield_gc_i=1,
getarrayitem_gc_i=0, getarrayitem_gc_pure_i=1,
int_add=3)
diff --git a/rpython/jit/metainterp/test/test_quasiimmut.py b/rpython/jit/metainterp/test/test_quasiimmut.py
--- a/rpython/jit/metainterp/test/test_quasiimmut.py
+++ b/rpython/jit/metainterp/test/test_quasiimmut.py
@@ -74,7 +74,7 @@
#
res = self.meta_interp(f, [100, 7])
assert res == 700
- self.check_resops(guard_not_invalidated=2, getfield_gc=0)
+ self.check_resops(guard_not_invalidated=2)
#
from rpython.jit.metainterp.warmspot import get_stats
loops = get_stats().loops
@@ -101,7 +101,7 @@
res = self.meta_interp(f, [100, 7], enable_opts="")
assert res == 700
# there should be no getfields, even though optimizations are turned off
- self.check_resops(guard_not_invalidated=1, getfield_gc=0)
+ self.check_resops(guard_not_invalidated=1)
def test_nonopt_1(self):
myjitdriver = JitDriver(greens=[], reds=['x', 'total', 'lst'])
@@ -124,8 +124,7 @@
assert f(100, 7) == 721
res = self.meta_interp(f, [100, 7])
assert res == 721
- self.check_resops(guard_not_invalidated=0, getfield_gc_r=1,
- getfield_gc_pure_i=2)
+ self.check_resops(guard_not_invalidated=0, getfield_gc_r=1, getfield_gc_i=2)
#
from rpython.jit.metainterp.warmspot import get_stats
loops = get_stats().loops
@@ -156,7 +155,7 @@
#
res = self.meta_interp(f, [100, 7])
assert res == 700
- self.check_resops(guard_not_invalidated=2, getfield_gc=0)
+ self.check_resops(guard_not_invalidated=2)
def test_change_during_tracing_1(self):
myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total'])
@@ -208,7 +207,7 @@
assert f(100, 7) == 700
res = self.meta_interp(f, [100, 7])
assert res == 700
- self.check_resops(guard_not_invalidated=0, getfield_gc=0)
+ self.check_resops(guard_not_invalidated=0)
def test_change_invalidate_reentering(self):
myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total'])
@@ -234,7 +233,7 @@
assert g(100, 7) == 700707
res = self.meta_interp(g, [100, 7])
assert res == 700707
- self.check_resops(guard_not_invalidated=4, getfield_gc=0)
+ self.check_resops(guard_not_invalidated=4)
def test_invalidate_while_running(self):
jitdriver = JitDriver(greens=['foo'], reds=['i', 'total'])
@@ -348,7 +347,7 @@
res = self.meta_interp(f, [100, 30])
assert res == 6019
self.check_resops(guard_not_invalidated=8, guard_not_forced=0,
- call_may_force=0, getfield_gc=0)
+ call_may_force=0)
def test_list_simple_1(self):
myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total'])
@@ -374,8 +373,7 @@
getarrayitem_gc_pure_r=0,
getarrayitem_gc_i=0,
getarrayitem_gc_r=0,
- getfield_gc_i=0, getfield_gc_pure_i=0,
- getfield_gc_r=0, getfield_gC_pure_r=0)
+ getfield_gc_i=0, getfield_gc_r=0)
#
from rpython.jit.metainterp.warmspot import get_stats
loops = get_stats().loops
@@ -405,9 +403,7 @@
assert res == 700
# operations must have been removed by the frontend
self.check_resops(getarrayitem_gc_pure_i=0, guard_not_invalidated=1,
- getarrayitem_gc_i=0,
- getfield_gc=0, getfield_gc_pure_i=0,
- getfield_gc_pure_r=0)
+ getarrayitem_gc_i=0, getfield_gc_i=0, getfield_gc_r=0)
def test_list_length_1(self):
myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total'])
diff --git a/rpython/jit/metainterp/test/test_tracingopts.py b/rpython/jit/metainterp/test/test_tracingopts.py
--- a/rpython/jit/metainterp/test/test_tracingopts.py
+++ b/rpython/jit/metainterp/test/test_tracingopts.py
@@ -436,10 +436,10 @@
return p.x[0] + p.x[1]
res = self.interp_operations(fn, [7])
assert res == 7 + 7 + 1
- self.check_operations_history(getfield_gc_r=0, getfield_gc_pure_r=0)
+ self.check_operations_history(getfield_gc_r=0)
res = self.interp_operations(fn, [-7])
assert res == -7 - 7 + 1
- self.check_operations_history(getfield_gc_r=0, getfield_gc_pure_r=0)
+ self.check_operations_history(getfield_gc_r=0)
def test_heap_caching_and_elidable_function(self):
class A:
@@ -517,12 +517,12 @@
return a1[0] + a2[0] + gn(a1, a2)
res = self.interp_operations(fn, [7])
assert res == 2 * 7 + 2 * 6
- self.check_operations_history(getfield_gc_pure_i=0,
- getfield_gc_pure_r=0)
+ self.check_operations_history(getfield_gc_i=0,
+ getfield_gc_r=0)
res = self.interp_operations(fn, [-7])
assert res == 2 * -7 + 2 * -8
- self.check_operations_history(getfield_gc_pure_i=0,
- getfield_gc_pure_r=0)
+ self.check_operations_history(getfield_gc_i=0,
+ getfield_gc_r=0)
def test_heap_caching_multiple_arrays(self):
class Gbl(object):
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