Author: Carl Friedrich Bolz <[email protected]>
Branch: optinfo-into-bridges
Changeset: r87847:50dd16dbcea8
Date: 2016-10-17 15:52 +0200
http://bitbucket.org/pypy/pypy/changeset/50dd16dbcea8/
Log: encode pending fields into the resume code
(it's more compact and saves one word on every guard)
diff --git a/rpython/jit/metainterp/compile.py
b/rpython/jit/metainterp/compile.py
--- a/rpython/jit/metainterp/compile.py
+++ b/rpython/jit/metainterp/compile.py
@@ -17,8 +17,7 @@
TargetToken, AbstractFailDescr, ConstInt)
from rpython.jit.metainterp import history, jitexc
from rpython.jit.metainterp.optimize import InvalidLoop
-from rpython.jit.metainterp.resume import (PENDINGFIELDSP,
- ResumeDataDirectReader, AccumInfo)
+from rpython.jit.metainterp.resume import ResumeDataDirectReader
from rpython.jit.metainterp.resumecode import NUMBERING
from rpython.jit.codewriter import heaptracker, longlong
@@ -864,18 +863,16 @@
class ResumeGuardDescr(AbstractResumeGuardDescr):
_attrs_ = ('rd_numb', 'rd_consts', 'rd_virtuals',
- 'rd_pendingfields', 'status')
+ 'status')
rd_numb = lltype.nullptr(NUMBERING)
rd_consts = None
rd_virtuals = None
- rd_pendingfields = lltype.nullptr(PENDINGFIELDSP.TO)
def copy_all_attributes_from(self, other):
if isinstance(other, ResumeGuardCopiedDescr):
other = other.prev
assert isinstance(other, ResumeGuardDescr)
self.rd_consts = other.rd_consts
- self.rd_pendingfields = other.rd_pendingfields
self.rd_virtuals = other.rd_virtuals
self.rd_numb = other.rd_numb
# we don't copy status
diff --git a/rpython/jit/metainterp/optimizeopt/heap.py
b/rpython/jit/metainterp/optimizeopt/heap.py
--- a/rpython/jit/metainterp/optimizeopt/heap.py
+++ b/rpython/jit/metainterp/optimizeopt/heap.py
@@ -227,6 +227,11 @@
self.cached_infos = []
self.cached_structs = []
+class PendingWrites(object):
+ def __init__(self, fields, arrays):
+ self.fields = fields
+ self.arrays = arrays
+
class OptHeap(Optimization):
"""Cache repeated heap accesses"""
@@ -329,7 +334,7 @@
if rop.is_ovf(op.opnum):
return
if rop.is_guard(op.opnum):
- self.optimizer.pendingfields = (
+ self.optimizer.pendingwrites = (
self.force_lazy_sets_for_guard())
return
opnum = op.getopnum()
@@ -513,6 +518,7 @@
pendingfields.append(op)
continue
cf.force_lazy_set(self, descr)
+ pendingarrays = []
for descr, submap in self.cached_arrayitems.iteritems():
for index, cf in submap.iteritems():
op = cf._lazy_set
@@ -525,10 +531,10 @@
opinfo = self.getptrinfo(op.getarg(0))
assert not opinfo.is_virtual() # it must be a non-virtual
if self.optimizer.is_virtual(op.getarg(2)):
- pendingfields.append(op)
+ pendingarrays.append(op)
else:
cf.force_lazy_set(self, descr)
- return pendingfields
+ return PendingWrites(pendingfields, pendingarrays)
def optimize_GETFIELD_GC_I(self, op):
descr = op.getdescr()
diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py
b/rpython/jit/metainterp/optimizeopt/optimizer.py
--- a/rpython/jit/metainterp/optimizeopt/optimizer.py
+++ b/rpython/jit/metainterp/optimizeopt/optimizer.py
@@ -274,8 +274,9 @@
self.interned_refs = self.cpu.ts.new_ref_dict()
self.interned_ints = {}
self.resumedata_memo = resume.ResumeDataLoopMemo(metainterp_sd)
- self.pendingfields = None # set temporarily to a list, normally by
- # heap.py, as we're about to generate a guard
+ # set temporarily to an instance of heap.PendingWrites, normally by
+ # heap.py, as we're about to generate a guard
+ self.pendingwrites = None
self.quasi_immutable_deps = None
self.replaces_guard = {}
self._newoperations = []
@@ -612,14 +613,14 @@
if rop.is_guard(op.opnum):
assert isinstance(op, GuardResOp)
self.metainterp_sd.profiler.count(jitprof.Counters.OPT_GUARDS)
- pendingfields = self.pendingfields
- self.pendingfields = None
+ pendingwrites = self.pendingwrites
+ self.pendingwrites = None
if self.replaces_guard and orig_op in self.replaces_guard:
self.replace_guard_op(self.replaces_guard[orig_op], op)
del self.replaces_guard[orig_op]
return
else:
- op = self.emit_guard_operation(op, pendingfields)
+ op = self.emit_guard_operation(op, pendingwrites)
elif op.can_raise():
self.exception_might_have_happened = True
opnum = op.opnum
@@ -632,7 +633,7 @@
self._really_emitted_operation = op
self._newoperations.append(op)
- def emit_guard_operation(self, op, pendingfields):
+ def emit_guard_operation(self, op, pendingwrites):
guard_op = op # self.replace_op_with(op, op.getopnum())
opnum = guard_op.getopnum()
# If guard_(no)_exception is merged with another previous guard, then
@@ -652,7 +653,7 @@
op = self._copy_resume_data_from(guard_op,
self._last_guard_op)
else:
- op = self.store_final_boxes_in_guard(guard_op, pendingfields)
+ op = self.store_final_boxes_in_guard(guard_op, pendingwrites)
self._last_guard_op = op
# for unrolling
for farg in op.getfailargs():
@@ -722,8 +723,7 @@
new_descr.copy_all_attributes_from(old_descr)
self._newoperations[old_op_pos] = new_op
- def store_final_boxes_in_guard(self, op, pendingfields):
- assert pendingfields is not None
+ def store_final_boxes_in_guard(self, op, pendingwrites):
if op.getdescr() is not None:
descr = op.getdescr()
assert isinstance(descr, compile.ResumeGuardDescr)
@@ -735,11 +735,12 @@
modifier = resume.ResumeDataVirtualAdder(self, descr, op, self.trace,
self.resumedata_memo)
try:
- newboxes = modifier.finish(pendingfields)
+ newboxes = modifier.finish(pendingwrites)
if (newboxes is not None and
len(newboxes) > self.metainterp_sd.options.failargs_limit):
raise resume.TagOverflow
except resume.TagOverflow:
+ #import pdb;pdb.xpm()
raise compile.giveup()
# check no duplicates
#if not we_are_translated():
diff --git a/rpython/jit/metainterp/optimizeopt/simplify.py
b/rpython/jit/metainterp/optimizeopt/simplify.py
--- a/rpython/jit/metainterp/optimizeopt/simplify.py
+++ b/rpython/jit/metainterp/optimizeopt/simplify.py
@@ -10,8 +10,7 @@
def emit(self, op):
if op.is_guard():
- if self.optimizer.pendingfields is None:
- self.optimizer.pendingfields = []
+ self.optimizer.pendingwrites = None
return Optimization.emit(self, op)
def optimize_CALL_PURE_I(self, op):
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_util.py
b/rpython/jit/metainterp/optimizeopt/test/test_util.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_util.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_util.py
@@ -488,6 +488,8 @@
self.globaldata = Fake()
self.config = get_combined_translation_config(translating=True)
self.jitlog = jl.JitLogger()
+ if cpu:
+ self.all_descrs = self.cpu.setup_descrs()
class logger_noopt:
@classmethod
diff --git a/rpython/jit/metainterp/optimizeopt/virtualize.py
b/rpython/jit/metainterp/optimizeopt/virtualize.py
--- a/rpython/jit/metainterp/optimizeopt/virtualize.py
+++ b/rpython/jit/metainterp/optimizeopt/virtualize.py
@@ -80,7 +80,8 @@
def postprocess_FINISH(self, op):
guard_op = self._finish_guard_op
if guard_op is not None:
- guard_op = self.optimizer.store_final_boxes_in_guard(guard_op, [])
+ # XXX why are there never any pendingwrites here?
+ guard_op = self.optimizer.store_final_boxes_in_guard(guard_op,
None)
i = len(self.optimizer._newoperations) - 1
assert i >= 0
self.optimizer._newoperations.insert(i, guard_op)
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
@@ -116,13 +116,6 @@
virtualizable_boxes, virtualref_boxes)
return result
-PENDINGFIELDSTRUCT = lltype.Struct('PendingField',
- ('lldescr', OBJECTPTR),
- ('num', rffi.SHORT),
- ('fieldnum', rffi.SHORT),
- ('itemindex', rffi.INT))
-PENDINGFIELDSP = lltype.Ptr(lltype.GcArray(PENDINGFIELDSTRUCT))
-
TAGMASK = 3
def tag(value, tagbits):
@@ -160,7 +153,7 @@
TAG_CONST_OFFSET = 0
class NumberingState(resumecode.Writer):
- def __init__(self, size):
+ def __init__(self, size=0):
resumecode.Writer.__init__(self, size)
self.liveboxes = {}
self.num_boxes = 0
@@ -217,45 +210,47 @@
# env numbering
+ def _number_box(self, box, optimizer, numb_state):
+ box = optimizer.get_box_replacement(box)
+ liveboxes = numb_state.liveboxes
+
+ if isinstance(box, Const):
+ tagged = self.getconst(box)
+ elif box in liveboxes:
+ tagged = liveboxes[box]
+ else:
+ is_virtual = False
+ if box.type == 'r':
+ info = optimizer.getptrinfo(box)
+ is_virtual = (info is not None and info.is_virtual())
+ if box.type == 'i':
+ info = optimizer.getrawptrinfo(box, create=False)
+ is_virtual = (info is not None and info.is_virtual())
+ if is_virtual:
+ tagged = tag(numb_state.num_virtuals, TAGVIRTUAL)
+ numb_state.num_virtuals += 1
+ else:
+ tagged = tag(numb_state.num_boxes, TAGBOX)
+ numb_state.num_boxes += 1
+ liveboxes[box] = tagged
+ return tagged
+
def _number_boxes(self, iter, arr, optimizer, numb_state):
""" Number boxes from one snapshot
"""
- num_boxes = numb_state.num_boxes
- num_virtuals = numb_state.num_virtuals
- liveboxes = numb_state.liveboxes
for item in arr:
box = iter.get(rffi.cast(lltype.Signed, item))
- box = optimizer.get_box_replacement(box)
+ tagged = self._number_box(box, optimizer, numb_state)
+ numb_state.append_int(tagged)
- if isinstance(box, Const):
- tagged = self.getconst(box)
- elif box in liveboxes:
- tagged = liveboxes[box]
- else:
- is_virtual = False
- if box.type == 'r':
- info = optimizer.getptrinfo(box)
- is_virtual = (info is not None and info.is_virtual())
- if box.type == 'i':
- info = optimizer.getrawptrinfo(box, create=False)
- is_virtual = (info is not None and info.is_virtual())
- if is_virtual:
- tagged = tag(num_virtuals, TAGVIRTUAL)
- num_virtuals += 1
- else:
- tagged = tag(num_boxes, TAGBOX)
- num_boxes += 1
- liveboxes[box] = tagged
- numb_state.append_int(tagged)
- numb_state.num_boxes = num_boxes
- numb_state.num_virtuals = num_virtuals
-
- def number(self, optimizer, position, trace):
+ def number(self, optimizer, position, trace, pendingwrites=None):
snapshot_iter = trace.get_snapshot_iter(position)
numb_state = NumberingState(snapshot_iter.size)
numb_state.append_int(0) # patch later: size of resume section
numb_state.append_int(0) # patch later: number of failargs
+ self._add_pending_writes(optimizer, pendingwrites, numb_state)
+
arr = snapshot_iter.vable_array
numb_state.append_int(len(arr))
@@ -278,6 +273,43 @@
return numb_state
+ def _add_pending_writes(self, optimizer, pendingwrites, numb_state):
+ if not pendingwrites:
+ numb_state.append_int(0)
+ numb_state.append_int(0)
+ return
+ metainterp_sd = optimizer.metainterp_sd
+ numb_state.append_int(len(pendingwrites.fields))
+ for op in pendingwrites.fields:
+ box = optimizer.get_box_replacement(op.getarg(0))
+ descr = op.getdescr()
+ if descr.descr_index == -1:
+ raise TagOverflow # shouldn't happen
+ fieldbox = optimizer.get_box_replacement(op.getarg(1))
+ numb_state.append_int(self._number_box(box, optimizer, numb_state))
+ numb_state.append_int(descr.descr_index)
+ numb_state.append_int(self._number_box(fieldbox, optimizer,
numb_state))
+
+ numb_state.append_int(len(pendingwrites.arrays))
+ for op in pendingwrites.arrays:
+ box = optimizer.get_box_replacement(op.getarg(0))
+ descr = op.getdescr()
+ if descr.descr_index == -1:
+ raise TagOverflow # shouldn't happen
+ boxindex = optimizer.get_box_replacement(op.getarg(1))
+ itemindex = boxindex.getint()
+ # sanity: it's impossible to run code with SETARRAYITEM_GC
+ # with negative index, so this guard cannot ever fail;
+ # but it's possible to try to *build* such invalid code
+ if itemindex < 0:
+ raise TagOverflow
+ fieldbox = optimizer.get_box_replacement(op.getarg(2))
+ numb_state.append_int(self._number_box(box, optimizer, numb_state))
+ numb_state.append_int(descr.descr_index)
+ # the index is limited to 2**21
+ numb_state.append_int(itemindex)
+ numb_state.append_int(self._number_box(fieldbox, optimizer,
numb_state))
+
# caching for virtuals and boxes inside them
@@ -409,7 +441,7 @@
_, tagbits = untag(tagged)
return tagbits == TAGVIRTUAL
- def finish(self, pending_setfields=[]):
+ def finish(self, pendingwrites=None):
optimizer = self.optimizer
# compute the numbering
storage = self.storage
@@ -419,7 +451,7 @@
assert resume_position >= 0
# count stack depth
numb_state = self.memo.number(optimizer,
- resume_position, optimizer.trace)
+ resume_position, optimizer.trace, pendingwrites)
self.liveboxes_from_env = liveboxes_from_env = numb_state.liveboxes
num_virtuals = numb_state.num_virtuals
self.liveboxes = {}
@@ -442,22 +474,8 @@
assert info.is_virtual()
info.visitor_walk_recursive(box, self, optimizer)
- for setfield_op in pending_setfields:
- box = setfield_op.getarg(0)
- box = optimizer.get_box_replacement(box)
- if setfield_op.getopnum() == rop.SETFIELD_GC:
- fieldbox = setfield_op.getarg(1)
- else:
- fieldbox = setfield_op.getarg(2)
- fieldbox = optimizer.get_box_replacement(fieldbox)
- self.register_box(box)
- self.register_box(fieldbox)
- info = optimizer.getptrinfo(fieldbox)
- assert info is not None and info.is_virtual()
- info.visitor_walk_recursive(fieldbox, self, optimizer)
-
+ # extends liveboxes!
self._number_virtuals(liveboxes, optimizer, num_virtuals)
- self._add_pending_fields(optimizer, pending_setfields)
numb_state.patch(1, len(liveboxes))
@@ -468,7 +486,7 @@
def _number_virtuals(self, liveboxes, optimizer, num_env_virtuals):
from rpython.jit.metainterp.optimizeopt.info import
AbstractVirtualPtrInfo
-
+
# !! 'liveboxes' is a list that is extend()ed in-place !!
memo = self.memo
new_liveboxes = [None] * memo.num_cached_boxes()
@@ -532,45 +550,6 @@
return True
return False
- def _add_pending_fields(self, optimizer, pending_setfields):
- rd_pendingfields = lltype.nullptr(PENDINGFIELDSP.TO)
- if pending_setfields:
- n = len(pending_setfields)
- rd_pendingfields = lltype.malloc(PENDINGFIELDSP.TO, n)
- for i in range(n):
- op = pending_setfields[i]
- box = optimizer.get_box_replacement(op.getarg(0))
- descr = op.getdescr()
- opnum = op.getopnum()
- if opnum == rop.SETARRAYITEM_GC:
- fieldbox = op.getarg(2)
- boxindex = optimizer.get_box_replacement(op.getarg(1))
- itemindex = boxindex.getint()
- # sanity: it's impossible to run code with SETARRAYITEM_GC
- # with negative index, so this guard cannot ever fail;
- # but it's possible to try to *build* such invalid code
- if itemindex < 0:
- raise TagOverflow
- elif opnum == rop.SETFIELD_GC:
- fieldbox = op.getarg(1)
- itemindex = -1
- else:
- raise AssertionError
- fieldbox = optimizer.get_box_replacement(fieldbox)
- #descr, box, fieldbox, itemindex = pending_setfields[i]
- lldescr = annlowlevel.cast_instance_to_base_ptr(descr)
- num = rffi.r_short(self._gettagged(box))
- fieldnum = rffi.r_short(self._gettagged(fieldbox))
- # the index is limited to 2147483647 (64-bit machines only)
- if itemindex > 2147483647:
- raise TagOverflow
- #
- rd_pendingfields[i].lldescr = lldescr
- rd_pendingfields[i].num = num
- rd_pendingfields[i].fieldnum = fieldnum
- rd_pendingfields[i].itemindex = rffi.cast(rffi.INT, itemindex)
- self.storage.rd_pendingfields = rd_pendingfields
-
def _gettagged(self, box):
if box is None:
return UNINITIALIZED
@@ -926,17 +905,18 @@
virtual_int_default = None
- def _init(self, cpu, storage):
- self.cpu = cpu
+ def _init(self, metainterp_sd, storage):
+ self.metainterp_sd = metainterp_sd
+ self.cpu = metainterp_sd.cpu
self.resumecodereader = resumecode.Reader(storage.rd_numb)
- count = self.resumecodereader.next_item()
- self.items_resume_section = count
+ items_resume_section = self.resumecodereader.next_item()
+ self.items_resume_section = items_resume_section
self.count = self.resumecodereader.next_item()
self.consts = storage.rd_consts
def _prepare(self, storage):
self._prepare_virtuals(storage.rd_virtuals)
- self._prepare_pendingfields(storage.rd_pendingfields)
+ self._prepare_pendingfields()
def read_jitcode_pos_pc(self):
jitcode_pos = self.resumecodereader.next_item()
@@ -1003,21 +983,23 @@
self.virtuals_cache = self.VirtualCache([self.virtual_ptr_default]
* len(virtuals),
[self.virtual_int_default]
* len(virtuals))
- def _prepare_pendingfields(self, pendingfields):
- if pendingfields:
- for i in range(len(pendingfields)):
- lldescr = pendingfields[i].lldescr
- num = pendingfields[i].num
- fieldnum = pendingfields[i].fieldnum
- itemindex = pendingfields[i].itemindex
- descr = annlowlevel.cast_base_ptr_to_instance(AbstractDescr,
- lldescr)
- struct = self.decode_ref(num)
- itemindex = rffi.cast(lltype.Signed, itemindex)
- if itemindex < 0:
- self.setfield(struct, fieldnum, descr)
- else:
- self.setarrayitem(struct, itemindex, fieldnum, descr)
+ def _prepare_pendingfields(self):
+ metainterp_sd = self.metainterp_sd
+ for i in range(self.resumecodereader.next_item()):
+ num = self.resumecodereader.next_item()
+ struct = self.decode_ref(num)
+ descrindex = self.resumecodereader.next_item()
+ descr = metainterp_sd.all_descrs[descrindex]
+ fieldnum = self.resumecodereader.next_item()
+ self.setfield(struct, fieldnum, descr)
+ for i in range(self.resumecodereader.next_item()):
+ num = self.resumecodereader.next_item()
+ struct = self.decode_ref(num)
+ descrindex = self.resumecodereader.next_item()
+ descr = metainterp_sd.all_descrs[descrindex]
+ index = self.resumecodereader.next_item()
+ fieldnum = self.resumecodereader.next_item()
+ self.setarrayitem(struct, index, fieldnum, descr)
def setarrayitem(self, array, index, fieldnum, arraydescr):
if arraydescr.is_array_of_pointers():
@@ -1072,7 +1054,7 @@
VirtualCache = get_VirtualCache_class('BoxReader')
def __init__(self, storage, deadframe, metainterp):
- self._init(metainterp.cpu, storage)
+ self._init(metainterp.staticdata, storage)
self.deadframe = deadframe
self.metainterp = metainterp
self.liveboxes = [None] * self.count
@@ -1363,7 +1345,7 @@
# 2: resuming from the GUARD_NOT_FORCED
def __init__(self, metainterp_sd, storage, deadframe, all_virtuals=None):
- self._init(metainterp_sd.cpu, storage)
+ self._init(metainterp_sd, storage)
self.deadframe = deadframe
self.callinfocollection = metainterp_sd.callinfocollection
if all_virtuals is None: # common case
@@ -1376,6 +1358,12 @@
# self.rd_virtuals can remain None, because virtuals_cache is
# already filled
+ # skip over the resume code section that does pending field writes
+ num_field_writes = self.resumecodereader.next_item()
+ assert num_field_writes == 0
+ num_array_writes = self.resumecodereader.next_item()
+ assert num_array_writes == 0
+
def handling_async_forcing(self):
self.resume_after_guard_not_forced = 1
diff --git a/rpython/jit/metainterp/resumecode.py
b/rpython/jit/metainterp/resumecode.py
--- a/rpython/jit/metainterp/resumecode.py
+++ b/rpython/jit/metainterp/resumecode.py
@@ -3,6 +3,8 @@
# ----- resume section
[total size of resume section, unencoded]
[number of failargs]
+ [<length> (<numb> <descr> <numb>] setfields
+ [<length> (<numb> <descr> <index> <numb>] setarrayitems
[<length> <virtualizable object> <numb> <numb> <numb>] if vinfo is not
None
-OR-
[1 <ginfo object>] if ginfo is not
None
diff --git a/rpython/jit/metainterp/test/test_resume.py
b/rpython/jit/metainterp/test/test_resume.py
--- a/rpython/jit/metainterp/test/test_resume.py
+++ b/rpython/jit/metainterp/test/test_resume.py
@@ -10,9 +10,9 @@
VArrayInfoNotClear, VStrPlainInfo, VStrConcatInfo, VStrSliceInfo,\
VUniPlainInfo, VUniConcatInfo, VUniSliceInfo,\
capture_resumedata, ResumeDataLoopMemo, UNASSIGNEDVIRTUAL, INT,\
- annlowlevel, PENDINGFIELDSP, TAG_CONST_OFFSET
+ annlowlevel, TAG_CONST_OFFSET, NumberingState
from rpython.jit.metainterp.resumecode import unpack_numbering,\
- create_numbering, NULL_NUMBER
+ create_numbering, NULL_NUMBER, Reader
from rpython.jit.metainterp.opencoder import Trace, Snapshot, TopSnapshot
from rpython.jit.metainterp.optimizeopt import info
@@ -35,7 +35,6 @@
rd_numb = None
rd_consts = []
rd_virtuals = None
- rd_pendingfields = None
class FakeOptimizer(object):
@@ -97,14 +96,6 @@
debug_print('\t\t', 'None')
else:
virtual.debug_prints()
- if storage.rd_pendingfields:
- debug_print('\tpending setfields')
- for i in range(len(storage.rd_pendingfields)):
- lldescr = storage.rd_pendingfields[i].lldescr
- num = storage.rd_pendingfields[i].num
- fieldnum = storage.rd_pendingfields[i].fieldnum
- itemindex = storage.rd_pendingfields[i].itemindex
- debug_print("\t\t", str(lldescr), str(untag(num)),
str(untag(fieldnum)), itemindex)
debug_stop("jit-resume")
@@ -171,6 +162,12 @@
else:
assert op.type == 'v'
+class FakeStaticData(object):
+ def __init__(self, cpu):
+ self.cpu = cpu
+ if hasattr(cpu, 'setup_descrs'):
+ self.all_descrs = cpu.setup_descrs()
+
class MyMetaInterp:
_already_allocated_resume_virtuals = None
callinfocollection = None
@@ -179,6 +176,7 @@
if cpu is None:
cpu = LLtypeMixin.cpu
self.cpu = cpu
+ self.staticdata = FakeStaticData(cpu)
self.trace = []
self.framestack = []
@@ -301,7 +299,7 @@
c1, c2, c3 = [ConstInt(111), ConstInt(222), ConstInt(333)]
storage = Storage()
storage.rd_consts = [c1, c2, c3]
- numb = Numbering([3, tag(0, TAGBOX), tagconst(0),
+ numb = Numbering([3, 0, 0, tag(0, TAGBOX), tagconst(0),
NULLREF, tag(0, TAGBOX), tag(1, TAGBOX)] +
[tagconst(1), tagconst(2)] +
[tag(0, TAGBOX), tag(1, TAGBOX), tag(2, TAGBOX)])
@@ -346,7 +344,7 @@
def test_simple_read_tagged_ints():
storage = Storage()
storage.rd_consts = []
- numb = Numbering([1, tag(100, TAGINT)])
+ numb = Numbering([1, 0, 0, tag(100, TAGINT)])
storage.rd_numb = numb
#
cpu = MyCPU([])
@@ -363,9 +361,8 @@
return s
class FakeStorage(object):
rd_virtuals = [FakeVinfo(), None]
- rd_numb = Numbering([1])
+ rd_numb = Numbering([1, 0, 0])
rd_consts = []
- rd_pendingfields = None
class FakeMetainterp(object):
_already_allocated_resume_virtuals = None
cpu = None
@@ -858,7 +855,7 @@
base = [0, 0, tag(0, TAGBOX), tag(1, TAGINT),
tag(1, TAGBOX), tag(0, TAGBOX), tag(2, TAGINT)]
- assert unpack_numbering(numb) == [17, 0, 0, 0] + base + [0, 2, tag(3,
TAGINT), tag(2, TAGBOX),
+ assert unpack_numbering(numb) == [19, 0, 0, 0, 0, 0] + base + [0, 2,
tag(3, TAGINT), tag(2, TAGBOX),
tag(0, TAGBOX), tag(1, TAGINT)]
t.append(0)
snap2 = t.create_top_snapshot(FakeJitCode("jitcode", 0), 2, Frame(env2),
@@ -872,7 +869,7 @@
assert numb_state2.liveboxes == {b1: tag(0, TAGBOX), b2: tag(1, TAGBOX),
b3: tag(2, TAGBOX)}
assert numb_state2.liveboxes is not numb_state.liveboxes
- assert unpack_numbering(numb2) == [17, 0, 0, 0] + base + [0, 2, tag(3,
TAGINT), tag(2, TAGBOX),
+ assert unpack_numbering(numb2) == [19, 0, 0, 0, 0, 0] + base + [0, 2,
tag(3, TAGINT), tag(2, TAGBOX),
tag(0, TAGBOX), tag(3, TAGINT)]
t.append(0)
@@ -894,7 +891,7 @@
assert numb_state3.num_virtuals == 0
assert numb_state3.liveboxes == {b1: tag(0, TAGBOX), b2: tag(1, TAGBOX)}
- assert unpack_numbering(numb3) == ([17, 0, 0, 2, tag(3, TAGINT), tag(4,
TAGINT),
+ assert unpack_numbering(numb3) == ([19, 0, 0, 0, 0, 2, tag(3, TAGINT),
tag(4, TAGINT),
tag(0, TAGBOX), tag(3, TAGINT)] +
base + [0, 2])
@@ -911,7 +908,7 @@
assert numb_state4.liveboxes == {b1: tag(0, TAGBOX), b2: tag(1, TAGBOX),
b4: tag(0, TAGVIRTUAL)}
- assert unpack_numbering(numb4) == [17, 0, 0, 2, tag(3, TAGINT), tag(0,
TAGVIRTUAL),
+ assert unpack_numbering(numb4) == [19, 0, 0, 0, 0, 2, tag(3, TAGINT),
tag(0, TAGVIRTUAL),
tag(0, TAGBOX), tag(3, TAGINT)] + base
+ [0, 2]
t.append(0)
@@ -930,7 +927,7 @@
assert numb_state5.liveboxes == {b1: tag(0, TAGBOX), b2: tag(1, TAGBOX),
b4: tag(0, TAGVIRTUAL), b5: tag(1,
TAGVIRTUAL)}
- assert unpack_numbering(numb5) == [22, 0,
+ assert unpack_numbering(numb5) == [24, 0, 0, 0,
3, tag(0, TAGBOX), tag(0, TAGVIRTUAL), tag(1, TAGVIRTUAL),
0] + base + [
2, 1, tag(3, TAGINT), tag(0, TAGVIRTUAL), tag(0, TAGBOX), tag(3,
TAGINT)
@@ -951,15 +948,17 @@
l = unpack_numbering(numb)
assert l[0] == len(l)
assert l[1] == 0
- assert l[1] == 0
assert l[2] == 0
assert l[3] == 0
assert l[4] == 0
+ assert l[5] == 0
+ assert l[6] == 0
+ assert l[7] == 0
mapping = dict(zip(inpargs, i.inputargs))
for i, item in enumerate(lst):
- v, tag = untag(l[i + 6])
+ v, tag = untag(l[i + 8])
if tag == TAGBOX:
- assert l[i + 6] == numb_state.liveboxes[mapping[item]]
+ assert l[i + 8] == numb_state.liveboxes[mapping[item]]
elif tag == TAGCONST:
assert memo.consts[v].getint() == item.getint()
elif tag == TAGINT:
@@ -1102,7 +1101,7 @@
class ResumeDataFakeReader(ResumeDataBoxReader):
"""Another subclass of AbstractResumeDataReader meant for tests."""
def __init__(self, storage, newboxes, metainterp):
- self._init(metainterp.cpu, storage)
+ self._init(metainterp.staticdata, storage)
self.liveboxes = newboxes
self.metainterp = metainterp
self._prepare(storage)
@@ -1232,7 +1231,7 @@
liveboxes = []
modifier._number_virtuals(liveboxes, FakeOptimizer(), 0)
storage.rd_consts = memo.consts[:]
- storage.rd_numb = Numbering([0])
+ storage.rd_numb = Numbering([0, 0, 0])
# resume
b3t, b5t = [IntFrontendOp(0), RefFrontendOp(0)]
b5t.setref_base(demo55o)
@@ -1303,7 +1302,7 @@
modifier._number_virtuals(liveboxes, FakeOptimizer(), 0)
dump_storage(storage, liveboxes)
storage.rd_consts = memo.consts[:]
- storage.rd_numb = Numbering([0])
+ storage.rd_numb = Numbering([0, 0, 0])
# resume
b1t, b3t, b4t = [IntFrontendOp(0), IntFrontendOp(0), IntFrontendOp(0)]
b1t.setint(11)
@@ -1356,7 +1355,7 @@
modifier._number_virtuals(liveboxes, FakeOptimizer(), 0)
dump_storage(storage, liveboxes)
storage.rd_consts = memo.consts[:]
- storage.rd_numb = Numbering([0])
+ storage.rd_numb = Numbering([0, 0, 0])
b4t = RefFrontendOp(0)
newboxes = _resume_remap(liveboxes, [#b2s -- virtual
b4s], b4t)
@@ -1384,25 +1383,50 @@
assert ptr.b == lltype.nullptr(LLtypeMixin.NODE)
-def test_virtual_adder_pending_fields():
+def test_virtual_adder_pending_fields(monkeypatch):
+ from rpython.jit.metainterp.optimizeopt.heap import PendingWrites
+ monkeypatch.setattr(LLtypeMixin.nextdescr, "descr_index", 0)
+ metainterp_sd = FakeMetaInterpStaticData()
+ metainterp_sd.all_descrs = [LLtypeMixin.nextdescr]
b2s, b4s = [RefFrontendOp(0), RefFrontendOp(0)]
storage = Storage()
- memo = ResumeDataLoopMemo(FakeMetaInterpStaticData())
+ optimizer = FakeOptimizer()
+ optimizer.metainterp_sd = metainterp_sd
+
+ memo = ResumeDataLoopMemo(metainterp_sd)
+
modifier = ResumeDataVirtualAdder(None, storage, storage, None, memo)
- modifier.liveboxes_from_env = {}
+ # simulated call to "finish"
+ # first call number:
+ numb_state = NumberingState()
+ numb_state.append_int(0)
+ numb_state.append_int(0)
+ pendingwrites = PendingWrites([
+ ResOperation(rop.SETFIELD_GC, [b2s, b4s],
descr=LLtypeMixin.nextdescr)],
+ [])
+ memo._add_pending_writes(optimizer, pendingwrites, numb_state)
+
+ # now back in finish
+
+ modifier.liveboxes_from_env = numb_state.liveboxes
modifier.liveboxes = {}
+ liveboxes = [None] * len(modifier.liveboxes_from_env)
+ for box, tagged in modifier.liveboxes_from_env.iteritems():
+ i, tagbits = untag(tagged)
+ assert tagbits == TAGBOX
+ liveboxes[i] = box
+ assert liveboxes == [b2s, b4s]
+
modifier.vfieldboxes = {}
+ # simulate _walk_pending_write # XXX unneeded?
modifier.register_box(b2s)
modifier.register_box(b4s)
- liveboxes = []
modifier._number_virtuals(liveboxes, FakeOptimizer(), 0)
- assert liveboxes == [b2s, b4s] or liveboxes == [b4s, b2s]
- modifier._add_pending_fields(FakeOptimizer(), [
- ResOperation(rop.SETFIELD_GC, [b2s, b4s],
descr=LLtypeMixin.nextdescr)])
storage.rd_consts = memo.consts[:]
- storage.rd_numb = Numbering([0])
+ storage.rd_numb = numb_state.create_numbering()
+
# resume
demo55.next = lltype.nullptr(LLtypeMixin.NODE)
b2t = RefFrontendOp(0)
@@ -1412,6 +1436,7 @@
newboxes = _resume_remap(liveboxes, [b2s, b4s], b2t, b4t)
metainterp = MyMetaInterp()
+ metainterp.staticdata = metainterp_sd
reader = ResumeDataFakeReader(storage, newboxes, metainterp)
assert reader.virtuals_cache is None
trace = metainterp.trace
@@ -1424,125 +1449,130 @@
assert demo55.next == demo66
def test_virtual_adder_pending_fields_and_arrayitems():
- class Storage(object):
- pass
- storage = Storage()
- modifier = ResumeDataVirtualAdder(None, storage, storage, None, None)
- modifier._add_pending_fields(None, [])
- assert not storage.rd_pendingfields
+ from rpython.jit.metainterp.optimizeopt.heap import PendingWrites
+ metainterp_sd = FakeMetaInterpStaticData()
+ metainterp_sd.all_descrs = []
+ optimizer = FakeOptimizer()
+ optimizer.metainterp_sd = metainterp_sd
+
+ memo = ResumeDataLoopMemo(metainterp_sd)
+ numb_state = NumberingState()
+ memo._add_pending_writes(optimizer, None, numb_state)
+ assert numb_state.current == [0, 0]
+
#
class FieldDescr(AbstractDescr):
+ def __init__(self):
+ self.descr_index = len(metainterp_sd.all_descrs)
+ metainterp_sd.all_descrs.append(self)
+
def is_array_of_primitives(self):
return False
+
field_a = FieldDescr()
- storage = Storage()
- modifier = ResumeDataVirtualAdder(None, storage, storage, None, None)
+ memo = ResumeDataLoopMemo(metainterp_sd)
+ numb_state = NumberingState()
a = IntFrontendOp(0)
b = IntFrontendOp(0)
- modifier.liveboxes_from_env = {a: rffi.cast(rffi.SHORT, 1042),
- b: rffi.cast(rffi.SHORT, 1061)}
- modifier._add_pending_fields(FakeOptimizer(), [
+ numb_state.liveboxes = {a: 1042, b: 1061}
+ pendingwrites = PendingWrites([
ResOperation(rop.SETFIELD_GC, [a, b],
- descr=field_a)])
- pf = storage.rd_pendingfields
- assert len(pf) == 1
- assert (annlowlevel.cast_base_ptr_to_instance(FieldDescr, pf[0].lldescr)
- is field_a)
- assert rffi.cast(lltype.Signed, pf[0].num) == 1042
- assert rffi.cast(lltype.Signed, pf[0].fieldnum) == 1061
- assert rffi.cast(lltype.Signed, pf[0].itemindex) == -1
+ descr=field_a)], [])
+ memo._add_pending_writes(optimizer, pendingwrites, numb_state)
+ assert numb_state.current == [1, 1042, 0, 1061, 0]
+
#
array_a = FieldDescr()
- storage = Storage()
- modifier = ResumeDataVirtualAdder(None, storage, storage, None, None)
+ memo = ResumeDataLoopMemo(metainterp_sd)
+ numb_state = NumberingState()
a42 = IntFrontendOp(0)
a61 = IntFrontendOp(0)
a62 = IntFrontendOp(0)
a63 = IntFrontendOp(0)
- modifier.liveboxes_from_env = {a42: rffi.cast(rffi.SHORT, 1042),
- a61: rffi.cast(rffi.SHORT, 1061),
- a62: rffi.cast(rffi.SHORT, 1062),
- a63: rffi.cast(rffi.SHORT, 1063)}
- modifier._add_pending_fields(FakeOptimizer(), [
+ numb_state.liveboxes = {a42: 1042, a61: 1061, a62: 1062, a63: 1063}
+ pendingwrites = PendingWrites([],
+ [
ResOperation(rop.SETARRAYITEM_GC, [a42, ConstInt(0), a61],
descr=array_a),
- ResOperation(rop.SETARRAYITEM_GC, [a42, ConstInt(2147483647), a62],
+ ResOperation(rop.SETARRAYITEM_GC, [a42, ConstInt(2**21 - 1), a62],
descr=array_a)])
- pf = storage.rd_pendingfields
- assert len(pf) == 2
- assert (annlowlevel.cast_base_ptr_to_instance(FieldDescr, pf[0].lldescr)
- is array_a)
- assert rffi.cast(lltype.Signed, pf[0].num) == 1042
- assert rffi.cast(lltype.Signed, pf[0].fieldnum) == 1061
- assert rffi.cast(lltype.Signed, pf[0].itemindex) == 0
- assert (annlowlevel.cast_base_ptr_to_instance(FieldDescr, pf[1].lldescr)
- is array_a)
- assert rffi.cast(lltype.Signed, pf[1].num) == 1042
- assert rffi.cast(lltype.Signed, pf[1].fieldnum) == 1062
- assert rffi.cast(lltype.Signed, pf[1].itemindex) == 2147483647
+ memo._add_pending_writes(optimizer, pendingwrites, numb_state)
+ assert numb_state.current == [0, # no pending field writes
+ 2, # two pending array writes
+ 1042, 1, 0, 1061, # first write
+ 1042, 1, 2 ** 21 - 1, 1062 # second write
+ ]
#
- if sys.maxint >= 2147483648:
- py.test.raises(TagOverflow, modifier._add_pending_fields,
- FakeOptimizer(),
- [ResOperation(rop.SETARRAYITEM_GC,
- [a42, ConstInt(2147483648), a63],
- descr=array_a)])
+
+ pendingwrites = PendingWrites([],
+ [ResOperation(rop.SETARRAYITEM_GC,
+ [a42, ConstInt(2147483648), a63],
+ descr=array_a)])
+ with py.test.raises(TagOverflow):
+ memo._add_pending_writes(optimizer, pendingwrites, numb_state)
+
def test_resume_reader_fields_and_arrayitems():
+ metainterp_sd = FakeMetaInterpStaticData()
+ metainterp_sd.all_descrs = []
+
class ResumeReader(AbstractResumeDataReader):
- def __init__(self, got=None, got_array=None):
+ def __init__(self, numb, got=None, got_array=None):
+ self.resumecodereader = Reader(numb)
+ self.metainterp_sd = metainterp_sd
self.got = got
self.got_array = got_array
def setfield(self, struct, fieldnum, descr):
assert lltype.typeOf(struct) is lltype.Signed
- assert lltype.typeOf(fieldnum) is rffi.SHORT
- fieldnum = rffi.cast(lltype.Signed, fieldnum)
+ assert lltype.typeOf(fieldnum) is lltype.Signed
self.got.append((descr, struct, fieldnum))
def setarrayitem(self, array, index, fieldnum, arraydescr):
assert lltype.typeOf(array) is lltype.Signed
assert lltype.typeOf(index) is lltype.Signed
- assert lltype.typeOf(fieldnum) is rffi.SHORT
- fieldnum = rffi.cast(lltype.Signed, fieldnum)
+ assert lltype.typeOf(fieldnum) is lltype.Signed
self.got_array.append((arraydescr, array, index, fieldnum))
def decode_ref(self, num):
return rffi.cast(lltype.Signed, num) * 100
+ numb = create_numbering([0, 0])
got = []
- pf = lltype.nullptr(PENDINGFIELDSP.TO)
- ResumeReader(got)._prepare_pendingfields(pf)
+ ResumeReader(numb, got)._prepare_pendingfields()
assert got == []
#
class FieldDescr(AbstractDescr):
- pass
+ def __init__(self):
+ self.descr_index = len(metainterp_sd.all_descrs)
+ metainterp_sd.all_descrs.append(self)
field_a = FieldDescr()
field_b = FieldDescr()
- pf = lltype.malloc(PENDINGFIELDSP.TO, 2)
- pf[0].lldescr = annlowlevel.cast_instance_to_base_ptr(field_a)
- pf[0].num = rffi.cast(rffi.SHORT, 1042)
- pf[0].fieldnum = rffi.cast(rffi.SHORT, 1061)
- pf[0].itemindex = rffi.cast(rffi.INT, -1)
- pf[1].lldescr = annlowlevel.cast_instance_to_base_ptr(field_b)
- pf[1].num = rffi.cast(rffi.SHORT, 2042)
- pf[1].fieldnum = rffi.cast(rffi.SHORT, 2061)
- pf[1].itemindex = rffi.cast(rffi.INT, -1)
+ numb = create_numbering([2, # number writes
+ 1042,
+ field_a.descr_index,
+ 1061,
+ 2042,
+ field_b.descr_index,
+ 2061,
+ 0, # number array writes
+ ])
got = []
- ResumeReader(got)._prepare_pendingfields(pf)
+ ResumeReader(numb, got)._prepare_pendingfields()
assert got == [(field_a, 104200, 1061), (field_b, 204200, 2061)]
#
array_a = FieldDescr()
- pf = lltype.malloc(PENDINGFIELDSP.TO, 1)
- pf[0].lldescr = annlowlevel.cast_instance_to_base_ptr(array_a)
- pf[0].num = rffi.cast(rffi.SHORT, 1042)
- pf[0].fieldnum = rffi.cast(rffi.SHORT, 1063)
- pf[0].itemindex = rffi.cast(rffi.INT, 123)
+ numb = create_numbering([0, # number writes
+ 1, # number array writes
+ 1042,
+ array_a.descr_index,
+ 123,
+ 1063])
got_array = []
- ResumeReader(got_array=got_array)._prepare_pendingfields(pf)
+ ResumeReader(numb, got_array=got_array)._prepare_pendingfields()
assert got_array == [(array_a, 104200, 123, 1063)]
def test_invalidation_needed():
class options:
failargs_limit = 10
-
+
metainterp_sd = FakeMetaInterpStaticData()
metainterp_sd.options = options
memo = ResumeDataLoopMemo(metainterp_sd)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit