Author: Armin Rigo <[email protected]>
Branch: heapcache-refactor
Changeset: r83099:d8bbee232b14
Date: 2016-03-17 11:36 +0100
http://bitbucket.org/pypy/pypy/changeset/d8bbee232b14/
Log: test_known_class_box. Implement the double versioning check.
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
@@ -6,6 +6,7 @@
# RefFrontendOp._heapc_flags:
HF_LIKELY_VIRTUAL = 0x01
+HF_KNOWN_CLASS = 0x02
@always_inline
def add_flags(ref_frontend_op, flags):
@@ -22,7 +23,7 @@
@always_inline
def test_flags(ref_frontend_op, flags):
f = r_uint(ref_frontend_op._heapc_flags)
- return bool(f & flags)
+ return bool(f & r_uint(flags))
class HeapCacheValue(object):
@@ -31,7 +32,6 @@
self.reset_keep_likely_virtual()
def reset_keep_likely_virtual(self):
- self.known_class = False
self.known_nullity = False
# did we see the allocation during tracing?
self.seen_allocation = False
@@ -106,10 +106,27 @@
class HeapCache(object):
def __init__(self):
+ # Works with flags stored on RefFrontendOp._heapc_flags.
+ # There are two ways to do a global resetting of these flags:
+ # reset() and reset_keep_likely_virtual(). The basic idea is
+ # to use a version number in each RefFrontendOp, and in order
+ # to reset the flags globally, we increment the global version
+ # number in this class. Then when we read '_heapc_flags' we
+ # also check if the associated '_heapc_version' is up-to-date
+ # or not. More precisely, we have two global version numbers
+ # here: 'head_version' and 'likely_virtual_version'. Normally
+ # we use 'head_version'. For is_likely_virtual() though, we
+ # use the other, older version number.
+ self.head_version = r_uint(0)
+ self.likely_virtual_version = r_uint(0)
self.reset()
- self.version = r_uint32(1)
def reset(self):
+ # Global reset of all flags. Update both version numbers so
+ # that any access to '_heapc_flags' will be marked as outdated.
+ self.head_version += 1
+ self.likely_virtual_version = self.head_version
+ #
# maps boxes to HeapCacheValue
self.values = {}
# heap cache
@@ -120,11 +137,33 @@
self.heap_array_cache = {}
def reset_keep_likely_virtuals(self):
+ # Update only 'head_version', but 'likely_virtual_version' remains
+ # at its older value.
+ self.head_version += 1
+ #
for value in self.values.itervalues():
value.reset_keep_likely_virtual()
self.heap_cache = {}
self.heap_array_cache = {}
+ @always_inline
+ def test_head_version(self, ref_frontend_op):
+ return r_uint(ref_frontend_op._heapc_version) == self.head_version
+
+ @always_inline
+ def test_likely_virtual_version(self, ref_frontend_op):
+ return (r_uint(ref_frontend_op._heapc_version) ==
+ self.likely_virtual_version)
+
+ def update_version(self, ref_frontend_op):
+ if not self.test_head_version(ref_frontend_op):
+ f = 0
+ if (self.test_likely_virtual_version(ref_frontend_op) and
+ test_flags(ref_frontend_op, HF_LIKELY_VIRTUAL)):
+ f |= HF_LIKELY_VIRTUAL
+ ref_frontend_op._heapc_flags = r_uint32(f)
+ ref_frontend_op._heapc_version = r_uint32(self.head_version)
+
def getvalue(self, box, create=True):
value = self.values.get(box, None)
if not value and create:
@@ -291,13 +330,14 @@
self.reset_keep_likely_virtuals()
def is_class_known(self, box):
- value = self.getvalue(box, create=False)
- if value:
- return value.known_class
- return False
+ return (isinstance(box, RefFrontendOp) and
+ self.test_head_version(box) and
+ test_flags(box, HF_KNOWN_CLASS))
def class_now_known(self, box):
- self.getvalue(box).known_class = True
+ assert isinstance(box, RefFrontendOp)
+ self.update_version(box)
+ add_flags(box, HF_KNOWN_CLASS)
def is_nullity_known(self, box):
value = self.getvalue(box, create=False)
@@ -325,10 +365,12 @@
def is_likely_virtual(self, box):
return (isinstance(box, RefFrontendOp) and
- test_flags(box, HF_LIKELY_VIRTUAL))
+ self.test_likely_virtual_version(box) and
+ test_flags(box, HF_LIKELY_VIRTUAL))
def new(self, box):
assert isinstance(box, RefFrontendOp)
+ self.update_version(box)
add_flags(box, HF_LIKELY_VIRTUAL)
value = self.getvalue(box)
value.is_unescaped = True
diff --git a/rpython/jit/metainterp/test/test_heapcache.py
b/rpython/jit/metainterp/test/test_heapcache.py
--- a/rpython/jit/metainterp/test/test_heapcache.py
+++ b/rpython/jit/metainterp/test/test_heapcache.py
@@ -60,15 +60,17 @@
class TestHeapCache(object):
def test_known_class_box(self):
h = HeapCache()
- assert not h.is_class_known(1)
- assert not h.is_class_known(2)
- h.class_now_known(1)
- assert h.is_class_known(1)
- assert not h.is_class_known(2)
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
+ assert not h.is_class_known(box1)
+ assert not h.is_class_known(box2)
+ h.class_now_known(box1)
+ assert h.is_class_known(box1)
+ assert not h.is_class_known(box2)
h.reset()
- assert not h.is_class_known(1)
- assert not h.is_class_known(2)
+ assert not h.is_class_known(box1)
+ assert not h.is_class_known(box2)
def test_known_nullity(self):
h = HeapCache()
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit