[pypy-svn] pypy out-of-line-guards-2: Detect cases were the value stored in the quasi-immutable field
arigo
commits-noreply at bitbucket.org
Sat Apr 2 20:17:36 CEST 2011
Author: Armin Rigo <arigo at tunes.org>
Branch: out-of-line-guards-2
Changeset: r43116:941dde3b5b4e
Date: 2011-04-02 18:46 +0200
http://bitbucket.org/pypy/pypy/changeset/941dde3b5b4e/
Log: Detect cases were the value stored in the quasi-immutable field
changed already between tracing and optimization.
diff --git a/pypy/jit/metainterp/quasiimmut.py b/pypy/jit/metainterp/quasiimmut.py
--- a/pypy/jit/metainterp/quasiimmut.py
+++ b/pypy/jit/metainterp/quasiimmut.py
@@ -44,11 +44,22 @@
class SlowMutateDescr(AbstractDescr):
- def __init__(self, cpu, gcref,
- constantfieldbox, fielddescr, mutatefielddescr):
+ def __init__(self, cpu, structbox, fielddescr, mutatefielddescr):
self.cpu = cpu
- self.gcref = gcref
- self.constantfieldbox = constantfieldbox
+ self.structbox = structbox
self.fielddescr = fielddescr
self.mutatefielddescr = mutatefielddescr
+ gcref = structbox.getref_base()
self.mutate = get_current_mutate_instance(cpu, gcref, mutatefielddescr)
+ self.constantfieldbox = self.get_current_constant_fieldvalue()
+
+ def get_current_constant_fieldvalue(self):
+ from pypy.jit.metainterp import executor
+ from pypy.jit.metainterp.resoperation import rop
+ fieldbox = executor.execute(self.cpu, None, rop.GETFIELD_GC,
+ self.fielddescr, self.structbox)
+ return fieldbox.constbox()
+
+ def is_still_valid(self):
+ currentbox = self.get_current_constant_fieldvalue()
+ return self.constantfieldbox.same_constant(currentbox)
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
@@ -385,15 +385,22 @@
# a constant too, and we rely on the rest of the optimizations to
# constant-fold the following getfield_gc.
structvalue = self.getvalue(op.getarg(0))
- if structvalue.is_constant():
- from pypy.jit.metainterp.quasiimmut import SlowMutateDescr
- # XXX check that the value is still correct!
- # XXX record as an out-of-line guard!
- smdescr = op.getdescr()
- assert isinstance(smdescr, SlowMutateDescr)
- fieldvalue = self.getvalue(smdescr.constantfieldbox)
- cf = self.field_cache(smdescr.fielddescr)
- cf.remember_field_value(structvalue, fieldvalue)
+ if not structvalue.is_constant():
+ return # not a constant at all; ignore QUASIIMMUT_FIELD
+ #
+ from pypy.jit.metainterp.quasiimmut import SlowMutateDescr
+ smdescr = op.getdescr()
+ assert isinstance(smdescr, SlowMutateDescr)
+ # check that the value is still correct; it could have changed
+ # already between the tracing and now. In this case, we are
+ # simply ignoring the QUASIIMMUT_FIELD hint and compiling it
+ # as a regular getfield.
+ if not smdescr.is_still_valid():
+ return
+ # XXX record as an out-of-line guard!
+ fieldvalue = self.getvalue(smdescr.constantfieldbox)
+ cf = self.field_cache(smdescr.fielddescr)
+ cf.remember_field_value(structvalue, fieldvalue)
def propagate_forward(self, op):
opnum = op.getopnum()
diff --git a/pypy/jit/metainterp/test/test_quasiimmut.py b/pypy/jit/metainterp/test/test_quasiimmut.py
--- a/pypy/jit/metainterp/test/test_quasiimmut.py
+++ b/pypy/jit/metainterp/test/test_quasiimmut.py
@@ -4,7 +4,7 @@
from pypy.jit.metainterp.quasiimmut import SlowMutate
from pypy.jit.metainterp.quasiimmut import get_current_mutate_instance
from pypy.jit.metainterp.test.test_basic import LLJitMixin
-from pypy.rlib.jit import JitDriver
+from pypy.rlib.jit import JitDriver, dont_look_inside
def test_get_current_mutate_instance():
@@ -64,6 +64,31 @@
assert res == 700
self.check_loops(getfield_gc=0, everywhere=True)
+ def test_change_during_tracing(self):
+ myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total'])
+ class Foo:
+ _immutable_fields_ = ['a?']
+ def __init__(self, a):
+ self.a = a
+ @dont_look_inside
+ def residual_call(foo):
+ foo.a += 1
+ def f(a, x):
+ foo = Foo(a)
+ total = 0
+ while x > 0:
+ myjitdriver.jit_merge_point(foo=foo, x=x, total=total)
+ # read a quasi-immutable field out of a Constant
+ total += foo.a
+ residual_call(foo)
+ x -= 1
+ return total
+ #
+ assert f(100, 7) == 721
+ res = self.meta_interp(f, [100, 7])
+ assert res == 721
+ self.check_loops(getfield_gc=1)
+
class TestLLtypeGreenFieldsTests(QuasiImmutTests, LLJitMixin):
pass
diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -560,11 +560,7 @@
mutatefielddescr):
from pypy.jit.metainterp.quasiimmut import SlowMutateDescr
cpu = self.metainterp.cpu
- fieldbox = executor.execute(cpu, self.metainterp, rop.GETFIELD_GC,
- fielddescr, box)
- fieldbox = fieldbox.constbox()
- descr = SlowMutateDescr(cpu, box.getref_base(), fieldbox,
- fielddescr, mutatefielddescr)
+ descr = SlowMutateDescr(cpu, box, fielddescr, mutatefielddescr)
self.metainterp.history.record(rop.QUASIIMMUT_FIELD, [box],
None, descr=descr)
More information about the Pypy-commit
mailing list