Author: Armin Rigo <[email protected]>
Branch: jit-leaner-frontend
Changeset: r83164:5ad06b41df68
Date: 2016-03-19 09:57 +0100
http://bitbucket.org/pypy/pypy/changeset/5ad06b41df68/
Log: hg merge heapcache-refactor
diff --git a/rpython/jit/backend/llgraph/runner.py
b/rpython/jit/backend/llgraph/runner.py
--- a/rpython/jit/backend/llgraph/runner.py
+++ b/rpython/jit/backend/llgraph/runner.py
@@ -455,7 +455,7 @@
if box is not frame.current_op:
value = frame.env[box]
else:
- value = box.getvalue() # 0 or 0.0 or NULL
+ value = 0 # box.getvalue() # 0 or 0.0 or NULL
else:
value = None
values.append(value)
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
@@ -1,33 +1,54 @@
-from rpython.jit.metainterp.history import ConstInt
+from rpython.jit.metainterp.history import Const, ConstInt
+from rpython.jit.metainterp.history import FrontendOp, RefFrontendOp
from rpython.jit.metainterp.resoperation import rop, OpHelpers
+from rpython.jit.metainterp.executor import constant_from_op
+from rpython.rlib.rarithmetic import r_uint32, r_uint
+from rpython.rlib.objectmodel import always_inline
-class HeapCacheValue(object):
- def __init__(self, box):
- self.box = box
- self.likely_virtual = False
- 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
- self.is_unescaped = False
- self.nonstandard_virtualizable = False
- self.length = None
- self.dependencies = None
+# RefFrontendOp._heapc_flags:
+HF_LIKELY_VIRTUAL = 0x01
+HF_KNOWN_CLASS = 0x02
+HF_KNOWN_NULLITY = 0x04
+HF_SEEN_ALLOCATION = 0x08 # did we see the allocation during tracing?
+HF_IS_UNESCAPED = 0x10
+HF_NONSTD_VABLE = 0x20
- def __repr__(self):
- return 'HeapCacheValue(%s)' % (self.box, )
+_HF_VERSION_INC = 0x40 # must be last
+_HF_VERSION_MAX = r_uint(2 ** 32 - _HF_VERSION_INC)
+
+@always_inline
+def add_flags(ref_frontend_op, flags):
+ f = ref_frontend_op._get_heapc_flags()
+ f |= r_uint(flags)
+ ref_frontend_op._set_heapc_flags(f)
+
+@always_inline
+def remove_flags(ref_frontend_op, flags):
+ f = ref_frontend_op._get_heapc_flags()
+ f &= r_uint(~flags)
+ ref_frontend_op._set_heapc_flags(f)
+
+@always_inline
+def test_flags(ref_frontend_op, flags):
+ f = ref_frontend_op._get_heapc_flags()
+ return bool(f & r_uint(flags))
+
+def maybe_replace_with_const(box):
+ if not isinstance(box, Const) and box.is_replaced_with_const():
+ return constant_from_op(box)
+ else:
+ return box
class CacheEntry(object):
- def __init__(self):
- # both are {from_value: to_value} dicts
+ def __init__(self, heapcache):
+ # both are {from_ref_box: to_field_box} 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 = {}
@@ -36,112 +57,137 @@
self.cache_seen_allocation.clear()
self.cache_anything.clear()
- def _getdict(self, value):
- if value.seen_allocation:
+ def _seen_alloc(self, ref_box):
+ if not isinstance(ref_box, RefFrontendOp):
+ return False
+ 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):
+ dict = self._getdict(self._seen_alloc(ref_box))
+ try:
+ res_box = dict[ref_box]
+ except KeyError:
+ return None
+ return maybe_replace_with_const(res_box)
- 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)
self._invalidate_unescaped(self.cache_seen_allocation)
def _invalidate_unescaped(self, d):
- for value in d.keys():
- if not value.is_unescaped:
- del d[value]
+ for ref_box in d.keys():
+ if not self.heapcache.is_unescaped(ref_box):
+ del d[ref_box]
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 DummyFieldUpdater(FieldUpdater):
+ def __init__(self):
+ self.currfieldbox = None
+
+ def getfield_now_known(self, fieldbox):
+ pass
+
+ def setfield(self, fieldbox):
+ pass
+
+dummy_field_updater = DummyFieldUpdater()
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 version number 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()
def reset(self):
- # maps boxes to values
- self.values = {}
- # store the boxes that contain newly allocated objects, this maps the
- # boxes to a bool, the bool indicates whether or not the object has
- # escaped the trace or not (True means the box never escaped, False
- # means it did escape), its presences in the mapping shows that it was
- # allocated inside the trace
- #if trace_branch:
- #self.new_boxes = {}
- # pass
- #else:
- #for box in self.new_boxes:
- # self.new_boxes[box] = False
- # pass
- #if reset_virtuals:
- # self.likely_virtuals = {} # only for jit.isvirtual()
- # Tracks which boxes should be marked as escaped when the key box
- # escapes.
- #self.dependencies = {}
-
+ # Global reset of all flags. Update both version numbers so
+ # that any access to '_heapc_flags' will be marked as outdated.
+ assert self.head_version < _HF_VERSION_MAX
+ self.head_version += _HF_VERSION_INC
+ self.likely_virtual_version = self.head_version
+ #
# heap cache
# maps descrs to CacheEntry
self.heap_cache = {}
# heap array cache
- # maps descrs to {index: {from_value: to_value}} dicts
+ # maps descrs to {index: CacheEntry} dicts
self.heap_array_cache = {}
def reset_keep_likely_virtuals(self):
- for value in self.values.itervalues():
- value.reset_keep_likely_virtual()
+ # Update only 'head_version', but 'likely_virtual_version' remains
+ # at its older value.
+ assert self.head_version < _HF_VERSION_MAX
+ self.head_version += _HF_VERSION_INC
self.heap_cache = {}
self.heap_array_cache = {}
- def getvalue(self, box, create=True):
- value = self.values.get(box, None)
- if not value and create:
- value = self.values[box] = HeapCacheValue(box)
- return value
+ @always_inline
+ def test_head_version(self, ref_frontend_op):
+ return ref_frontend_op._get_heapc_flags() >= self.head_version
- def getvalues(self, boxes):
- return [self.getvalue(box) for box in boxes]
+ @always_inline
+ def test_likely_virtual_version(self, ref_frontend_op):
+ return ref_frontend_op._get_heapc_flags() >=
self.likely_virtual_version
+
+ def update_version(self, ref_frontend_op):
+ """Ensure the version of 'ref_frontend_op' is current. If not,
+ it will update 'ref_frontend_op' (removing most flags currently set).
+ """
+ if not self.test_head_version(ref_frontend_op):
+ f = self.head_version
+ 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._set_heapc_flags(f)
+ ref_frontend_op._heapc_deps = None
def invalidate_caches(self, opnum, descr, argboxes):
self.mark_escaped(opnum, descr, argboxes)
self.clear_caches(opnum, descr, argboxes)
def _escape_from_write(self, box, fieldbox):
- value = self.getvalue(box, create=False)
- fieldvalue = self.getvalue(fieldbox, create=False)
- if (value is not None and value.is_unescaped and
- fieldvalue is not None and fieldvalue.is_unescaped):
- if value.dependencies is None:
- value.dependencies = []
- value.dependencies.append(fieldvalue)
- elif fieldvalue is not None:
- self._escape(fieldvalue)
+ if self.is_unescaped(box) and self.is_unescaped(fieldbox):
+ deps = self._get_deps(box)
+ deps.append(fieldbox)
+ elif fieldbox is not None:
+ self._escape_box(fieldbox)
def mark_escaped(self, opnum, descr, argboxes):
if opnum == rop.SETFIELD_GC:
@@ -176,19 +222,20 @@
self._escape_box(box)
def _escape_box(self, box):
- value = self.getvalue(box, create=False)
- if not value:
- return
- self._escape(value)
-
- def _escape(self, value):
- value.is_unescaped = False
- value.likely_virtual = False
- deps = value.dependencies
- value.dependencies = None
- if deps is not None:
- for dep in deps:
- self._escape(dep)
+ if isinstance(box, RefFrontendOp):
+ remove_flags(box, HF_LIKELY_VIRTUAL | HF_IS_UNESCAPED)
+ deps = box._heapc_deps
+ if deps is not None:
+ if not self.test_head_version(box):
+ box._heapc_deps = None
+ else:
+ # 'deps[0]' is abused to store the array length, keep it
+ if deps[0] is None:
+ box._heapc_deps = None
+ else:
+ box._heapc_deps = [deps[0]]
+ for i in range(1, len(deps)):
+ self._escape_box(deps[i])
def clear_caches(self, opnum, descr, argboxes):
if (opnum == rop.SETFIELD_GC or
@@ -241,7 +288,8 @@
self.reset_keep_likely_virtuals()
def _clear_caches_arraycopy(self, opnum, desrc, argboxes, effectinfo):
- seen_allocation_of_target = self.getvalue(argboxes[2]).seen_allocation
+ seen_allocation_of_target = self._check_flag(
+ argboxes[2], HF_SEEN_ALLOCATION)
if (
isinstance(argboxes[3], ConstInt) and
isinstance(argboxes[4], ConstInt) and
@@ -285,74 +333,82 @@
return
self.reset_keep_likely_virtuals()
+ def _get_deps(self, box):
+ if not isinstance(box, RefFrontendOp):
+ return None
+ self.update_version(box)
+ if box._heapc_deps is None:
+ box._heapc_deps = [None]
+ return box._heapc_deps
+
+ def _check_flag(self, box, flag):
+ return (isinstance(box, RefFrontendOp) and
+ self.test_head_version(box) and
+ 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):
- value = self.getvalue(box, create=False)
- if value:
- return value.known_class
- return False
+ return self._check_flag(box, HF_KNOWN_CLASS)
def class_now_known(self, box):
- self.getvalue(box).known_class = True
+ if isinstance(box, Const):
+ return
+ self._set_flag(box, HF_KNOWN_CLASS)
def is_nullity_known(self, box):
- value = self.getvalue(box, create=False)
- if value:
- return value.known_nullity
- return False
+ if isinstance(box, Const):
+ return bool(box.getref_base())
+ return self._check_flag(box, HF_KNOWN_NULLITY)
def nullity_now_known(self, box):
- self.getvalue(box).known_nullity = True
+ if isinstance(box, Const):
+ return
+ 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)
- if value:
- return value.is_unescaped
- return False
+ return self._check_flag(box, HF_IS_UNESCAPED)
def is_likely_virtual(self, box):
- value = self.getvalue(box, create=False)
- if value:
- return value.likely_virtual
- return False
+ # note: this is different from _check_flag()
+ return (isinstance(box, RefFrontendOp) and
+ self.test_likely_virtual_version(box) and
+ test_flags(box, HF_LIKELY_VIRTUAL))
def new(self, box):
- value = self.getvalue(box)
- value.is_unescaped = True
- value.likely_virtual = True
- value.seen_allocation = True
+ assert isinstance(box, RefFrontendOp)
+ self.update_version(box)
+ add_flags(box, HF_LIKELY_VIRTUAL | HF_SEEN_ALLOCATION |
HF_IS_UNESCAPED)
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)
+ if not isinstance(box, RefFrontendOp):
+ return dummy_field_updater
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)
@@ -365,17 +421,12 @@
def getarrayitem(self, box, indexbox, descr):
if not isinstance(indexbox, ConstInt):
return None
- value = self.getvalue(box, create=False)
- if value is None:
- return None
index = indexbox.getint()
cache = self.heap_array_cache.get(descr, None)
if cache:
indexcache = cache.get(index, None)
if indexcache is not None:
- resvalue = indexcache.read(value)
- if resvalue:
- return resvalue.box
+ return indexcache.read(box)
return None
def _get_or_make_array_cache_entry(self, indexbox, descr):
@@ -385,16 +436,14 @@
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
def getarrayitem_now_known(self, box, indexbox, fieldbox, descr):
- value = self.getvalue(box)
- fieldvalue = self.getvalue(fieldbox)
indexcache = self._get_or_make_array_cache_entry(indexbox, descr)
if indexcache:
- indexcache.read_now_known(value, fieldvalue)
+ indexcache.read_now_known(box, fieldbox)
def setarrayitem(self, box, indexbox, fieldbox, descr):
if not isinstance(indexbox, ConstInt):
@@ -402,25 +451,31 @@
if cache is not None:
cache.clear()
return
- value = self.getvalue(box)
- fieldvalue = self.getvalue(fieldbox)
indexcache = self._get_or_make_array_cache_entry(indexbox, descr)
if indexcache:
- indexcache.do_write_with_aliasing(value, fieldvalue)
+ indexcache.do_write_with_aliasing(box, fieldbox)
def arraylen(self, box):
- value = self.getvalue(box, create=False)
- if value and value.length:
- return value.length.box
+ if (isinstance(box, RefFrontendOp) and
+ self.test_head_version(box) and
+ box._heapc_deps is not None):
+ res_box = box._heapc_deps[0]
+ if res_box is not None:
+ return maybe_replace_with_const(res_box)
return None
def arraylen_now_known(self, box, lengthbox):
- value = self.getvalue(box)
- value.length = self.getvalue(lengthbox)
+ # we store in '_heapc_deps' a list of boxes: the *first* box is
+ # the known length or None, and the remaining boxes are the
+ # regular dependencies.
+ if isinstance(box, Const):
+ return
+ deps = self._get_deps(box)
+ assert deps is not None
+ deps[0] = lengthbox
def replace_box(self, oldbox, newbox):
- value = self.getvalue(oldbox, create=False)
- if value is None:
- return
- value.box = newbox
- self.values[newbox] = value
+ # here, only for replacing a box with a const
+ if isinstance(oldbox, FrontendOp) and isinstance(newbox, Const):
+ assert newbox.same_constant(constant_from_op(oldbox))
+ oldbox.set_replaced_with_const()
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
@@ -3,6 +3,7 @@
from rpython.rlib.objectmodel import we_are_translated, Symbolic
from rpython.rlib.objectmodel import compute_unique_id, specialize
from rpython.rlib.rarithmetic import r_int64, is_valid_int
+from rpython.rlib.rarithmetic import LONG_BIT, intmask, r_uint
from rpython.conftest import option
@@ -74,54 +75,6 @@
) #compute_unique_id(box))
-class XxxAbstractValue(object):
- __slots__ = ()
-
- def getint(self):
- raise NotImplementedError
-
- def getfloatstorage(self):
- raise NotImplementedError
-
- def getfloat(self):
- return longlong.getrealfloat(self.getfloatstorage())
-
- def getref_base(self):
- raise NotImplementedError
-
- def getref(self, TYPE):
- raise NotImplementedError
- getref._annspecialcase_ = 'specialize:arg(1)'
-
- def constbox(self):
- raise NotImplementedError
-
- def getaddr(self):
- "Only for raw addresses (BoxInt & ConstInt), not for GC addresses"
- raise NotImplementedError
-
- def sort_key(self):
- raise NotImplementedError
-
- def nonnull(self):
- raise NotImplementedError
-
- def repr_rpython(self):
- return '%s' % self
-
- def _get_str(self):
- raise NotImplementedError
-
- def same_box(self, other):
- return self is other
-
- def same_shape(self, other):
- # only structured containers can compare their shape (vector box)
- return True
-
- def getaccum(self):
- return None
-
class AbstractDescr(AbstractValue):
__slots__ = ('descr_index',)
llopaque = True
@@ -641,34 +594,76 @@
# ____________________________________________________________
+FO_REPLACED_WITH_CONST = r_uint(1)
+FO_POSITION_SHIFT = 1
+FO_POSITION_MASK = r_uint(0xFFFFFFFE)
+
+
class FrontendOp(AbstractResOp):
type = 'v'
- _attrs_ = ('position',)
+ _attrs_ = ('position_and_flags',)
def __init__(self, pos):
- self.position = pos
+ # p is the 32-bit position shifted left by one (might be negative,
+ # but casted to the 32-bit UINT type)
+ p = rffi.cast(rffi.UINT, pos << FO_POSITION_SHIFT)
+ self.position_and_flags = r_uint(p) # zero-extended to a full word
def get_position(self):
- return self.position
+ # p is the signed 32-bit position, from self.position_and_flags
+ p = rffi.cast(rffi.INT, self.position_and_flags)
+ return intmask(p) >> FO_POSITION_SHIFT
+
+ def set_position(self, new_pos):
+ assert new_pos >= 0
+ self.position_and_flags &= ~FO_POSITION_MASK
+ self.position_and_flags |= r_uint(new_pos << FO_POSITION_SHIFT)
+
+ def is_replaced_with_const(self):
+ return bool(self.position_and_flags & FO_REPLACED_WITH_CONST)
+
+ def set_replaced_with_const(self):
+ self.position_and_flags |= FO_REPLACED_WITH_CONST
+
+ def __repr__(self):
+ return '%s(0x%x)' % (self.__class__.__name__, self.position_and_flags)
class IntFrontendOp(IntOp, FrontendOp):
- _attrs_ = ('position', '_resint')
+ _attrs_ = ('position_and_flags', '_resint')
def copy_value_from(self, other):
self._resint = other.getint()
class FloatFrontendOp(FloatOp, FrontendOp):
- _attrs_ = ('position', '_resfloat')
+ _attrs_ = ('position_and_flags', '_resfloat')
def copy_value_from(self, other):
self._resfloat = other.getfloatstorage()
class RefFrontendOp(RefOp, FrontendOp):
- _attrs_ = ('position', '_resref')
+ _attrs_ = ('position_and_flags', '_resref', '_heapc_deps')
+ if LONG_BIT == 32:
+ _attrs_ += ('_heapc_flags',) # on 64 bit, this gets stored into the
+ _heapc_flags = r_uint(0) # high 32 bits of 'position_and_flags'
+ _heapc_deps = None
def copy_value_from(self, other):
self._resref = other.getref_base()
+ if LONG_BIT == 32:
+ def _get_heapc_flags(self):
+ return self._heapc_flags
+ def _set_heapc_flags(self, value):
+ self._heapc_flags = value
+ else:
+ def _get_heapc_flags(self):
+ return self.position_and_flags >> 32
+ def _set_heapc_flags(self, value):
+ self.position_and_flags = (
+ (self.position_and_flags & 0xFFFFFFFF) |
+ (value << 32))
+
+
class History(object):
ends_with_jump = False
trace = None
@@ -688,7 +683,7 @@
# hack to record the ops *after* we know our inputargs
for (opnum, argboxes, op, descr) in self._cache:
pos = self.trace.record_op(opnum, argboxes, descr)
- op.position = pos
+ op.set_position(pos)
self._cache = None
def length(self):
@@ -701,7 +696,7 @@
self.trace.cut_at(cut_at)
def any_operation(self):
- return self.trace._count > 0
+ return self.trace._count > self.trace._start
@specialize.argtype(2)
def set_op_value(self, op, value):
@@ -720,7 +715,7 @@
@specialize.argtype(3)
def record(self, opnum, argboxes, value, descr=None):
if self.trace is None:
- pos = -1
+ pos = 2**14 - 1
else:
pos = self.trace.record_op(opnum, argboxes, descr)
if value is None:
diff --git a/rpython/jit/metainterp/opencoder.py
b/rpython/jit/metainterp/opencoder.py
--- a/rpython/jit/metainterp/opencoder.py
+++ b/rpython/jit/metainterp/opencoder.py
@@ -10,7 +10,7 @@
from rpython.jit.metainterp.history import ConstInt, Const, ConstFloat,
ConstPtr
from rpython.jit.metainterp.resoperation import AbstractResOp,
AbstractInputArg,\
ResOperation, oparity, rop, opwithdescr, GuardResOp, IntOp, FloatOp, RefOp
-from rpython.rlib.rarithmetic import intmask
+from rpython.rlib.rarithmetic import intmask, r_uint
from rpython.rlib.objectmodel import we_are_translated
from rpython.rtyper.lltypesystem import rffi, lltype, llmemory
from rpython.jit.metainterp.typesystem import llhelper
@@ -63,24 +63,19 @@
if force_inputargs is not None:
self.inputargs = [rop.inputarg_from_tp(arg.type) for
arg in force_inputargs]
- self._inputargs = [None] * len(trace.inputargs)
for i, arg in enumerate(force_inputargs):
- if arg.get_position() >= 0:
- self._cache[arg.get_position()] = self.inputargs[i]
- else:
- self._inputargs[-arg.get_position()-1] = self.inputargs[i]
+ self._cache[arg.get_position()] = self.inputargs[i]
else:
self.inputargs = [rop.inputarg_from_tp(arg.type) for
arg in self.trace.inputargs]
- self._inputargs = self.inputargs[:]
+ for i, arg in enumerate(self.inputargs):
+ self._cache[i] = arg
self.start = start
self.pos = start
- self._count = 0
+ self._count = start
self.end = end
def _get(self, i):
- if i < 0:
- return self._inputargs[-i - 1]
res = self._cache[i]
assert res is not None
return res
@@ -197,9 +192,10 @@
self._floats_dict = {}
self._snapshots = []
for i, inparg in enumerate(inputargs):
- assert isinstance(inparg, AbstractInputArg)
- inparg.position = -i - 1
- self._count = 0
+ inparg.set_position(i)
+ self._count = len(inputargs)
+ self._start = len(inputargs)
+ self._pos = self._start
self.inputargs = inputargs
def append(self, v):
@@ -284,8 +280,7 @@
self._refs.append(box.getref_base())
return tag(TAGCONSTPTR, v)
elif isinstance(box, AbstractResOp):
- return tag(TAGBOX, box.get_position())
- elif isinstance(box, AbstractInputArg):
+ assert box.get_position() >= 0
return tag(TAGBOX, box.get_position())
else:
assert False, "unreachable code"
@@ -362,7 +357,7 @@
def get_iter(self, metainterp_sd=None):
assert metainterp_sd
- return TraceIterator(self, 0, self._pos, metainterp_sd=metainterp_sd)
+ return TraceIterator(self, self._start, self._pos,
metainterp_sd=metainterp_sd)
def unpack(self):
iter = self.get_iter()
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
@@ -2822,7 +2822,7 @@
self.history.record_nospec(rop.VIRTUAL_REF_FINISH,
[vrefbox, virtualbox], None)
newop = self.history.record_nospec(opnum, arglist, descr)
- op.position = newop.position
+ op.set_position(newop.get_position())
# mark by replacing it with ConstPtr(NULL)
self.virtualref_boxes[i+1] = self.cpu.ts.CONST_NULL
diff --git a/rpython/jit/metainterp/resume.py b/rpython/jit/metainterp/resume.py
--- a/rpython/jit/metainterp/resume.py
+++ b/rpython/jit/metainterp/resume.py
@@ -1,9 +1,9 @@
from rpython.jit.codewriter.effectinfo import EffectInfo
from rpython.jit.metainterp import jitprof
from rpython.jit.metainterp.history import (Const, ConstInt, getkind,
- INT, REF, FLOAT, AbstractDescr)
-from rpython.jit.metainterp.resoperation import rop, InputArgInt,\
- InputArgFloat, InputArgRef
+ INT, REF, FLOAT, AbstractDescr, IntFrontendOp, RefFrontendOp,
+ FloatFrontendOp)
+from rpython.jit.metainterp.resoperation import rop
from rpython.rlib import rarithmetic, rstack
from rpython.rlib.objectmodel import (we_are_translated, specialize,
compute_unique_id)
@@ -1264,11 +1264,14 @@
num += len(self.liveboxes)
assert num >= 0
if kind == INT:
- box = InputArgInt(self.cpu.get_int_value(self.deadframe, num))
+ box = IntFrontendOp(0)
+ box.setint(self.cpu.get_int_value(self.deadframe, num))
elif kind == REF:
- box = InputArgRef(self.cpu.get_ref_value(self.deadframe, num))
+ box = RefFrontendOp(0)
+ box.setref_base(self.cpu.get_ref_value(self.deadframe, num))
elif kind == FLOAT:
- box = InputArgFloat(self.cpu.get_float_value(self.deadframe, num))
+ box = FloatFrontendOp(0)
+ box.setfloatstorage(self.cpu.get_float_value(self.deadframe, num))
else:
assert 0, "bad kind: %d" % ord(kind)
self.liveboxes[num] = box
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
@@ -1,15 +1,9 @@
+import py
from rpython.jit.metainterp.heapcache import HeapCache
from rpython.jit.metainterp.resoperation import rop, InputArgInt
-from rpython.jit.metainterp.history import ConstInt, BasicFailDescr
+from rpython.jit.metainterp.history import ConstInt, ConstPtr, BasicFailDescr
+from rpython.jit.metainterp.history import IntFrontendOp, RefFrontendOp
-box1 = "box1"
-box2 = "box2"
-box3 = "box3"
-box4 = "box4"
-box5 = "box5"
-lengthbox1 = object()
-lengthbox2 = object()
-lengthbox3 = object()
descr1 = object()
descr2 = object()
descr3 = object()
@@ -59,43 +53,52 @@
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()
- assert not h.is_nullity_known(1)
- assert not h.is_nullity_known(2)
- h.nullity_now_known(1)
- assert h.is_nullity_known(1)
- assert not h.is_nullity_known(2)
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
+ assert not h.is_nullity_known(box1)
+ assert not h.is_nullity_known(box2)
+ h.nullity_now_known(box1)
+ assert h.is_nullity_known(box1)
+ assert not h.is_nullity_known(box2)
h.reset()
- assert not h.is_nullity_known(1)
- assert not h.is_nullity_known(2)
+ assert not h.is_nullity_known(box1)
+ assert not h.is_nullity_known(box2)
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)
@@ -119,6 +122,10 @@
def test_heapcache_read_fields_multiple(self):
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
+ box3 = RefFrontendOp(3)
+ box4 = RefFrontendOp(4)
h.getfield_now_known(box1, descr1, box2)
h.getfield_now_known(box3, descr1, box4)
assert h.getfield(box1, descr1) is box2
@@ -134,6 +141,10 @@
def test_heapcache_write_fields_multiple(self):
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
+ box3 = RefFrontendOp(3)
+ box4 = RefFrontendOp(4)
h.setfield(box1, box2, descr1)
assert h.getfield(box1, descr1) is box2
h.setfield(box3, box4, descr1)
@@ -141,6 +152,10 @@
assert h.getfield(box1, descr1) is None # box1 and box3 can alias
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
+ box3 = RefFrontendOp(3)
+ box4 = RefFrontendOp(4)
h.new(box1)
h.setfield(box1, box2, descr1)
assert h.getfield(box1, descr1) is box2
@@ -149,6 +164,10 @@
assert h.getfield(box1, descr1) is None # box1 and box3 can alias
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
+ box3 = RefFrontendOp(3)
+ box4 = RefFrontendOp(4)
h.new(box1)
h.new(box3)
h.setfield(box1, box2, descr1)
@@ -162,6 +181,10 @@
def test_heapcache_arrays(self):
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
+ box3 = RefFrontendOp(3)
+ box4 = RefFrontendOp(4)
assert h.getarrayitem(box1, index1, descr1) is None
assert h.getarrayitem(box1, index1, descr2) is None
assert h.getarrayitem(box1, index2, descr1) is None
@@ -204,6 +227,10 @@
def test_heapcache_array_nonconst_index(self):
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
+ box3 = RefFrontendOp(3)
+ box4 = RefFrontendOp(4)
h.setarrayitem(box1, index1, box2, descr1)
h.setarrayitem(box1, index2, box4, descr1)
assert h.getarrayitem(box1, index1, descr1) is box2
@@ -214,6 +241,10 @@
def test_heapcache_read_fields_multiple_array(self):
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
+ box3 = RefFrontendOp(3)
+ box4 = RefFrontendOp(4)
h.getarrayitem_now_known(box1, index1, box2, descr1)
h.getarrayitem_now_known(box3, index1, box4, descr1)
assert h.getarrayitem(box1, index1, descr1) is box2
@@ -229,6 +260,10 @@
def test_heapcache_write_fields_multiple_array(self):
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
+ box3 = RefFrontendOp(3)
+ box4 = RefFrontendOp(4)
h.setarrayitem(box1, index1, box2, descr1)
assert h.getarrayitem(box1, index1, descr1) is box2
h.setarrayitem(box3, index1, box4, descr1)
@@ -236,6 +271,10 @@
assert h.getarrayitem(box1, index1, descr1) is None # box1 and box3
can alias
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
+ box3 = RefFrontendOp(3)
+ box4 = RefFrontendOp(4)
h.new(box1)
h.setarrayitem(box1, index1, box2, descr1)
assert h.getarrayitem(box1, index1, descr1) is box2
@@ -244,6 +283,10 @@
assert h.getarrayitem(box1, index1, descr1) is None # box1 and box3
can alias
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
+ box3 = RefFrontendOp(3)
+ box4 = RefFrontendOp(4)
h.new(box1)
h.new(box3)
h.setarrayitem(box1, index1, box2, descr1)
@@ -257,6 +300,10 @@
def test_length_cache(self):
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
+ lengthbox1 = IntFrontendOp(11)
+ lengthbox2 = IntFrontendOp(12)
h.new_array(box1, lengthbox1)
assert h.arraylen(box1) is lengthbox1
@@ -267,6 +314,9 @@
def test_invalidate_cache(self):
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
+ box4 = RefFrontendOp(4)
h.setfield(box1, box2, descr1)
h.setarrayitem(box1, index1, box2, descr1)
h.setarrayitem(box1, index2, box4, descr1)
@@ -298,8 +348,13 @@
assert h.getarrayitem(box1, index1, descr1) is None
assert h.getarrayitem(box1, index2, descr1) is None
- def test_replace_box(self):
+ def test_replace_box_with_box(self):
+ py.test.skip("replacing a box with another box: not supported any
more")
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
+ box3 = RefFrontendOp(3)
+ box4 = RefFrontendOp(4)
h.setfield(box1, box2, descr1)
h.setfield(box1, box3, descr2)
h.setfield(box2, box3, descr3)
@@ -310,16 +365,22 @@
h.setfield(box4, box3, descr1)
assert h.getfield(box4, descr1) is box3
+ def test_replace_box_with_const(self):
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
+ box3 = RefFrontendOp(3)
+ c_box3 = ConstPtr(ConstPtr.value)
h.setfield(box1, box2, descr1)
h.setfield(box1, box3, descr2)
h.setfield(box2, box3, descr3)
- h.replace_box(box3, box4)
+ h.replace_box(box3, c_box3)
assert h.getfield(box1, descr1) is box2
- assert h.getfield(box1, descr2) is box4
- assert h.getfield(box2, descr3) is box4
+ assert c_box3.same_constant(h.getfield(box1, descr2))
+ assert c_box3.same_constant(h.getfield(box2, descr3))
def test_replace_box_twice(self):
+ py.test.skip("replacing a box with another box: not supported any
more")
h = HeapCache()
h.setfield(box1, box2, descr1)
h.setfield(box1, box3, descr2)
@@ -343,6 +404,7 @@
assert h.getfield(box2, descr3) is box5
def test_replace_box_array(self):
+ py.test.skip("replacing a box with another box: not supported any
more")
h = HeapCache()
h.setarrayitem(box1, index1, box2, descr1)
h.setarrayitem(box1, index1, box3, descr2)
@@ -362,6 +424,7 @@
assert h.arraylen(box4) is lengthbox2
def test_replace_box_array_twice(self):
+ py.test.skip("replacing a box with another box: not supported any
more")
h = HeapCache()
h.setarrayitem(box1, index1, box2, descr1)
h.setarrayitem(box1, index1, box3, descr2)
@@ -382,8 +445,34 @@
h.replace_box(lengthbox2, lengthbox3)
assert h.arraylen(box4) is lengthbox3
+ def test_replace_box_with_const_in_array(self):
+ h = HeapCache()
+ box1 = RefFrontendOp(1)
+ lengthbox2 = IntFrontendOp(2)
+ lengthbox2.setint(10)
+ h.arraylen_now_known(box1, lengthbox2)
+ assert h.arraylen(box1) is lengthbox2
+ c10 = ConstInt(10)
+ h.replace_box(lengthbox2, c10)
+ assert c10.same_constant(h.arraylen(box1))
+
+ box2 = IntFrontendOp(2)
+ box2.setint(12)
+ h.setarrayitem(box1, index2, box2, descr1)
+ assert h.getarrayitem(box1, index2, descr1) is box2
+ c12 = ConstInt(12)
+ h.replace_box(box2, c12)
+ assert c12.same_constant(h.getarrayitem(box1, index2, descr1))
+
def test_ll_arraycopy(self):
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
+ box3 = RefFrontendOp(3)
+ box4 = RefFrontendOp(4)
+ box5 = RefFrontendOp(5)
+ lengthbox1 = IntFrontendOp(11)
+ lengthbox2 = IntFrontendOp(12)
h.new_array(box1, lengthbox1)
h.setarrayitem(box1, index1, box2, descr1)
h.new_array(box2, lengthbox1)
@@ -412,6 +501,10 @@
def test_ll_arraycopy_differing_descrs(self):
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
+ box3 = RefFrontendOp(3)
+ lengthbox2 = IntFrontendOp(12)
h.setarrayitem(box1, index1, box2, descr2)
assert h.getarrayitem(box1, index1, descr2) is box2
h.new_array(box2, lengthbox2)
@@ -424,6 +517,9 @@
def test_ll_arraycopy_differing_descrs_nonconst_index(self):
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
+ box3 = RefFrontendOp(3)
h.setarrayitem(box1, index1, box2, descr2)
assert h.getarrayitem(box1, index1, descr2) is box2
h.invalidate_caches(
@@ -435,6 +531,9 @@
def test_ll_arraycopy_result_propogated(self):
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
+ box3 = RefFrontendOp(3)
h.setarrayitem(box1, index1, box2, descr1)
h.invalidate_caches(
rop.CALL_N,
@@ -445,6 +544,11 @@
def test_ll_arraycopy_dest_new(self):
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
+ box3 = RefFrontendOp(3)
+ box4 = RefFrontendOp(4)
+ lengthbox1 = IntFrontendOp(11)
h.new_array(box1, lengthbox1)
h.setarrayitem(box3, index1, box4, descr1)
h.invalidate_caches(
@@ -455,6 +559,10 @@
def test_ll_arraycopy_doesnt_escape_arrays(self):
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
+ lengthbox1 = IntFrontendOp(11)
+ lengthbox2 = IntFrontendOp(12)
h.new_array(box1, lengthbox1)
h.new_array(box2, lengthbox2)
h.invalidate_caches(
@@ -474,6 +582,8 @@
def test_unescaped(self):
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
assert not h.is_unescaped(box1)
h.new(box2)
assert h.is_unescaped(box2)
@@ -484,6 +594,9 @@
def test_unescaped_testing(self):
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
+ box3 = RefFrontendOp(3)
h.new(box1)
h.new(box2)
assert h.is_unescaped(box1)
@@ -502,6 +615,8 @@
def test_ops_dont_escape(self):
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
h.new(box1)
h.new(box2)
assert h.is_unescaped(box1)
@@ -515,6 +630,9 @@
def test_circular_virtuals(self):
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
+ box3 = RefFrontendOp(3)
h.new(box1)
h.new(box2)
h.invalidate_caches(rop.SETFIELD_GC, None, [box1, box2])
@@ -523,6 +641,10 @@
def test_unescaped_array(self):
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
+ lengthbox1 = IntFrontendOp(11)
+ lengthbox2 = IntFrontendOp(12)
h.new_array(box1, lengthbox1)
assert h.is_unescaped(box1)
h.invalidate_caches(rop.SETARRAYITEM_GC, None, [box1, index1, box2])
@@ -546,6 +668,8 @@
def test_call_doesnt_invalidate_unescaped_boxes(self):
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
h.new(box1)
assert h.is_unescaped(box1)
h.setfield(box1, box2, descr1)
@@ -557,6 +681,9 @@
def test_call_doesnt_invalidate_unescaped_array_boxes(self):
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box3 = RefFrontendOp(3)
+ lengthbox1 = IntFrontendOp(11)
h.new_array(box1, lengthbox1)
assert h.is_unescaped(box1)
h.setarrayitem(box1, index1, box3, descr1)
@@ -568,6 +695,8 @@
def test_bug_missing_ignored_operations(self):
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
h.new(box1)
h.new(box2)
h.setfield(box1, box2, descr1)
@@ -590,6 +719,8 @@
# calling some residual code that changes the values on box3: then
# the content of box2 is still cached at the old value.
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
h.new(box1)
h.new(box2)
h.setfield(box1, box2, descr1)
@@ -602,6 +733,8 @@
def test_bug_heap_cache_is_cleared_but_not_is_unescaped_2(self):
h = HeapCache()
+ box1 = RefFrontendOp(1)
+ box2 = RefFrontendOp(2)
h.new(box1)
h.new(box2)
h.setfield(box1, box2, descr1)
@@ -624,6 +757,7 @@
def test_is_likely_virtual(self):
h = HeapCache()
+ box1 = RefFrontendOp(1)
h.new(box1)
assert h.is_unescaped(box1)
assert h.is_likely_virtual(box1)
@@ -633,3 +767,29 @@
h._escape_box(box1)
assert not h.is_unescaped(box1)
assert not h.is_likely_virtual(box1)
+
+ def test_is_likely_virtual_2(self):
+ h = HeapCache()
+ box1 = RefFrontendOp(1)
+ h.new(box1)
+ assert h.is_unescaped(box1)
+ assert h.is_likely_virtual(box1)
+ h.reset_keep_likely_virtuals()
+ assert not h.is_unescaped(box1)
+ assert h.is_likely_virtual(box1)
+ h.reset() # reset everything
+ assert not h.is_unescaped(box1)
+ assert not h.is_likely_virtual(box1)
+
+ def test_is_likely_virtual_3(self):
+ h = HeapCache()
+ box1 = RefFrontendOp(1)
+ h.new(box1)
+ assert h.is_unescaped(box1)
+ assert h.is_likely_virtual(box1)
+ h.reset_keep_likely_virtuals()
+ assert not h.is_unescaped(box1)
+ assert h.is_likely_virtual(box1)
+ h.class_now_known(box1) # interaction of the two families of flags
+ assert not h.is_unescaped(box1)
+ assert h.is_likely_virtual(box1)
diff --git a/rpython/jit/metainterp/test/test_history.py
b/rpython/jit/metainterp/test/test_history.py
--- a/rpython/jit/metainterp/test/test_history.py
+++ b/rpython/jit/metainterp/test/test_history.py
@@ -62,6 +62,14 @@
assert c5.nonnull()
assert c6.nonnull()
+def test_frontendop():
+ f = FrontendOp(42)
+ assert f.get_position() == 42
+ f = FrontendOp(-56)
+ assert f.get_position() == -56
+ f.set_position(6519)
+ assert f.get_position() == 6519
+
class TestZTranslated(StandaloneTests):
def test_ztranslated_same_constant_float(self):
def fn(args):
diff --git a/rpython/jit/metainterp/test/test_opencoder.py
b/rpython/jit/metainterp/test/test_opencoder.py
--- a/rpython/jit/metainterp/test/test_opencoder.py
+++ b/rpython/jit/metainterp/test/test_opencoder.py
@@ -1,7 +1,7 @@
from rpython.jit.metainterp.opencoder import Trace, untag, TAGINT, TAGBOX
-from rpython.jit.metainterp.resoperation import rop, InputArgInt, AbstractResOp
-from rpython.jit.metainterp.history import ConstInt
+from rpython.jit.metainterp.resoperation import rop, AbstractResOp
+from rpython.jit.metainterp.history import ConstInt, IntFrontendOp
from rpython.jit.metainterp.optimizeopt.optimizer import Optimizer
from rpython.jit.metainterp import resume
from rpython.jit.metainterp.test.strategies import lists_of_operations
@@ -31,8 +31,11 @@
self.jitcode = jitcode
self.boxes = boxes
- def get_list_of_active_boxes(self, flag):
- return self.boxes
+ def get_list_of_active_boxes(self, flag, new_array, encode):
+ a = new_array(len(self.boxes))
+ for i, box in enumerate(self.boxes):
+ a[i] = encode(box)
+ return a
def unpack_snapshot(t, op, pos):
op.framestack = []
@@ -58,7 +61,7 @@
return iter.inputargs, l, iter
def test_simple_iterator(self):
- i0, i1 = InputArgInt(), InputArgInt()
+ i0, i1 = IntFrontendOp(0), IntFrontendOp(0)
t = Trace([i0, i1])
add = FakeOp(t.record_op(rop.INT_ADD, [i0, i1]))
t.record_op(rop.INT_ADD, [add, ConstInt(1)])
@@ -72,7 +75,7 @@
assert l[0].getarg(1) is i1
def test_rd_snapshot(self):
- i0, i1 = InputArgInt(), InputArgInt()
+ i0, i1 = IntFrontendOp(0), IntFrontendOp(0)
t = Trace([i0, i1])
add = FakeOp(t.record_op(rop.INT_ADD, [i0, i1]))
t.record_op(rop.GUARD_FALSE, [add])
@@ -96,7 +99,7 @@
assert fstack[1].boxes == [i0, i0, l[0]]
def test_read_snapshot_interface(self):
- i0, i1, i2 = InputArgInt(), InputArgInt(), InputArgInt()
+ i0, i1, i2 = IntFrontendOp(0), IntFrontendOp(0), IntFrontendOp(0)
t = Trace([i0, i1, i2])
t.record_op(rop.GUARD_TRUE, [i1])
frame0 = FakeFrame(1, JitCode(2), [i0, i1])
@@ -128,8 +131,9 @@
assert pc == 3
assert snapshot_iter.unpack_array(framestack[1].box_array) == [i2, i2]
+ # XXXX fixme
@given(lists_of_operations())
- def test_random_snapshot(self, lst):
+ def xxx_test_random_snapshot(self, lst):
inputargs, ops = lst
t = Trace(inputargs)
for op in ops:
@@ -156,11 +160,11 @@
assert (((-iter._next() - 1) << 15) | (iter._next())) == i
def test_cut_trace_from(self):
- i0, i1, i2 = InputArgInt(), InputArgInt(), InputArgInt()
+ i0, i1, i2 = IntFrontendOp(0), IntFrontendOp(0), IntFrontendOp(0)
t = Trace([i0, i1, i2])
- add1 = t.record_op(rop.INT_ADD, [i0, i1])
+ add1 = FakeOp(t.record_op(rop.INT_ADD, [i0, i1]))
cut_point = t.cut_point()
- add2 = t.record_op(rop.INT_ADD, [add1, i1])
+ add2 = FakeOp(t.record_op(rop.INT_ADD, [add1, i1]))
t.record_op(rop.GUARD_TRUE, [add2])
resume.capture_resumedata([FakeFrame(3, JitCode(4), [add2, add1, i1])],
None, [], t)
@@ -174,9 +178,9 @@
class SomeDescr(AbstractDescr):
pass
- i0, i1, i2 = InputArgInt(), InputArgInt(), InputArgInt()
+ i0, i1, i2 = IntFrontendOp(0), IntFrontendOp(0), IntFrontendOp(0)
t = Trace([i0, i1, i2])
- p0 = t.record_op(rop.NEW_WITH_VTABLE, [], descr=SomeDescr())
+ p0 = FakeOp(t.record_op(rop.NEW_WITH_VTABLE, [], descr=SomeDescr()))
t.record_op(rop.GUARD_TRUE, [i0])
resume.capture_resumedata([], [i1, i2, p0], [p0, i1], t)
(i0, i1, i2), l, iter = self.unpack(t)
diff --git a/rpython/jit/metainterp/warmstate.py
b/rpython/jit/metainterp/warmstate.py
--- a/rpython/jit/metainterp/warmstate.py
+++ b/rpython/jit/metainterp/warmstate.py
@@ -75,7 +75,9 @@
if in_const_box:
return history.ConstPtr(value)
else:
- return resoperation.InputArgRef(value)
+ res = history.RefFrontendOp(0)
+ res.setref_base(value)
+ return res
else:
adr = llmemory.cast_ptr_to_adr(value)
value = heaptracker.adr2int(adr)
@@ -89,7 +91,9 @@
if in_const_box:
return history.ConstFloat(value)
else:
- return resoperation.InputArgFloat(value)
+ res = history.FloatFrontendOp(0)
+ res.setfloatstorage(value)
+ return res
elif isinstance(value, str) or isinstance(value, unicode):
assert len(value) == 1 # must be a character
value = ord(value)
@@ -100,7 +104,9 @@
if in_const_box:
return history.ConstInt(value)
else:
- return resoperation.InputArgInt(value)
+ res = history.IntFrontendOp(0)
+ res.setint(value)
+ return res
@specialize.arg(0)
def equal_whatever(TYPE, x, y):
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit