Author: Carl Friedrich Bolz <cfb...@gmx.de> Branch: optinfo-into-bridges Changeset: r87804:55bfa972b650 Date: 2016-10-14 15:46 +0200 http://bitbucket.org/pypy/pypy/changeset/55bfa972b650/
Log: factor out resumecode decoding into a Reader class instead of passing indexes everywhere diff --git a/rpython/jit/codewriter/jitcode.py b/rpython/jit/codewriter/jitcode.py --- a/rpython/jit/codewriter/jitcode.py +++ b/rpython/jit/codewriter/jitcode.py @@ -141,14 +141,13 @@ def get_register_index_f(self, index): return ord(self.live_f[index]) - def enumerate_vars(self, callback_i, callback_r, callback_f, spec, index): + def enumerate_vars(self, callback_i, callback_r, callback_f, spec): for i in range(self.get_register_count_i()): - index = callback_i(index, self.get_register_index_i(i)) + callback_i(self.get_register_index_i(i)) for i in range(self.get_register_count_r()): - index = callback_r(index, self.get_register_index_r(i)) + callback_r(self.get_register_index_r(i)) for i in range(self.get_register_count_f()): - index = callback_f(index, self.get_register_index_f(i)) - return index + callback_f(self.get_register_index_f(i)) enumerate_vars._annspecialcase_ = 'specialize:arg(4)' _liveness_cache = {} diff --git a/rpython/jit/metainterp/optimizeopt/bridgeopt.py b/rpython/jit/metainterp/optimizeopt/bridgeopt.py --- a/rpython/jit/metainterp/optimizeopt/bridgeopt.py +++ b/rpython/jit/metainterp/optimizeopt/bridgeopt.py @@ -1,7 +1,7 @@ """ Code to feed information from the optimizer via the resume code into the optimizer of the bridge attached to a guard. """ -from rpython.jit.metainterp.resumecode import numb_next_item, numb_next_n_items, unpack_numbering +from rpython.jit.metainterp import resumecode # XXX at the moment this is all quite ad-hoc. Could be delegated to the # different optimization passes @@ -81,6 +81,7 @@ for box1, descr, box2 in triples: index = metainterp_sd.descrs_dct.get(descr, -1) if index == -1: + # XXX XXX XXX fix length! continue # just skip it, if the descr is not encodable numb_state.append_short(tag_box(box1, liveboxes_from_env, memo)) numb_state.append_int(index) @@ -90,12 +91,13 @@ numb_state.append_int(0) def deserialize_optimizer_knowledge(optimizer, resumestorage, frontend_boxes, liveboxes): + reader = resumecode.Reader(resumestorage.rd_numb) assert len(frontend_boxes) == len(liveboxes) - numb = resumestorage.rd_numb metainterp_sd = optimizer.metainterp_sd # skip resume section - index = skip_resume_section(numb, optimizer) + startcount = reader.next_item() + reader.jump(startcount - 1) # class knowledge bitfield = 0 @@ -104,7 +106,7 @@ if box.type != "r": continue if not mask: - bitfield, index = numb_next_item(numb, index) + bitfield = reader.next_item() mask = 0b100000 class_known = bitfield & mask mask >>= 1 @@ -113,19 +115,15 @@ optimizer.make_constant_class(box, cls) # heap knowledge - length, index = numb_next_item(numb, index) + length = reader.next_item() result = [] for i in range(length): - tagged, index = numb_next_item(numb, index) + tagged = reader.next_item() box1 = decode_box(resumestorage, tagged, liveboxes, metainterp_sd.cpu) - tagged, index = numb_next_item(numb, index) + tagged = reader.next_item() descr = metainterp_sd.opcode_descrs[tagged] - tagged, index = numb_next_item(numb, index) + tagged = reader.next_item() box2 = decode_box(resumestorage, tagged, liveboxes, metainterp_sd.cpu) result.append((box1, descr, box2)) if optimizer.optheap: optimizer.optheap.deserialize_optheap(result) - -def skip_resume_section(numb, optimizer): - startcount, index = numb_next_item(numb, 0) - return numb_next_n_items(numb, startcount, 0) 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 @@ -950,12 +950,9 @@ def _init(self, cpu, storage): self.cpu = cpu - self.numb = storage.rd_numb - count, self.cur_index = resumecode.numb_next_item( - self.numb, 0) - # XXX inefficient - self.size_resume_section = resumecode.numb_next_n_items( - self.numb, count, 0) + self.resumecodereader = resumecode.Reader(storage.rd_numb) + count = self.resumecodereader.next_item() + self.items_resume_section = count self.count = storage.rd_count self.consts = storage.rd_consts @@ -964,14 +961,12 @@ self._prepare_pendingfields(storage.rd_pendingfields) def read_jitcode_pos_pc(self): - jitcode_pos, self.cur_index = resumecode.numb_next_item(self.numb, - self.cur_index) - pc, self.cur_index = resumecode.numb_next_item(self.numb, - self.cur_index) + jitcode_pos = self.resumecodereader.next_item() + pc = self.resumecodereader.next_item() return jitcode_pos, pc def done_reading(self): - return self.cur_index >= self.size_resume_section + return self.resumecodereader.items_read >= self.items_resume_section def getvirtual_ptr(self, index): # Returns the index'th virtual, building it lazily if needed. @@ -1048,29 +1043,25 @@ def _prepare_next_section(self, info): # Use info.enumerate_vars(), normally dispatching to # rpython.jit.codewriter.jitcode. Some tests give a different 'info'. - self.cur_index = info.enumerate_vars(self._callback_i, - self._callback_r, - self._callback_f, - self.unique_id, # <-- annotation hack - self.cur_index) + info.enumerate_vars(self._callback_i, + self._callback_r, + self._callback_f, + self.unique_id) # <-- annotation hack - def _callback_i(self, index, register_index): - item, index = resumecode.numb_next_item(self.numb, index) + def _callback_i(self, register_index): + item = self.resumecodereader.next_item() value = self.decode_int(item) self.write_an_int(register_index, value) - return index - def _callback_r(self, index, register_index): - item, index = resumecode.numb_next_item(self.numb, index) + def _callback_r(self, register_index): + item = self.resumecodereader.next_item() value = self.decode_ref(item) self.write_a_ref(register_index, value) - return index - def _callback_f(self, index, register_index): - item, index = resumecode.numb_next_item(self.numb, index) + def _callback_f(self, register_index): + item = self.resumecodereader.next_item() value = self.decode_float(item) self.write_a_float(register_index, value) - return index # ---------- when resuming for pyjitpl.py, make boxes ---------- @@ -1109,42 +1100,33 @@ self.boxes_f = boxes_f self._prepare_next_section(info) - def consume_virtualizable_boxes(self, vinfo, index): + def consume_virtualizable_boxes(self, vinfo): # we have to ignore the initial part of 'nums' (containing vrefs), # find the virtualizable from nums[-1], and use it to know how many # boxes of which type we have to return. This does not write # anything into the virtualizable. - numb = self.numb - item, index = resumecode.numb_next_item(numb, index) + item = self.resumecodereader.next_item() virtualizablebox = self.decode_ref(item) virtualizable = vinfo.unwrap_virtualizable_box(virtualizablebox) - return vinfo.load_list_of_boxes(virtualizable, self, virtualizablebox, - numb, index) + return vinfo.load_list_of_boxes(virtualizable, self, virtualizablebox) - def consume_virtualref_boxes(self, index): + def consume_virtualref_boxes(self): # Returns a list of boxes, assumed to be all BoxPtrs. # We leave up to the caller to call vrefinfo.continue_tracing(). - size, index = resumecode.numb_next_item(self.numb, index) - if size == 0: - return [], index - lst = [] - for i in range(size * 2): - item, index = resumecode.numb_next_item(self.numb, index) - lst.append(self.decode_ref(item)) - return lst, index + size = self.resumecodereader.next_item() + return [self.decode_ref(self.resumecodereader.next_item()) + for i in range(size * 2)] def consume_vref_and_vable_boxes(self, vinfo, ginfo): - vable_size, index = resumecode.numb_next_item(self.numb, self.cur_index) + vable_size = self.resumecodereader.next_item() if vinfo is not None: - virtualizable_boxes, index = self.consume_virtualizable_boxes(vinfo, - index) + virtualizable_boxes = self.consume_virtualizable_boxes(vinfo) elif ginfo is not None: - item, index = resumecode.numb_next_item(self.numb, index) + item = self.resumecodereader.next_item() virtualizable_boxes = [self.decode_ref(item)] else: virtualizable_boxes = None - virtualref_boxes, index = self.consume_virtualref_boxes(index) - self.cur_index = index + virtualref_boxes = self.consume_virtualref_boxes() return virtualizable_boxes, virtualref_boxes def allocate_with_vtable(self, descr=None): @@ -1421,30 +1403,26 @@ info = blackholeinterp.get_current_position_info() self._prepare_next_section(info) - def consume_virtualref_info(self, vrefinfo, index): + def consume_virtualref_info(self, vrefinfo): # we have to decode a list of references containing pairs # [..., virtual, vref, ...] and returns the index at the end - size, index = resumecode.numb_next_item(self.numb, index) + size = self.resumecodereader.next_item() if vrefinfo is None or size == 0: assert size == 0 - return index + return for i in range(size): - virtual_item, index = resumecode.numb_next_item( - self.numb, index) - vref_item, index = resumecode.numb_next_item( - self.numb, index) + virtual_item = self.resumecodereader.next_item() + vref_item = self.resumecodereader.next_item() virtual = self.decode_ref(virtual_item) vref = self.decode_ref(vref_item) # For each pair, we store the virtual inside the vref. vrefinfo.continue_tracing(vref, virtual) - return index - def consume_vable_info(self, vinfo, index): + def consume_vable_info(self, vinfo): # we have to ignore the initial part of 'nums' (containing vrefs), # find the virtualizable from nums[-1], load all other values # from the CPU stack, and copy them into the virtualizable - numb = self.numb - item, index = resumecode.numb_next_item(self.numb, index) + item = self.resumecodereader.next_item() virtualizable = self.decode_ref(item) # just reset the token, we'll force it later vinfo.reset_token_gcref(virtualizable) @@ -1467,18 +1445,17 @@ load_value_of_type._annspecialcase_ = 'specialize:arg(1)' def consume_vref_and_vable(self, vrefinfo, vinfo, ginfo): - vable_size, index = resumecode.numb_next_item(self.numb, self.cur_index) + vable_size = self.resumecodereader.next_item() if self.resume_after_guard_not_forced != 2: if vinfo is not None: - index = self.consume_vable_info(vinfo, index) + self.consume_vable_info(vinfo) if ginfo is not None: - _, index = resumecode.numb_next_item(self.numb, index) - index = self.consume_virtualref_info(vrefinfo, index) + _ = self.resumecodereader.next_item() + self.consume_virtualref_info(vrefinfo) else: - index = resumecode.numb_next_n_items(self.numb, vable_size, index) - vref_size, index = resumecode.numb_next_item(self.numb, index) - index = resumecode.numb_next_n_items(self.numb, vref_size * 2, index) - self.cur_index = index + self.resumecodereader.jump(vable_size) + vref_size = self.resumecodereader.next_item() + self.resumecodereader.jump(vref_size * 2) def allocate_with_vtable(self, descr=None): from rpython.jit.metainterp.executor import exec_new_with_vtable 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 @@ -86,3 +86,30 @@ next, i = numb_next_item(numb, i) l.append(next) return l + +class Reader(object): + def __init__(self, code): + self.code = code + self.cur_pos = 0 # index into the code + self.items_read = 0 # number of items read + + def next_item(self): + result, self.cur_pos = numb_next_item(self.code, self.cur_pos) + self.items_read += 1 + return result + + def peek(self): + result, _ = numb_next_item(self.code, self.cur_pos) + return result + + def jump(self, size): + """ jump n items forward without returning anything """ + index = self.cur_pos + for i in range(size): + _, index = numb_next_item(self.code, index) + self.items_read += size + self.cur_pos = index + + def unpack(self): + # mainly for debugging + return unpack_numbering(self.code) 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 @@ -254,18 +254,17 @@ def get_current_position_info(self): class MyInfo: @staticmethod - def enumerate_vars(callback_i, callback_r, callback_f, _, index): + def enumerate_vars(callback_i, callback_r, callback_f, _): count_i = count_r = count_f = 0 for ARG in self.ARGS: if ARG == lltype.Signed: - index = callback_i(index, count_i); count_i += 1 + callback_i(count_i); count_i += 1 elif ARG == llmemory.GCREF: - index = callback_r(index, count_r); count_r += 1 + callback_r(count_r); count_r += 1 elif ARG == longlong.FLOATSTORAGE: - index = callback_f(index, count_f); count_f += 1 + callback_f(count_f); count_f += 1 else: assert 0 - return index return MyInfo() def setarg_i(self, index, value): @@ -1074,11 +1073,11 @@ cpu = MyCPU([]) reader = ResumeDataDirectReader(MyMetaInterp(cpu), storage, "deadframe") reader.consume_vref_and_vable(None, None, None) - reader.cur_index += 2 # framestack + reader.resumecodereader.jump(2) # framestack _next_section(reader, sys.maxint, 1, sys.maxint, 2**16) - reader.cur_index += 2 # framestack + reader.resumecodereader.jump(2) # framestack _next_section(reader, 2, 3) - reader.cur_index += 2 # framestack + reader.resumecodereader.jump(2) # framestack _next_section(reader, sys.maxint, 2**16, -65) def test_virtual_adder_memo_const_sharing(): @@ -1117,9 +1116,10 @@ return True class MyInfo: @staticmethod - def enumerate_vars(callback_i, callback_r, callback_f, _, index): - while index < max_index: - tagged, _ = resumecode.numb_next_item(self.numb, index) + def enumerate_vars(callback_i, callback_r, callback_f, _): + index = 0 + while not self.done_reading(): + tagged = self.resumecodereader.peek() _, tag = untag(tagged) if tag == TAGVIRTUAL: kind = REF @@ -1127,22 +1127,21 @@ kind = Whatever() box = self.decode_box(tagged, kind) if box.type == INT: - index = callback_i(index, index) + callback_i(index) elif box.type == REF: - index = callback_r(index, index) + callback_r(index) elif box.type == FLOAT: - index = callback_f(index, index) + callback_f(index) else: assert 0 + index += 1 - size_section, self.cur_index = resumecode.numb_next_item(self.numb, 0) - max_index = resumecode.numb_next_n_items(self.numb, size_section, 0) - size, self.cur_index = resumecode.numb_next_item(self.numb, self.cur_index) + size = self.resumecodereader.next_item() assert size == 0 - size, self.cur_index = resumecode.numb_next_item(self.numb, self.cur_index) + size = self.resumecodereader.next_item() assert size == 0 - pc, self.cur_index = resumecode.numb_next_item(self.numb, self.cur_index) - jitcode_pos, self.cur_index = resumecode.numb_next_item(self.numb, self.cur_index) + pc = self.resumecodereader.next_item() + jitcode_pos = self.resumecodereader.next_item() self._prepare_next_section(MyInfo()) return self.lst diff --git a/rpython/jit/metainterp/virtualizable.py b/rpython/jit/metainterp/virtualizable.py --- a/rpython/jit/metainterp/virtualizable.py +++ b/rpython/jit/metainterp/virtualizable.py @@ -144,7 +144,7 @@ setarrayitem(lst, j, x) return index - def load_list_of_boxes(virtualizable, reader, vable_box, numb, index): + def load_list_of_boxes(virtualizable, reader, vable_box): virtualizable = cast_gcref_to_vtype(virtualizable) # Uses 'virtualizable' only to know the length of the arrays; # does not write anything into it. The returned list is in @@ -152,13 +152,13 @@ # the virtualizable itself. boxes = [] for FIELDTYPE, fieldname in unroll_static_fields: - item, index = numb_next_item(numb, index) + item = reader.resumecodereader.next_item() box = reader.decode_box_of_type(FIELDTYPE, item) boxes.append(box) for ARRAYITEMTYPE, fieldname in unroll_array_fields: lst = getattr(virtualizable, fieldname) for j in range(getlength(lst)): - item, index = numb_next_item(numb, index) + item = reader.resumecodereader.next_item() box = reader.decode_box_of_type(ARRAYITEMTYPE, item) boxes.append(box) boxes.append(vable_box) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit