Author: Carl Friedrich Bolz <[email protected]>
Branch: guard-compatible
Changeset: r85375:7add21f0e70a
Date: 2016-06-24 16:51 +0200
http://bitbucket.org/pypy/pypy/changeset/7add21f0e70a/
Log: a test with virtualstate merging and quasi-immutables
diff --git a/rpython/jit/metainterp/compatible.py
b/rpython/jit/metainterp/compatible.py
--- a/rpython/jit/metainterp/compatible.py
+++ b/rpython/jit/metainterp/compatible.py
@@ -395,6 +395,7 @@
def emit_condition(self, op, short, optimizer, const=None):
from rpython.jit.metainterp.resoperation import rop, ResOperation
+ from rpython.jit.metainterp.quasiimmut import QuasiImmutDescr
# more mess
fielddescr = self.fielddescr
if fielddescr.is_pointer_field():
@@ -406,9 +407,15 @@
else:
getfield_op = ResOperation(
rop.GETFIELD_GC_I, [op], fielddescr)
+ if const is not None:
+ ref = const.getref_base()
+ qmutdescr = QuasiImmutDescr(
+ optimizer.cpu, ref, self.fielddescr, self.mutatefielddescr)
+ else:
+ qmutdescr = self.qmutdescr
short.extend([
ResOperation(
- rop.QUASIIMMUT_FIELD, [op], self.qmutdescr),
+ rop.QUASIIMMUT_FIELD, [op], qmutdescr),
ResOperation(
rop.GUARD_NOT_INVALIDATED, []),
getfield_op])
@@ -416,15 +423,19 @@
PureCallCondition.emit_condition(self, op, short, optimizer, const)
call_op = short[index]
# puh, not pretty
- args = call_op.getarglist()
+ args = call_op.getarglist()[:]
if const is not None:
+ args[1] = const
del optimizer.call_pure_results[args]
assert call_op.opnum in (
rop.CALL_PURE_I, rop.CALL_PURE_R,
rop.CALL_PURE_F, rop.CALL_PURE_N)
call_op.setarg(2, getfield_op)
if const is not None:
- optimizer.call_pure_results[call_op.getarglist()] = self.res
+ ref = const.getref_base()
+ args[2] = QuasiImmutDescr._get_fieldvalue(
+ self.fielddescr, ref, optimizer.cpu)
+ optimizer.call_pure_results[args] = self.res
def repr(self, argrepr="?"):
addr = self.args[0].getaddr()
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
@@ -629,7 +629,8 @@
self._last_guard_op)
else:
op = self.store_final_boxes_in_guard(guard_op, pendingfields)
- self._last_guard_op = op
+ if opnum == rop.GUARD_COMPATIBLE:
+ self._last_guard_op = op # XXX don't share the next one either
# for unrolling
for farg in op.getfailargs():
if farg:
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
@@ -482,7 +482,7 @@
"""
self.compare(guards, expected, [box])
- def make_ccond(self):
+ def make_ccond_info(self):
from rpython.jit.metainterp.compatible import CompatibilityCondition
optimizer = FakeOptimizer(self.cpu)
ccond = CompatibilityCondition(ConstPtr(self.quasiptr))
@@ -507,13 +507,12 @@
copied_op, cond = ccond.prepare_const_arg_call(
op, optimizer)
ccond.record_condition(cond, ConstInt(5), optimizer)
-
- return ccond
+ value = info.PtrInfo()
+ value._compatibility_conditions = ccond
+ return value
def test_info_make_guards_guard_compatible_with_conditions(self):
- value1 = info.PtrInfo()
- ccond = self.make_ccond()
- value1._compatibility_conditions = ccond
+ value1 = self.make_ccond_info()
box = InputArgRef()
guards = []
@@ -532,12 +531,8 @@
self.compare(guards, expected, [box])
def test_virtualstate_guard_compatible(self):
- value1 = info.PtrInfo()
- ccond1 = self.make_ccond()
- value1._compatibility_conditions = ccond1
- value2 = info.PtrInfo()
- ccond2 = self.make_ccond()
- value2._compatibility_conditions = ccond2
+ value1 = self.make_ccond_info()
+ value2 = self.make_ccond_info()
state1 = not_virtual(self.cpu, 'r', value1)
state2 = not_virtual(self.cpu, 'r', value2)
@@ -553,6 +548,26 @@
ccond1.conditions = []
self.check_no_guards(state1, state2)
+ def test_virtualstate_guard_compatible_make_guards(self):
+ value1 = self.make_ccond_info()
+ value2 = self.make_ccond_info()
+
+ state1 = not_virtual(self.cpu, 'r', value1)
+ state2 = not_virtual(self.cpu, 'r', value2)
+
+
+ cond = ccond2.conditions[:]
+ ccond2.conditions = [cond[0]]
+ box = InputArgRef(self.nodeaddr)
+ self.guards(state1, state2)
+
+ ccond2.conditions = [cond[1]]
+ self.check_no_guards(state1, state2)
+
+ ccond2.conditions = []
+ self.check_no_guards(state1, state2)
+ self.check_no_guards(state1, state2)
+
def test_equal_inputargs(self):
classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
diff --git a/rpython/jit/metainterp/test/test_compatible.py
b/rpython/jit/metainterp/test/test_compatible.py
--- a/rpython/jit/metainterp/test/test_compatible.py
+++ b/rpython/jit/metainterp/test/test_compatible.py
@@ -402,3 +402,82 @@
# trace, one bridge, a finish bridge
self.check_trace_count(3)
+
+ def test_quasi_immutable_merge(self):
+ from rpython.rlib.objectmodel import we_are_translated
+ class C(object):
+ _immutable_fields_ = ['version?']
+
+ class Version(object):
+ def __init__(self, cls):
+ self.cls = cls
+ p1 = C()
+ p1.version = Version(p1)
+ p1.x = 1
+ p2 = C()
+ p2.version = Version(p2)
+ p2.x = 1
+ p3 = C()
+ p3.version = Version(p3)
+ p3.x = 3
+
+ driver = jit.JitDriver(greens = [], reds = ['n', 'x'])
+
+ class Counter(object):
+ pass
+
+ c = Counter()
+ c.count = 0
+ @jit.elidable_compatible()
+ def g(cls, v):
+ if we_are_translated():
+ c.count += 1
+ return cls.x
+
+ def f(n, x):
+ res = 0
+ while n > 0:
+ driver.can_enter_jit(n=n, x=x)
+ driver.jit_merge_point(n=n, x=x)
+ x = jit.hint(x, promote_compatible=True)
+ v = x.version
+ res = g(x, x.version)
+ n -= res
+ if n % 11 == 5:
+ n -= 1
+ return res
+
+ def main(x):
+ res = f(100, p1)
+ assert res == 1
+ res = f(100, p2)
+ assert res == 1
+ res = f(100, p3)
+ assert res == 3
+ # invalidate p1 or p2
+ if x:
+ p1.x = 2
+ p1.version = Version(p1)
+ res = f(100, p1)
+ assert res == 2
+ p1.x = 1
+ p1.version = Version(p1)
+ else:
+ p2.x = 2
+ p2.version = Version(p2)
+ res = f(100, p2)
+ assert res == 2
+ p2.x = 1
+ p2.version = Version(p2)
+ return c.count
+ main(True)
+ main(False)
+
+ x = self.meta_interp(main, [True])
+ assert x < 30
+
+ x = self.meta_interp(main, [False])
+ assert x < 30
+ self.check_trace_count(7)
+
+
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit