Author: Carl Friedrich Bolz <[email protected]>
Branch: guard-compatible
Changeset: r86269:2963715f455b
Date: 2016-08-18 11:44 +0200
http://bitbucket.org/pypy/pypy/changeset/2963715f455b/
Log: guard_compatible was broken by b116f09c4e9d: by removing the quasi-
immut operations, the guard_compatible optimizer doesn't see them
early enough. Fix it by making clearing this cache when emmitting a
guard_compatible
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
@@ -163,6 +163,10 @@
# maps descrs to {index: CacheEntry} dicts
self.heap_array_cache = {}
+ # maps descrs to CacheEntry, contains only descrs that are
+ # quasi-immutable
+ self.quasi_immut_descrs = {}
+
def reset_keep_likely_virtuals(self):
# Update only 'head_version', but 'likely_virtual_version' remains
# at its older value.
@@ -511,7 +515,17 @@
cache = self.heap_cache.get(fielddescr, None)
if cache is None:
cache = self.heap_cache[fielddescr] = CacheEntry(self)
+ self.quasi_immut_descrs[fielddescr] = cache
if cache.quasiimmut_seen is not None:
cache.quasiimmut_seen[box] = None
else:
cache.quasiimmut_seen = {box: None}
+
+ def invalidate_quasi_immut(self, box):
+ # slow, but should be rare
+ for fielddescr, cache in self.quasi_immut_descrs.iteritems():
+ if cache.quasiimmut_seen:
+ try:
+ del cache.quasiimmut_seen[box]
+ except KeyError:
+ pass
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
@@ -1209,7 +1209,11 @@
self.metainterp.generate_guard(rop.GUARD_COMPATIBLE, box,
[promoted_box],
resumepc=orgpc)
self.metainterp.heapcache.have_guard_compatible_now(box)
- # importantly, there is no replace_box here!
+ # it's necessary to not cache quasi-immutable reads on this box
+ # the guard-compatible machinery needs to see the quasi-immutable
+ # read
+ self.metainterp.heapcache.invalidate_quasi_immut(box)
+ # importantly, there is no replace_box here (unlike guard_value)
@arguments("box", "orgpc")
def opimpl_guard_class(self, box, orgpc):
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
@@ -622,6 +622,7 @@
self.num = num
self.version = Version()
self.dct = {}
+ self.classdct = {}
def instantiate(self):
return Obj(self)
@@ -630,6 +631,10 @@
def lookup_version(self, version, name):
return self.dct.get(name, -1)
+
@jit.elidable_compatible(quasi_immut_field_name_for_second_arg='version')
+ def lookup_class(self, version, name):
+ return self.classdct.get(name, -1)
+
class Version(object):
pass
@@ -641,18 +646,30 @@
map = self.map
assert isinstance(map, Map)
map = jit.hint(map, promote_compatible=True)
- return map.lookup_version(name)
+ result = map.lookup_version(name)
+ if result == -1:
+ return map.lookup_class(name)
+ return result
m1 = Map(1)
m1.dct['a'] = 1
m1.dct['b'] = 2
+ m1.classdct['d'] = 4
+ m1.classdct['e'] = 5
m2 = Map(2)
m2.dct['a'] = 1
m2.dct['b'] = 2
m2.dct['c'] = 5
+ m2.classdct['d'] = 4
+ m2.classdct['e'] = 5
+ m2.classdct['f'] = 5
+
+ m3 = Map(3)
+ m3.version = None
p1 = m1.instantiate()
p2 = m2.instantiate()
+ p3 = m3.instantiate()
driver = jit.JitDriver(greens = [], reds = ['n', 'res', 'p'])
@@ -660,15 +677,21 @@
res = p.map.num
while n > 0:
driver.jit_merge_point(n=n, p=p, res=res)
- res += p.lookup('a')
- res += p.lookup('c')
- res += p.lookup('b')
+ version = p.map.version
+ if version is not None:
+ res += p.lookup('a')
+ res += p.lookup('c')
+ res += p.lookup('b')
+ res += p.lookup('d')
+ res += p.lookup('e')
+ res += p.lookup('f')
n -= 1
return res
def main(x):
res = f(100, p1)
res = f(100, p2)
+ res = f(100, p3)
main(True)
main(False)
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
@@ -538,6 +538,34 @@
self.check_operations_history(quasiimmut_field=1)
+ def test_heap_caching_quasi_immutable_clear_after_guard_compatible(self):
+ class A:
+ _immutable_fields_ = ['x?']
+ a1 = A()
+ a1.x = 5
+ a2 = A()
+ a2.x = 7
+
+ @jit.elidable
+ def get(n):
+ if n > 0:
+ return a1
+ return a2
+
+ def g(a):
+ return a.x
+
+ def fn(n):
+ a = get(n)
+ res = g(a)
+ jit.hint(a, promote_compatible=True)
+ return res + a.x
+
+ res = self.interp_operations(fn, [7])
+ assert res == 10
+ self.check_operations_history(quasiimmut_field=2)
+
+
def test_heap_caching_multiple_tuples(self):
class Gbl(object):
pass
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit