Author: Armin Rigo <ar...@tunes.org> 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 pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit