def _optimize_call_arrayop(self, op, source_box, dest_box, source_start_box, dest_start_box, length_box): length = self.get_constant_box(length_box) if length and length.getint() == 0: return True # 0-length arraycopy or arraymove source_info = getptrinfo(source_box) dest_info = getptrinfo(dest_box) source_start_box = self.get_constant_box(source_start_box) dest_start_box = self.get_constant_box(dest_start_box) extrainfo = op.getdescr().get_extra_info() if (source_start_box and dest_start_box and length and ((dest_info and dest_info.is_virtual()) or length.getint() <= 8) and ((source_info and source_info.is_virtual()) or length.getint() <= 8) and extrainfo.single_write_descr_array is not None): #<-sanity check source_start = source_start_box.getint() dest_start = dest_start_box.getint() arraydescr = extrainfo.single_write_descr_array if arraydescr.is_array_of_structs(): return False # not supported right now index_current = 0 index_delta = +1 index_stop = length.getint() if (source_box is dest_box and # ARRAYMOVE only source_start < dest_start): # iterate in reverse order index_current = index_stop - 1 index_delta = -1 index_stop = -1 # XXX fish fish fish while index_current != index_stop: index = index_current index_current += index_delta assert index >= 0 if source_info and source_info.is_virtual(): val = source_info.getitem(arraydescr, index + source_start) else: opnum = OpHelpers.getarrayitem_for_descr(arraydescr) newop = ResOperation( opnum, [source_box, ConstInt(index + source_start)], descr=arraydescr) self.optimizer.send_extra_operation(newop) val = newop if val is None: continue if dest_info and dest_info.is_virtual(): dest_info.setitem(arraydescr, index + dest_start, get_box_replacement(dest_box), val) else: newop = ResOperation( rop.SETARRAYITEM_GC, [dest_box, ConstInt(index + dest_start), val], descr=arraydescr) self.optimizer.send_extra_operation(newop) return True return False
def produce_short_preamble_ops(self, structbox, descr, index, optimizer, shortboxes): if self._items is None: return if index >= len(self._items): # we don't know about this item return item = self._items[index] if item is not None: op = optimizer.get_box_replacement(item) opnum = OpHelpers.getarrayitem_for_descr(descr) getarrayitem_op = ResOperation(opnum, [structbox, ConstInt(index)], descr=descr) shortboxes.add_heap_op(op, getarrayitem_op)
def produce_short_preamble_ops(self, structbox, descr, index, optimizer, shortboxes): if self._items is None: return if index >= len(self._items): # we don't know about this item return item = self._items[index] if item is not None: op = optimizer.get_box_replacement(item) opnum = OpHelpers.getarrayitem_for_descr(descr) getarrayitem_op = ResOperation( opnum, [structbox, ConstInt(index)], descr=descr) shortboxes.add_heap_op(op, getarrayitem_op)
def _optimize_CALL_ARRAYCOPY(self, op): length = self.get_constant_box(op.getarg(5)) if length and length.getint() == 0: return None # 0-length arraycopy source_info = self.getptrinfo(op.getarg(1)) dest_info = self.getptrinfo(op.getarg(2)) source_start_box = self.get_constant_box(op.getarg(3)) dest_start_box = self.get_constant_box(op.getarg(4)) extrainfo = op.getdescr().get_extra_info() if (source_start_box and dest_start_box and length and ((dest_info and dest_info.is_virtual()) or length.getint() <= 8) and ((source_info and source_info.is_virtual()) or length.getint() <= 8) and extrainfo.single_write_descr_array is not None): #<-sanity check source_start = source_start_box.getint() dest_start = dest_start_box.getint() arraydescr = extrainfo.single_write_descr_array if arraydescr.is_array_of_structs(): return self.emit(op) # not supported right now # XXX fish fish fish for index in range(length.getint()): if source_info and source_info.is_virtual(): val = source_info.getitem(arraydescr, index + source_start) else: opnum = OpHelpers.getarrayitem_for_descr(arraydescr) newop = ResOperation( opnum, [op.getarg(1), ConstInt(index + source_start)], descr=arraydescr) self.optimizer.send_extra_operation(newop) val = newop if val is None: continue if dest_info and dest_info.is_virtual(): dest_info.setitem(arraydescr, index + dest_start, self.get_box_replacement(op.getarg(2)), val) else: newop = ResOperation( rop.SETARRAYITEM_GC, [op.getarg(2), ConstInt(index + dest_start), val], descr=arraydescr) self.optimizer.send_extra_operation(newop) return None return self.emit(op)
def _optimize_CALL_ARRAYCOPY(self, op): length = self.get_constant_box(op.getarg(5)) if length and length.getint() == 0: return True # 0-length arraycopy source_info = self.getptrinfo(op.getarg(1)) dest_info = self.getptrinfo(op.getarg(2)) source_start_box = self.get_constant_box(op.getarg(3)) dest_start_box = self.get_constant_box(op.getarg(4)) extrainfo = op.getdescr().get_extra_info() if (source_start_box and dest_start_box and length and ((dest_info and dest_info.is_virtual()) or length.getint() <= 8) and ((source_info and source_info.is_virtual()) or length.getint() <= 8) and len(extrainfo.write_descrs_arrays) == 1): # <-sanity check source_start = source_start_box.getint() dest_start = dest_start_box.getint() arraydescr = extrainfo.write_descrs_arrays[0] if arraydescr.is_array_of_structs(): return False # not supported right now # XXX fish fish fish for index in range(length.getint()): if source_info and source_info.is_virtual(): val = source_info.getitem(arraydescr, index + source_start) else: opnum = OpHelpers.getarrayitem_for_descr(arraydescr) newop = ResOperation(opnum, [op.getarg(1), ConstInt(index + source_start)], descr=arraydescr) self.optimizer.send_extra_operation(newop) val = newop if val is None: continue if dest_info and dest_info.is_virtual(): dest_info.setitem(arraydescr, index + dest_start, self.get_box_replacement(op.getarg(2)), val) else: newop = ResOperation(rop.SETARRAYITEM_GC, [op.getarg(2), ConstInt(index + dest_start), val], descr=arraydescr) self.emit_operation(newop) return True return False
def patch_new_loop_to_load_virtualizable_fields(loop, jitdriver_sd, vable): # XXX merge with rewriting vinfo = jitdriver_sd.virtualizable_info extra_ops = [] inputargs = loop.inputargs vable_box = inputargs[jitdriver_sd.index_of_virtualizable] i = jitdriver_sd.num_red_args loop.inputargs = inputargs[:i] for descr in vinfo.static_field_descrs: assert i < len(inputargs) box = inputargs[i] opnum = OpHelpers.getfield_for_descr(descr) emit_op(extra_ops, ResOperation(opnum, [vable_box], descr)) box.set_forwarded(extra_ops[-1]) i += 1 arrayindex = 0 for descr in vinfo.array_field_descrs: arraylen = vinfo.get_array_length(vable, arrayindex) arrayop = ResOperation(rop.GETFIELD_GC_R, [vable_box], descr) emit_op(extra_ops, arrayop) arraydescr = vinfo.array_descrs[arrayindex] assert i + arraylen <= len(inputargs) for index in range(arraylen): opnum = OpHelpers.getarrayitem_for_descr(arraydescr) box = inputargs[i] emit_op(extra_ops, ResOperation(opnum, [arrayop, ConstInt(index)], descr=arraydescr)) i += 1 box.set_forwarded(extra_ops[-1]) arrayindex += 1 assert i == len(inputargs) for op in loop.operations: emit_op(extra_ops, op) loop.operations = extra_ops
def patch_new_loop_to_load_virtualizable_fields(loop, jitdriver_sd, vable): # XXX merge with rewriting vinfo = jitdriver_sd.virtualizable_info extra_ops = [] inputargs = loop.inputargs vable_box = inputargs[jitdriver_sd.index_of_virtualizable] i = jitdriver_sd.num_red_args loop.inputargs = inputargs[:i] for descr in vinfo.static_field_descrs: assert i < len(inputargs) box = inputargs[i] opnum = OpHelpers.getfield_for_descr(descr) emit_op(extra_ops, ResOperation(opnum, [vable_box], descr=descr)) box.set_forwarded(extra_ops[-1]) i += 1 arrayindex = 0 for descr in vinfo.array_field_descrs: arraylen = vinfo.get_array_length(vable, arrayindex) arrayop = ResOperation(rop.GETFIELD_GC_R, [vable_box], descr=descr) emit_op(extra_ops, arrayop) arraydescr = vinfo.array_descrs[arrayindex] assert i + arraylen <= len(inputargs) for index in range(arraylen): opnum = OpHelpers.getarrayitem_for_descr(arraydescr) box = inputargs[i] emit_op(extra_ops, ResOperation(opnum, [arrayop, ConstInt(index)], descr=arraydescr)) i += 1 box.set_forwarded(extra_ops[-1]) arrayindex += 1 assert i == len(inputargs) for op in loop.operations: emit_op(extra_ops, op) loop.operations = extra_ops