Author: fijal Branch: jit-leaner-frontend Changeset: r82993:065b7dae64ce Date: 2016-03-12 18:36 +0200 http://bitbucket.org/pypy/pypy/changeset/065b7dae64ce/
Log: hack differently 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 @@ -27,52 +27,32 @@ pass class SnapshotIterator(object): - def __init__(self, main_iter, pos, end_pos): - self.trace = main_iter.trace + def __init__(self, main_iter, snapshot): self.main_iter = main_iter - self.end = end_pos - self.start = pos - self.pos = pos - self.save_pos = -1 + # reverse the snapshots and store the vable, vref lists + assert isinstance(snapshot, TopSnapshot) + self.vable_array = snapshot.vable_array + self.vref_array = snapshot.vref_array + self.size = len(self.vable_array) + len(self.vref_array) + 2 + jc_index, pc = unpack_uint(snapshot.packed_jitcode_pc) + self.framestack = [] + if jc_index == 2**16-1: + return + while snapshot: + self.framestack.append(snapshot) + self.size += len(snapshot.box_array) + 2 + snapshot = snapshot.prev + self.framestack.reverse() - def length(self): - return self.end - self.start + def get(self, index): + return self.main_iter._untag(index) - def done(self): - return self.pos >= self.end + def unpack_jitcode_pc(self, snapshot): + return unpack_uint(snapshot.packed_jitcode_pc) - def _next(self): - res = rffi.cast(lltype.Signed, self.trace._ops[self.pos]) - self.pos += 1 - return res - - def next(self): - r = self.main_iter._untag(self._next()) - assert r - return r - - def read_boxes(self, size): - return [self.next() for i in range(size)] - - def get_size_jitcode_pc(self): - if self.save_pos >= 0: - self.pos = self.save_pos - self.save_pos = -1 - size = self._next() - if size < 0: - self.save_pos = self.pos + 1 - self.pos = ((-size - 1) << 15) | (self._next()) - assert self.pos >= 0 - size = self._next() - assert size >= 0 - return size, self._next(), self._next() - - def get_list_of_boxes(self): - size = self._next() - l = [] - for i in range(size): - l.append(self.next()) - return l + def unpack_array(self, arr): + # NOT_RPYTHON + return [self.get(i) for i in arr] class TraceIterator(BaseTrace): def __init__(self, trace, start, end, force_inputargs=None): @@ -127,14 +107,8 @@ else: assert False - def skip_resume_data(self): - pos = self.pos - self.pos += self._next() - return pos - - def get_snapshot_iter(self, pos): - end = rffi.cast(lltype.Signed, self.trace._ops[pos]) + pos - return SnapshotIterator(self, pos + 1, end) + def get_snapshot_iter(self, index): + return SnapshotIterator(self, self.trace._snapshots[index]) def next(self): opnum = self._next() @@ -147,7 +121,7 @@ args.append(self._untag(self._next())) if opwithdescr[opnum]: descr_index = self._next() - if descr_index == -1: + if descr_index == -1 or rop.is_guard(opnum): descr = None else: descr = self.trace._descrs[descr_index] @@ -156,7 +130,7 @@ res = ResOperation(opnum, args, -1, descr=descr) if rop.is_guard(opnum): assert isinstance(res, GuardResOp) - res.rd_resume_position = self.skip_resume_data() + res.rd_resume_position = descr_index self._cache[self._count] = res self._count += 1 return res @@ -174,6 +148,30 @@ iter._count = self.count return iter +def combine_uint(index1, index2): + assert 0 <= index1 < 65536 + assert 0 <= index2 < 65536 + return index1 << 16 | index2 # it's ok to return signed here, + # we need only 32bit, but 64 is ok for now + +def unpack_uint(packed): + return (packed >> 16) & 0xffff, packed & 0xffff + +class Snapshot(object): + _attrs_ = ('packed_jitcode_pc', 'box_array', 'prev') + + prev = None + + def __init__(self, packed_jitcode_pc, box_array): + self.packed_jitcode_pc = packed_jitcode_pc + self.box_array = box_array + +class TopSnapshot(Snapshot): + def __init__(self, packed_jitcode_pc, box_array, vable_array, vref_array): + Snapshot.__init__(self, packed_jitcode_pc, box_array) + self.vable_array = vable_array + self.vref_array = vref_array + class Trace(BaseTrace): def __init__(self, inputargs): self._ops = [rffi.cast(rffi.SHORT, -15)] * 30000 @@ -191,6 +189,7 @@ self._bigints_dict = {} self._floats = [] self._floats_dict = {} + self._snapshots = [] for i, inparg in enumerate(inputargs): assert isinstance(inparg, AbstractInputArg) inparg.position = -i - 1 @@ -301,32 +300,12 @@ self._count += 1 return pos - def _record_raw(self, opnum, tagged_args, tagged_descr=-1): - NOT_USED - operations = self._ops - pos = self._count - operations.append(opnum) - expected_arity = oparity[opnum] - if expected_arity == -1: - operations.append(len(tagged_args)) - else: - assert len(argboxes) == expected_arity - operations.extend(tagged_args) - if tagged_descr != -1: - operations.append(tagged_descr) - self._count += 1 - return pos - def _encode_descr(self, descr): # XXX provide a global cache for prebuilt descrs so we don't # have to repeat them here self._descrs.append(descr) return len(self._descrs) - 1 -# def record_forwarding(self, op, newtag): -# index = op._pos -# self._ops[index] = -newtag - 1 - def record_snapshot_link(self, pos): self._sharings += 1 lower = pos & 0x7fff @@ -340,40 +319,35 @@ assert opnum >= 0 return ResOperation(opnum, argboxes, pos, descr) - def record_op_tag(self, opnum, tagged_args, descr=None): - NOT_USED - return tag(TAGBOX, self._record_raw(opnum, tagged_args, descr)) + def _list_of_boxes(self, boxes): + return [rffi.cast(rffi.SHORT, self._encode(box)) for box in boxes] - def record_snapshot(self, jitcode, pc, active_boxes): - self._total_snapshots += 1 - pos = self._pos - self.append(len(active_boxes)) # unnecessary, can be read from - self.append(jitcode.index) - self.append(pc) - for box in active_boxes: - self.append(self._encode(box)) # not tagged, as it must be boxes - return pos + def create_top_snapshot(self, jitcode, pc, boxes, vable_boxes, vref_boxes): + array = self._list_of_boxes(boxes) + vable_array = self._list_of_boxes(vable_boxes) + vref_array = self._list_of_boxes(vref_boxes) + s = TopSnapshot(combine_uint(jitcode.index, pc), array, vable_array, + vref_array) + assert rffi.cast(lltype.Signed, self._ops[self._pos - 1]) == -1 + # guards have no descr + self._snapshots.append(s) + self._ops[self._pos - 1] = rffi.cast(rffi.SHORT, len(self._snapshots) - 1) + return s - def record_list_of_boxes(self, boxes): - self.append(len(boxes)) - for box in boxes: - self.append(self._encode(box)) + def create_empty_top_snapshot(self, vable_boxes, vref_boxes): + vable_array = self._list_of_boxes(vable_boxes) + vref_array = self._list_of_boxes(vref_boxes) + s = TopSnapshot(combine_uint(2**16 - 1, 0), [], vable_array, + vref_array) + assert rffi.cast(lltype.Signed, self._ops[self._pos - 1]) == -1 + # guards have no descr + self._snapshots.append(s) + self._ops[self._pos - 1] = rffi.cast(rffi.SHORT, len(self._snapshots) - 1) + return s - def get_patchable_position(self): - p = self._pos - self.append(-1) - return p - - def patch_position_to_current(self, p): - prev = self._ops[p] - assert rffi.cast(lltype.Signed, prev) == -1 - self._snapshot_lgt += self._pos - p - self._ops[p] = rffi.cast(rffi.SHORT, self._pos - p) - - def check_snapshot_jitcode_pc(self, jitcode, pc, resumedata_pos): - # XXX expensive? - assert self._ops[resumedata_pos + 1] == rffi.cast(rffi.SHORT, jitcode.index) - assert self._ops[resumedata_pos + 2] == rffi.cast(rffi.SHORT, pc) + def create_snapshot(self, jitcode, pc, boxes): + array = self._list_of_boxes(boxes) + return Snapshot(combine_uint(jitcode.index, pc), array) def get_iter(self): return TraceIterator(self, 0, self._pos) 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 @@ -70,7 +70,7 @@ self.copy_constants(self.registers_f, jitcode.constants_f, ConstFloat) self._result_argcode = 'v' # for resume.py operation - self.parent_resumedata_position = -1 + self.parent_snapshot = None # counter for unrolling inlined loops self.unroll_iterations = 1 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 @@ -20,36 +20,6 @@ # because it needs to support optimize.py which encodes virtuals with # arbitrary cycles and also to compress the information -class Snapshot(object): - __slots__ = ('prev', 'boxes') - - def __init__(self, prev, boxes): - self.prev = prev - self.boxes = boxes - -class TopSnapshot(Snapshot): - __slots__ = ('vable_boxes',) - - def __init__(self, prev, boxes, vable_boxes): - Snapshot.__init__(self, prev, boxes) - self.vable_boxes = vable_boxes - -def combine_uint(index1, index2): - assert 0 <= index1 < 65536 - assert 0 <= index2 < 65536 - return index1 << 16 | index2 # it's ok to return signed here, - # we need only 32bit, but 64 is ok for now - -def unpack_uint(packed): - return (packed >> 16) & 0xffff, packed & 0xffff - -class FrameInfo(object): - __slots__ = ('prev', 'packed_jitcode_pc') - - def __init__(self, prev, jitcode_index, pc): - self.prev = prev - self.packed_jitcode_pc = combine_uint(jitcode_index, pc) - class VectorInfo(object): """ prev: the previous VectorInfo or None @@ -112,21 +82,19 @@ self.variable, self.location) -def _ensure_parent_resumedata(framestack, n, t): +def _ensure_parent_resumedata(framestack, n, t, snapshot): if n == 0: return - _ensure_parent_resumedata(framestack, n - 1, t) target = framestack[n] back = framestack[n - 1] - if target.parent_resumedata_position != -1: - if not we_are_translated(): - t.check_snapshot_jitcode_pc(back.jitcode, back.pc, - target.parent_resumedata_position) - t.record_snapshot_link(target.parent_resumedata_position) + if target.parent_snapshot: + snapshot.prev = target.parent_snapshot return - pos = t.record_snapshot(back.jitcode, back.pc, - back.get_list_of_active_boxes(True)) - target.parent_resumedata_position = pos + s = t.create_snapshot(back.jitcode, back.pc, + back.get_list_of_active_boxes(True)) + snapshot.prev = s + _ensure_parent_resumedata(framestack, n - 1, t, s) + target.parent_snapshot = s def capture_resumedata(framestack, virtualizable_boxes, virtualref_boxes, t): n = len(framestack) - 1 @@ -137,15 +105,15 @@ else: virtualizable_boxes = [] virtualref_boxes = virtualref_boxes[:] - pos = t.get_patchable_position() - t.record_list_of_boxes(virtualizable_boxes) - t.record_list_of_boxes(virtualref_boxes) if n >= 0: top = framestack[n] - _ensure_parent_resumedata(framestack, n, t) - t.record_snapshot(top.jitcode, top.pc, - top.get_list_of_active_boxes(False)) - t.patch_position_to_current(pos) + snapshot = t.create_top_snapshot(top.jitcode, top.pc, + top.get_list_of_active_boxes(False), virtualizable_boxes, + virtualref_boxes) + _ensure_parent_resumedata(framestack, n, t,snapshot) + else: + snapshot = t.create_empty_top_snapshot( + virtualizable_boxes, virtualref_boxes) return result PENDINGFIELDSTRUCT = lltype.Struct('PendingField', @@ -198,12 +166,14 @@ class NumberingState(object): def __init__(self, size): self.liveboxes = {} - self.current = [] + self.current = [0] * size + self._pos = 0 self.n = 0 self.v = 0 def append(self, item): - self.current.append(item) + self.current[self._pos] = item + self._pos += 1 class ResumeDataLoopMemo(object): @@ -256,14 +226,14 @@ # env numbering - def _number_boxes(self, iter, length, optimizer, state): + def _number_boxes(self, iter, arr, optimizer, state): """ Number boxes from one snapshot """ n = state.n v = state.v liveboxes = state.liveboxes - for i in range(length): - box = iter.next() + for item in arr: + box = iter.get(item) box = optimizer.get_box_replacement(box) if isinstance(box, Const): @@ -291,24 +261,25 @@ def number(self, optimizer, position, trace): snapshot_iter = trace.get_snapshot_iter(position) - state = NumberingState(snapshot_iter.length()) + state = NumberingState(snapshot_iter.size) - virtualizable_length = snapshot_iter._next() + arr = snapshot_iter.vable_array - state.append(rffi.cast(rffi.SHORT, virtualizable_length)) - self._number_boxes(snapshot_iter, virtualizable_length, optimizer, state) + state.append(rffi.cast(rffi.SHORT, len(arr))) + self._number_boxes(snapshot_iter, arr, optimizer, state) - n = snapshot_iter._next() + arr = snapshot_iter.vref_array + n = len(arr) assert not (n & 1) state.append(rffi.cast(rffi.SHORT, n >> 1)) - self._number_boxes(snapshot_iter, n, optimizer, state) + self._number_boxes(snapshot_iter, arr, optimizer, state) - while not snapshot_iter.done(): - size, jitcode_index, pc = snapshot_iter.get_size_jitcode_pc() + for snapshot in snapshot_iter.framestack: + jitcode_index, pc = snapshot_iter.unpack_jitcode_pc(snapshot) state.append(rffi.cast(rffi.SHORT, jitcode_index)) state.append(rffi.cast(rffi.SHORT, pc)) - self._number_boxes(snapshot_iter, size, optimizer, state) + self._number_boxes(snapshot_iter, snapshot.box_array, optimizer, state) numb = resumecode.create_numbering(state.current) return numb, state.liveboxes, state.v @@ -454,7 +425,7 @@ # make sure that nobody attached resume data to this guard yet assert not storage.rd_numb resume_position = self.guard_op.rd_resume_position - assert resume_position > 0 + assert resume_position >= 0 # count stack depth numb, liveboxes_from_env, v = self.memo.number(optimizer, resume_position, self.optimizer.trace) diff --git a/rpython/jit/metainterp/test/strategies.py b/rpython/jit/metainterp/test/strategies.py --- a/rpython/jit/metainterp/test/strategies.py +++ b/rpython/jit/metainterp/test/strategies.py @@ -19,7 +19,7 @@ self.index = index class Frame(object): - parent_resumedata_position = -1 + parent_snapshot = None def __init__(self, jitcode, pc, boxes): self.jitcode = jitcode 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 @@ -14,7 +14,7 @@ self.index = index class FakeFrame(object): - parent_resumedata_position = -1 + parent_snapshot = None def __init__(self, pc, jitcode, boxes): self.pc = pc @@ -27,14 +27,17 @@ def unpack_snapshot(t, op, pos): op.framestack = [] si = t.get_snapshot_iter(op.rd_resume_position) - virtualizables = si.get_list_of_boxes() - vref_boxes = si.get_list_of_boxes() + virtualizables = si.get_virtualizables() + vref_boxes = si.get_vref_boxes() while not si.done(): size, jitcode, pc = si.get_size_jitcode_pc() + if jitcode == 2**16 - 1: + break boxes = [] for i in range(size): boxes.append(si.next()) op.framestack.append(FakeFrame(JitCode(jitcode), pc, boxes)) + op.framestack.reverse() op.virtualizables = virtualizables op.vref_boxes = vref_boxes @@ -99,27 +102,27 @@ (i0, i1, i2), l, iter = self.unpack(t) pos = l[0].rd_resume_position snapshot_iter = iter.get_snapshot_iter(pos) - assert snapshot_iter.get_list_of_boxes() == [] - assert snapshot_iter.get_list_of_boxes() == [] + assert snapshot_iter.get_virtualizables() == [] + assert snapshot_iter.get_vref_boxes() == [] + size, jc_index, pc = snapshot_iter.get_size_jitcode_pc() + assert size == 2 + assert jc_index == 4 + assert pc == 3 + assert [snapshot_iter.next() for i in range(2)] == [i2, i2] size, jc_index, pc = snapshot_iter.get_size_jitcode_pc() assert size == 2 assert jc_index == 2 assert pc == 1 assert [snapshot_iter.next() for i in range(2)] == [i0, i1] + pos = l[1].rd_resume_position + snapshot_iter = iter.get_snapshot_iter(pos) + assert snapshot_iter.get_virtualizables() == [] + assert snapshot_iter.get_vref_boxes() == [] size, jc_index, pc = snapshot_iter.get_size_jitcode_pc() assert size == 2 assert jc_index == 4 assert pc == 3 assert [snapshot_iter.next() for i in range(2)] == [i2, i2] - pos = l[1].rd_resume_position - snapshot_iter = iter.get_snapshot_iter(pos) - assert snapshot_iter.get_list_of_boxes() == [] - assert snapshot_iter.get_list_of_boxes() == [] - size, jc_index, pc = snapshot_iter.get_size_jitcode_pc() - assert size == 2 - assert jc_index == 2 - assert pc == 1 - assert [snapshot_iter.next() for i in range(2)] == [i0, i1] @given(lists_of_operations()) def test_random_snapshot(self, lst): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit