Author: Armin Rigo <[email protected]>
Branch: heapcache-refactor
Changeset: r83102:13c3037d3ce3
Date: 2016-03-17 12:07 +0100
http://bitbucket.org/pypy/pypy/changeset/13c3037d3ce3/
Log: in-progress
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
@@ -5,9 +5,11 @@
# RefFrontendOp._heapc_flags:
-HF_LIKELY_VIRTUAL = 0x01
-HF_KNOWN_CLASS = 0x02
-HF_KNOWN_NULLITY = 0x04
+HF_LIKELY_VIRTUAL = 0x01
+HF_KNOWN_CLASS = 0x02
+HF_KNOWN_NULLITY = 0x04
+HF_SEEN_ALLOCATION = 0x08 # did we see the allocation during tracing?
+HF_NONSTD_VABLE = 0x10
@always_inline
def add_flags(ref_frontend_op, flags):
@@ -33,10 +35,7 @@
self.reset_keep_likely_virtual()
def reset_keep_likely_virtual(self):
- # did we see the allocation during tracing?
- self.seen_allocation = False
self.is_unescaped = False
- self.nonstandard_virtualizable = False
self.length = None
self.dependencies = None
@@ -45,12 +44,13 @@
class CacheEntry(object):
- def __init__(self):
+ def __init__(self, heapcache):
# both are {from_value: to_value} dicts
# the first is for boxes where we did not see the allocation, the
# second for anything else. the reason that distinction makes sense is
# because if we saw the allocation, we know it cannot alias with
# anything else where we saw the allocation.
+ self.heapcache = heapcache
self.cache_anything = {}
self.cache_seen_allocation = {}
@@ -59,21 +59,26 @@
self.cache_seen_allocation.clear()
self.cache_anything.clear()
- def _getdict(self, value):
- if value.seen_allocation:
+ def _seen_alloc(self, ref_box):
+ assert isinstance(ref_box, RefFrontendOp)
+ return self.heapcache._check_flag(ref_box, HF_SEEN_ALLOCATION)
+
+ def _getdict(self, seen_alloc):
+ if seen_alloc:
return self.cache_seen_allocation
else:
return self.cache_anything
- def do_write_with_aliasing(self, value, fieldvalue):
- self._clear_cache_on_write(value.seen_allocation)
- self._getdict(value)[value] = fieldvalue
+ def do_write_with_aliasing(self, ref_box, fieldbox):
+ seen_alloc = self._seen_alloc(ref_box)
+ self._clear_cache_on_write(seen_alloc)
+ self._getdict(seen_alloc)[ref_box] = fieldbox
- def read(self, value):
- return self._getdict(value).get(value, None)
+ def read(self, ref_box):
+ return self._getdict(self._seen_alloc(ref_box)).get(ref_box, None)
- def read_now_known(self, value, fieldvalue):
- self._getdict(value)[value] = fieldvalue
+ def read_now_known(self, ref_box, fieldbox):
+ self._getdict(self._seen_alloc(ref_box))[ref_box] = fieldbox
def invalidate_unescaped(self):
self._invalidate_unescaped(self.cache_anything)
@@ -86,22 +91,16 @@
class FieldUpdater(object):
- def __init__(self, heapcache, value, cache, fieldvalue):
- self.heapcache = heapcache
- self.value = value
+ def __init__(self, ref_box, cache, fieldbox):
+ self.ref_box = ref_box
self.cache = cache
- if fieldvalue is not None:
- self.currfieldbox = fieldvalue.box
- else:
- self.currfieldbox = None
+ self.currfieldbox = fieldbox # <= read directly from pyjitpl.py
def getfield_now_known(self, fieldbox):
- fieldvalue = self.heapcache.getvalue(fieldbox)
- self.cache.read_now_known(self.value, fieldvalue)
+ self.cache.read_now_known(self.ref_box, fieldbox)
def setfield(self, fieldbox):
- fieldvalue = self.heapcache.getvalue(fieldbox)
- self.cache.do_write_with_aliasing(self.value, fieldvalue)
+ self.cache.do_write_with_aliasing(self.ref_box, fieldbox)
class HeapCache(object):
@@ -329,34 +328,33 @@
return
self.reset_keep_likely_virtuals()
- def is_class_known(self, box):
+ def _check_flag(self, box, flag):
return (isinstance(box, RefFrontendOp) and
self.test_head_version(box) and
- test_flags(box, HF_KNOWN_CLASS))
+ test_flags(box, flag))
+
+ def _set_flag(self, box, flag):
+ assert isinstance(box, RefFrontendOp)
+ self.update_version(box)
+ add_flags(box, flag)
+
+ def is_class_known(self, box):
+ return self._check_flag(box, HF_KNOWN_CLASS)
def class_now_known(self, box):
- assert isinstance(box, RefFrontendOp)
- self.update_version(box)
- add_flags(box, HF_KNOWN_CLASS)
+ self._set_flag(box, HF_KNOWN_CLASS)
def is_nullity_known(self, box):
- return (isinstance(box, RefFrontendOp) and
- self.test_head_version(box) and
- test_flags(box, HF_KNOWN_NULLITY))
+ return self._check_flag(box, HF_KNOWN_NULLITY)
def nullity_now_known(self, box):
- assert isinstance(box, RefFrontendOp)
- self.update_version(box)
- add_flags(box, HF_KNOWN_NULLITY)
+ self._set_flag(box, HF_KNOWN_NULLITY)
def is_nonstandard_virtualizable(self, box):
- value = self.getvalue(box, create=False)
- if value:
- return value.nonstandard_virtualizable
- return False
+ return self._check_flag(box, HF_NONSTD_VABLE)
def nonstandard_virtualizables_now_known(self, box):
- self.getvalue(box).nonstandard_virtualizable = True
+ self._set_flag(box, HF_NONSTD_VABLE)
def is_unescaped(self, box):
value = self.getvalue(box, create=False)
@@ -372,34 +370,29 @@
def new(self, box):
assert isinstance(box, RefFrontendOp)
self.update_version(box)
- add_flags(box, HF_LIKELY_VIRTUAL)
+ add_flags(box, HF_LIKELY_VIRTUAL | HF_SEEN_ALLOCATION)
value = self.getvalue(box)
value.is_unescaped = True
- value.seen_allocation = True
def new_array(self, box, lengthbox):
self.new(box)
self.arraylen_now_known(box, lengthbox)
def getfield(self, box, descr):
- value = self.getvalue(box, create=False)
- if value:
- cache = self.heap_cache.get(descr, None)
- if cache:
- tovalue = cache.read(value)
- if tovalue:
- return tovalue.box
+ cache = self.heap_cache.get(descr, None)
+ if cache:
+ return cache.read(box)
return None
def get_field_updater(self, box, descr):
- value = self.getvalue(box)
+ assert isinstance(box, RefFrontendOp)
cache = self.heap_cache.get(descr, None)
if cache is None:
- cache = self.heap_cache[descr] = CacheEntry()
- fieldvalue = None
+ cache = self.heap_cache[descr] = CacheEntry(self)
+ fieldbox = None
else:
- fieldvalue = cache.read(value)
- return FieldUpdater(self, value, cache, fieldvalue)
+ fieldbox = cache.read(box)
+ return FieldUpdater(box, cache, fieldbox)
def getfield_now_known(self, box, descr, fieldbox):
upd = self.get_field_updater(box, descr)
@@ -432,7 +425,7 @@
cache = self.heap_array_cache.setdefault(descr, {})
indexcache = cache.get(index, None)
if indexcache is None:
- cache[index] = indexcache = CacheEntry()
+ cache[index] = indexcache = CacheEntry(self)
return indexcache
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
@@ -651,6 +651,9 @@
def get_position(self):
return self.position
+ def __repr__(self):
+ return '%s(%s)' % (self.__class__.__name__, self.position)
+
class IntFrontendOp(IntOp, FrontendOp):
_attrs_ = ('position', '_resint')
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
@@ -3,11 +3,6 @@
from rpython.jit.metainterp.history import ConstInt, BasicFailDescr
from rpython.jit.metainterp.history import RefFrontendOp
-box1 = "box1"
-box2 = "box2"
-box3 = "box3"
-box4 = "box4"
-box5 = "box5"
lengthbox1 = object()
lengthbox2 = object()
lengthbox3 = object()
@@ -89,18 +84,23 @@
def test_nonstandard_virtualizable(self):
h = HeapCache()
- assert not h.is_nonstandard_virtualizable(1)
- assert not h.is_nonstandard_virtualizable(2)
- h.nonstandard_virtualizables_now_known(1)
- assert h.is_nonstandard_virtualizable(1)
- assert not h.is_nonstandard_virtualizable(2)
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
+ assert not h.is_nonstandard_virtualizable(box1)
+ assert not h.is_nonstandard_virtualizable(box2)
+ h.nonstandard_virtualizables_now_known(box1)
+ assert h.is_nonstandard_virtualizable(box1)
+ assert not h.is_nonstandard_virtualizable(box2)
h.reset()
- assert not h.is_nonstandard_virtualizable(1)
- assert not h.is_nonstandard_virtualizable(2)
+ assert not h.is_nonstandard_virtualizable(box1)
+ assert not h.is_nonstandard_virtualizable(box2)
def test_heapcache_fields(self):
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
+ box3 = RefFrontendOp(3)
assert h.getfield(box1, descr1) is None
assert h.getfield(box1, descr2) is None
h.setfield(box1, box2, descr1)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit