def handle_setarrayitem(self, op): itemsize, basesize, _ = unpack_arraydescr(op.getdescr()) ptr_box = op.getarg(0) index_box = op.getarg(1) value_box = op.getarg(2) self.emit_gc_store_or_indexed(op, ptr_box, index_box, value_box, itemsize, itemsize, basesize)
def handle_call_assembler(self, op): descrs = self.gc_ll_descr.getframedescrs(self.cpu) loop_token = op.getdescr() assert isinstance(loop_token, history.JitCellToken) jfi = loop_token.compiled_loop_token.frame_info llfi = heaptracker.adr2int(llmemory.cast_ptr_to_adr(jfi)) frame = self.gen_malloc_frame(llfi) self.emit_setfield(frame, history.ConstInt(llfi), descr=descrs.jf_frame_info) arglist = op.getarglist() index_list = loop_token.compiled_loop_token._ll_initial_locs for i, arg in enumerate(arglist): descr = self.cpu.getarraydescr_for_frame(arg.type) assert self.cpu.JITFRAME_FIXED_SIZE & 1 == 0 _, itemsize, _ = self.cpu.unpack_arraydescr_size(descr) array_offset = index_list[i] # index, already measured in bytes # emit GC_STORE _, basesize, _ = unpack_arraydescr(descr) offset = basesize + array_offset args = [frame, ConstInt(offset), arg, ConstInt(itemsize)] self.emit_op(ResOperation(rop.GC_STORE, args)) descr = op.getdescr() assert isinstance(descr, JitCellToken) jd = descr.outermost_jitdriver_sd args = [frame] if jd and jd.index_of_virtualizable >= 0: args = [frame, arglist[jd.index_of_virtualizable]] else: args = [frame] call_asm = ResOperation(op.getopnum(), args, descr=op.getdescr()) self.replace_op_with(self.get_box_replacement(op), call_asm) self.emit_op(call_asm)
def handle_call_assembler(self, op): descrs = self.gc_ll_descr.getframedescrs(self.cpu) loop_token = op.getdescr() assert isinstance(loop_token, history.JitCellToken) jfi = loop_token.compiled_loop_token.frame_info llfi = heaptracker.adr2int(llmemory.cast_ptr_to_adr(jfi)) frame = self.gen_malloc_frame(llfi) self.emit_setfield(frame, history.ConstInt(llfi), descr=descrs.jf_frame_info) arglist = op.getarglist() index_list = loop_token.compiled_loop_token._ll_initial_locs for i, arg in enumerate(arglist): descr = self.cpu.getarraydescr_for_frame(arg.type) assert self.cpu.JITFRAME_FIXED_SIZE & 1 == 0 _, itemsize, _ = self.cpu.unpack_arraydescr_size(descr) array_offset = index_list[i] # index, already measured in bytes # emit GC_STORE _, basesize, _ = unpack_arraydescr(descr) offset = basesize + array_offset args = [frame, ConstInt(offset), arg, ConstInt(itemsize)] self.emit_op(ResOperation(rop.GC_STORE, args)) descr = op.getdescr() assert isinstance(descr, JitCellToken) jd = descr.outermost_jitdriver_sd args = [frame] if jd and jd.index_of_virtualizable >= 0: args = [frame, arglist[jd.index_of_virtualizable]] else: args = [frame] call_asm = ResOperation(op.getopnum(), args, descr=op.getdescr()) self.replace_op_with(self.get_box_replacement(op), call_asm) self.emit_op(call_asm)
def check_operation(self, state, pack, op): opnum = op.getopnum() descr = op.getdescr() if not we_are_translated() and not isinstance(descr, ArrayDescr): itemsize = descr.get_item_size_in_bytes() ofs = 0 else: itemsize, ofs, _ = unpack_arraydescr(op.getdescr()) args = [ op.getarg(0), op.getarg(1), op.getarg(2), ConstInt(1), ConstInt(ofs) ] if opnum in (rop.SETARRAYITEM_GC, rop.SETARRAYITEM_RAW): index_box = op.getarg(1) scale, offset, changed, emit = cpu_simplify_scale( state.cpu, index_box, itemsize, ofs) args[3] = ConstInt(scale) args[4] = ConstInt(offset) if emit: state.oplist.append(changed) args[1] = changed return args
def prepare_zero_array(self, op): itemsize, ofs, _ = unpack_arraydescr(op.getdescr()) base_loc = self.ensure_reg(op.getarg(0)) startindex_loc = self.ensure_reg_or_16bit_imm(op.getarg(1)) length_loc = self.ensure_reg_or_16bit_imm(op.getarg(2)) ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(ofs)) return [base_loc, startindex_loc, length_loc, ofs_loc, imm(itemsize)]
def handle_setarrayitem(self, op): itemsize, basesize, _ = unpack_arraydescr(op.getdescr()) ptr_box = op.getarg(0) index_box = op.getarg(1) value_box = op.getarg(2) self.emit_gc_store_or_indexed(op, ptr_box, index_box, value_box, itemsize, itemsize, basesize)
def prepare_raw_store(self, op): size, ofs, _ = unpack_arraydescr(op.getdescr()) base_loc = self.ensure_reg(op.getarg(0)) index_loc = self.ensure_reg_or_any_imm(op.getarg(1)) value_loc = self.ensure_reg(op.getarg(2)) ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(ofs)) return [base_loc, index_loc, value_loc, ofs_loc, imm(1), imm(size)]
def _prepare_raw_load(self, op): size, ofs, sign = unpack_arraydescr(op.getdescr()) base_loc = self.ensure_reg(op.getarg(0)) index_loc = self.ensure_reg_or_any_imm(op.getarg(1)) ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(ofs)) self.free_op_vars() result_loc = self.force_allocate_reg(op) return [base_loc, index_loc, result_loc, ofs_loc, imm(1), imm(size), imm(sign)]
def _consider_vec_getarrayitem(self, op): descr = op.getdescr() assert isinstance(descr, ArrayDescr) assert not descr.is_array_of_pointers() and not descr.is_array_of_structs() itemsize, ofs, _ = unpack_arraydescr(descr) integer = not (descr.is_array_of_floats() or descr.getconcrete_type() == FLOAT) aligned = False args = op.getarglist() base_loc = self.rm.make_sure_var_in_reg(op.getarg(0), args) ofs_loc = self.rm.make_sure_var_in_reg(op.getarg(1), args) result_loc = self.force_allocate_reg(op) self.perform(op, [base_loc, ofs_loc, imm(itemsize), imm(ofs), imm(integer), imm(aligned)], result_loc)
def prepare_zero_array(self, op): # args: base, start, len, scale_start, scale_len itemsize, ofs, _ = unpack_arraydescr(op.getdescr()) startindex_loc = self.ensure_reg_or_16bit_imm(op.getarg(1)) ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(ofs)) base_loc, length_loc = self.rm.ensure_even_odd_pair(op.getarg(0), None, bind_first=True, must_exist=False, load_loc_odd=False) length_box = op.getarg(2) ll = self.rm.loc(length_box) if length_loc is not ll: self.assembler.regalloc_mov(ll, length_loc) return [base_loc, startindex_loc, length_loc, ofs_loc, imm(itemsize)]
def prepare_zero_array(self, op): _, ofs, _ = unpack_arraydescr(op.getdescr()) base_loc = self.ensure_reg(op.getarg(0)) startindex_loc = self.ensure_reg_or_16bit_imm(op.getarg(1)) length_loc = self.ensure_reg_or_16bit_imm(op.getarg(2)) # startindex and length are bytes, not array items anymore. # rewrite already applied the scale! startindex_scale_box = op.getarg(3) assert startindex_scale_box.getint() == 1 length_scale_box = op.getarg(4) assert length_scale_box.getint() == 1 # ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(ofs)) return [base_loc, startindex_loc, length_loc, ofs_loc]
def prepare_zero_array(self, op): _, ofs, _ = unpack_arraydescr(op.getdescr()) base_loc = self.ensure_reg(op.getarg(0)) startindex_loc = self.ensure_reg_or_16bit_imm(op.getarg(1)) length_loc = self.ensure_reg_or_16bit_imm(op.getarg(2)) # startindex and length are bytes, not array items anymore. # rewrite already applied the scale! startindex_scale_box = op.getarg(3) assert startindex_scale_box.getint() == 1 length_scale_box = op.getarg(4) assert length_scale_box.getint() == 1 # ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(ofs)) return [base_loc, startindex_loc, length_loc, ofs_loc]
def _consider_vec_getarrayitem(self, op): descr = op.getdescr() assert isinstance(descr, ArrayDescr) assert not descr.is_array_of_pointers() and \ not descr.is_array_of_structs() itemsize, ofs, _ = unpack_arraydescr(descr) integer = not (descr.is_array_of_floats() or descr.getconcrete_type() == FLOAT) aligned = False args = op.getarglist() base_loc = self.rm.make_sure_var_in_reg(op.getarg(0), args) ofs_loc = self.rm.make_sure_var_in_reg(op.getarg(1), args) result_loc = self.force_allocate_reg(op) self.perform(op, [base_loc, ofs_loc, imm(itemsize), imm(ofs), imm(integer), imm(aligned)], result_loc)
def _prepare_load(self, op): descr = op.getdescr() assert isinstance(descr, ArrayDescr) assert not descr.is_array_of_pointers() and \ not descr.is_array_of_structs() itemsize, ofs, _ = unpack_arraydescr(descr) integer = not (descr.is_array_of_floats() or descr.getconcrete_type() == FLOAT) a0 = op.getarg(0) a1 = op.getarg(1) base_loc = self.ensure_reg(a0) ofs_loc = self.ensure_reg(a1) result_loc = self.force_allocate_vector_reg(op) return [result_loc, base_loc, ofs_loc, imm(itemsize), imm(ofs), imm(integer)]
def prepare_vec_store(self, op): descr = op.getdescr() assert isinstance(descr, ArrayDescr) assert not descr.is_array_of_pointers() and \ not descr.is_array_of_structs() itemsize, ofs, _ = unpack_arraydescr(descr) a0 = op.getarg(0) a1 = op.getarg(1) a2 = op.getarg(2) baseloc = self.ensure_reg(a0) ofsloc = self.ensure_reg(a1) valueloc = self.ensure_vector_reg(a2) integer = not (descr.is_array_of_floats() or descr.getconcrete_type() == FLOAT) return [baseloc, ofsloc, valueloc, imm(itemsize), imm(ofs), imm(integer)]
def prepare_zero_array(self, op): # args: base, start, len, scale_start, scale_len itemsize, ofs, _ = unpack_arraydescr(op.getdescr()) startindex_loc = self.ensure_reg_or_16bit_imm(op.getarg(1)) ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(ofs)) base_loc, length_loc = self.rm.ensure_even_odd_pair(op.getarg(0), None, bind_first=True, must_exist=False, load_loc_odd=False) length_box = op.getarg(2) ll = self.rm.loc(length_box) if length_loc is not ll: self.assembler.regalloc_mov(ll, length_loc) return [base_loc, startindex_loc, length_loc, ofs_loc, imm(itemsize)]
def consider_vec_store(self, op): # TODO descr = op.getdescr() assert isinstance(descr, ArrayDescr) assert not descr.is_array_of_pointers() and \ not descr.is_array_of_structs() itemsize, _, _ = unpack_arraydescr(descr) args = op.getarglist() base_loc = self.rm.make_sure_var_in_reg(op.getarg(0), args) value_loc = self.make_sure_var_in_reg(op.getarg(2), args) ofs_loc = self.rm.make_sure_var_in_reg(op.getarg(1), args) scale = get_scale(op.getarg(3).getint()) ofs = op.getarg(4).getint() integer = not (descr.is_array_of_floats() or \ descr.getconcrete_type() == FLOAT) self.perform_discard(op, [base_loc, ofs_loc, value_loc, imm(itemsize), imm(scale), imm(ofs), imm(integer)])
def check_operation(self, state, pack, op): opnum = op.getopnum() descr = op.getdescr() if not we_are_translated() and not isinstance(descr, ArrayDescr): itemsize = descr.get_item_size_in_bytes() ofs = 0 else: itemsize, ofs, _ = unpack_arraydescr(op.getdescr()) args = [op.getarg(0), op.getarg(1), op.getarg(2), ConstInt(1), ConstInt(ofs)] if opnum in (rop.SETARRAYITEM_GC, rop.SETARRAYITEM_RAW): index_box = op.getarg(1) scale, offset, changed, emit = cpu_simplify_scale(state.cpu, index_box, itemsize, ofs) args[3] = ConstInt(scale) args[4] = ConstInt(offset) if emit: state.oplist.append(changed) args[1] = changed return args
def consider_vec_store(self, op): # TODO descr = op.getdescr() assert isinstance(descr, ArrayDescr) assert not descr.is_array_of_pointers() and \ not descr.is_array_of_structs() itemsize, _, _ = unpack_arraydescr(descr) args = op.getarglist() base_loc = self.rm.make_sure_var_in_reg(op.getarg(0), args) value_loc = self.make_sure_var_in_reg(op.getarg(2), args) ofs_loc = self.rm.make_sure_var_in_reg(op.getarg(1), args) scale = get_scale(op.getarg(3).getint()) ofs = op.getarg(4).getint() integer = not (descr.is_array_of_floats() or \ descr.getconcrete_type() == FLOAT) self.perform_discard(op, [base_loc, ofs_loc, value_loc, imm(itemsize), imm(scale), imm(ofs), imm(integer)])
def _rewrite_changeable_constptrs(self, op, ops_with_movable_const_ptr, moving_obj_tracker): newops = [] for arg_i in ops_with_movable_const_ptr[op]: v = op.getarg(arg_i) # assert to make sure we got what we expected assert isinstance(v, ConstPtr) array_index = moving_obj_tracker.get_array_index(v) size, offset, _ = unpack_arraydescr(moving_obj_tracker.ptr_array_descr) array_index = array_index * size + offset args = [moving_obj_tracker.const_ptr_gcref_array, ConstInt(array_index), ConstInt(size)] load_op = ResOperation(rop.GC_LOAD_R, args) newops.append(load_op) op.setarg(arg_i, load_op) # newops.append(op) return newops
def _prepare_load(self, op): descr = op.getdescr() assert isinstance(descr, ArrayDescr) assert not descr.is_array_of_pointers() and \ not descr.is_array_of_structs() itemsize, ofs, _ = unpack_arraydescr(descr) integer = not (descr.is_array_of_floats() or descr.getconcrete_type() == FLOAT) a0 = op.getarg(0) a1 = op.getarg(1) base_loc = self.ensure_reg(a0) ofs_loc = self.ensure_reg(a1) result_loc = self.force_allocate_vector_reg(op) return [ result_loc, base_loc, ofs_loc, imm(itemsize), imm(ofs), imm(integer) ]
def prepare_vec_store(self, op): descr = op.getdescr() assert isinstance(descr, ArrayDescr) assert not descr.is_array_of_pointers() and \ not descr.is_array_of_structs() itemsize, ofs, _ = unpack_arraydescr(descr) a0 = op.getarg(0) a1 = op.getarg(1) a2 = op.getarg(2) baseloc = self.ensure_reg(a0) ofsloc = self.ensure_reg(a1) valueloc = self.ensure_vector_reg(a2) integer = not (descr.is_array_of_floats() or descr.getconcrete_type() == FLOAT) return [ baseloc, ofsloc, valueloc, imm(itemsize), imm(ofs), imm(integer) ]
def transform_to_gc_load(self, op): NOT_SIGNED = 0 CINT_ZERO = ConstInt(0) opnum = op.getopnum() if rop.is_getarrayitem(opnum) or \ opnum in (rop.GETARRAYITEM_RAW_I, rop.GETARRAYITEM_RAW_F): self.handle_getarrayitem(op) elif opnum in (rop.SETARRAYITEM_GC, rop.SETARRAYITEM_RAW): self.handle_setarrayitem(op) elif opnum == rop.RAW_STORE: itemsize, ofs, _ = unpack_arraydescr(op.getdescr()) ptr_box = op.getarg(0) index_box = op.getarg(1) value_box = op.getarg(2) self.emit_gc_store_or_indexed(op, ptr_box, index_box, value_box, itemsize, 1, ofs) elif opnum in (rop.RAW_LOAD_I, rop.RAW_LOAD_F): itemsize, ofs, sign = unpack_arraydescr(op.getdescr()) ptr_box = op.getarg(0) index_box = op.getarg(1) self.emit_gc_load_or_indexed(op, ptr_box, index_box, itemsize, 1, ofs, sign) elif opnum in (rop.GETINTERIORFIELD_GC_I, rop.GETINTERIORFIELD_GC_R, rop.GETINTERIORFIELD_GC_F): ofs, itemsize, fieldsize, sign = unpack_interiorfielddescr( op.getdescr()) ptr_box = op.getarg(0) index_box = op.getarg(1) self.emit_gc_load_or_indexed(op, ptr_box, index_box, fieldsize, itemsize, ofs, sign) elif opnum in (rop.SETINTERIORFIELD_RAW, rop.SETINTERIORFIELD_GC): ofs, itemsize, fieldsize, sign = unpack_interiorfielddescr( op.getdescr()) ptr_box = op.getarg(0) index_box = op.getarg(1) value_box = op.getarg(2) self.emit_gc_store_or_indexed(op, ptr_box, index_box, value_box, fieldsize, itemsize, ofs) elif opnum in (rop.GETFIELD_GC_I, rop.GETFIELD_GC_F, rop.GETFIELD_GC_R, rop.GETFIELD_RAW_I, rop.GETFIELD_RAW_F, rop.GETFIELD_RAW_R): ofs, itemsize, sign = unpack_fielddescr(op.getdescr()) ptr_box = op.getarg(0) if op.getopnum() in (rop.GETFIELD_GC_F, rop.GETFIELD_GC_I, rop.GETFIELD_GC_R): # See test_zero_ptr_field_before_getfield(). We hope there is # no getfield_gc in the middle of initialization code, but there # shouldn't be, given that a 'new' is already delayed by previous # optimization steps. In practice it should immediately be # followed by a bunch of 'setfields', and the 'pending_zeros' # optimization we do here is meant for this case. self.emit_pending_zeros() self.emit_gc_load_or_indexed(op, ptr_box, ConstInt(0), itemsize, 1, ofs, sign) self.emit_op(op) return True self.emit_gc_load_or_indexed(op, ptr_box, ConstInt(0), itemsize, 1, ofs, sign) elif opnum in (rop.SETFIELD_GC, rop.SETFIELD_RAW): ofs, itemsize, sign = unpack_fielddescr(op.getdescr()) ptr_box = op.getarg(0) value_box = op.getarg(1) self.emit_gc_store_or_indexed(op, ptr_box, ConstInt(0), value_box, itemsize, 1, ofs) elif opnum == rop.ARRAYLEN_GC: descr = op.getdescr() assert isinstance(descr, ArrayDescr) ofs = descr.lendescr.offset self.emit_gc_load_or_indexed(op, op.getarg(0), ConstInt(0), WORD, 1, ofs, NOT_SIGNED) elif opnum == rop.STRLEN: basesize, itemsize, ofs_length = get_array_token( rstr.STR, self.cpu.translate_support_code) self.emit_gc_load_or_indexed(op, op.getarg(0), ConstInt(0), WORD, 1, ofs_length, NOT_SIGNED) elif opnum == rop.UNICODELEN: basesize, itemsize, ofs_length = get_array_token( rstr.UNICODE, self.cpu.translate_support_code) self.emit_gc_load_or_indexed(op, op.getarg(0), ConstInt(0), WORD, 1, ofs_length, NOT_SIGNED) elif opnum == rop.STRHASH: offset, size = get_field_token(rstr.STR, 'hash', self.cpu.translate_support_code) assert size == WORD self.emit_gc_load_or_indexed(op, op.getarg(0), ConstInt(0), WORD, 1, offset, sign=True) elif opnum == rop.UNICODEHASH: offset, size = get_field_token(rstr.UNICODE, 'hash', self.cpu.translate_support_code) assert size == WORD self.emit_gc_load_or_indexed(op, op.getarg(0), ConstInt(0), WORD, 1, offset, sign=True) elif opnum == rop.STRGETITEM: basesize, itemsize, ofs_length = get_array_token( rstr.STR, self.cpu.translate_support_code) assert itemsize == 1 basesize -= 1 # for the extra null character self.emit_gc_load_or_indexed(op, op.getarg(0), op.getarg(1), itemsize, itemsize, basesize, NOT_SIGNED) elif opnum == rop.UNICODEGETITEM: basesize, itemsize, ofs_length = get_array_token( rstr.UNICODE, self.cpu.translate_support_code) self.emit_gc_load_or_indexed(op, op.getarg(0), op.getarg(1), itemsize, itemsize, basesize, NOT_SIGNED) elif opnum == rop.STRSETITEM: basesize, itemsize, ofs_length = get_array_token( rstr.STR, self.cpu.translate_support_code) assert itemsize == 1 basesize -= 1 # for the extra null character self.emit_gc_store_or_indexed(op, op.getarg(0), op.getarg(1), op.getarg(2), itemsize, itemsize, basesize) elif opnum == rop.UNICODESETITEM: basesize, itemsize, ofs_length = get_array_token( rstr.UNICODE, self.cpu.translate_support_code) self.emit_gc_store_or_indexed(op, op.getarg(0), op.getarg(1), op.getarg(2), itemsize, itemsize, basesize) return False
def handle_getarrayitem(self, op): itemsize, ofs, sign = unpack_arraydescr(op.getdescr()) ptr_box = op.getarg(0) index_box = op.getarg(1) self.emit_gc_load_or_indexed(op, ptr_box, index_box, itemsize, itemsize, ofs, sign)
def emit_op_zero_array(self, op, arglocs): from rpython.jit.backend.llsupport.descr import unpack_arraydescr assert len(arglocs) == 0 size_box = op.getarg(2) if isinstance(size_box, ConstInt) and size_box.getint() == 0: return itemsize, baseofs, _ = unpack_arraydescr(op.getdescr()) args = op.getarglist() # # ZERO_ARRAY(base_loc, start, size, 1, 1) # 'start' and 'size' are both expressed in bytes, # and the two scaling arguments should always be ConstInt(1) on ARM. assert args[3].getint() == 1 assert args[4].getint() == 1 # base_loc = self._regalloc.rm.make_sure_var_in_reg(args[0], args) startbyte_box = args[1] if isinstance(startbyte_box, ConstInt): startbyte_loc = None startbyte = startbyte_box.getint() assert startbyte >= 0 else: startbyte_loc = self._regalloc.rm.make_sure_var_in_reg(startbyte_box, args) startbyte = -1 # base_loc and startbyte_loc are in two regs here (or startbyte_loc # is an immediate). Compute the dstaddr_loc, which is the raw # address that we will pass as first argument to memset(). # It can be in the same register as either one, but not in # args[2], because we're still needing the latter. dstaddr_loc = r.ip1 if startbyte >= 0: # a constant ofs = baseofs + startbyte reg = base_loc.value else: self.mc.ADD_rr(dstaddr_loc.value, base_loc.value, startbyte_loc.value) ofs = baseofs reg = dstaddr_loc.value if check_imm_arg(ofs): self.mc.ADD_ri(dstaddr_loc.value, reg, ofs) else: self.mc.gen_load_int(r.ip0.value, ofs) self.mc.ADD_rr(dstaddr_loc.value, reg, r.ip0.value) # We use STRB, STRH, STRW or STR based on whether we know the array # item size is a multiple of 1, 2 or 4. if itemsize & 1: itemsize = 1 elif itemsize & 2: itemsize = 2 elif itemsize & 4: itemsize = 4 else: itemsize = 8 limit = itemsize next_group = -1 if itemsize < 8 and startbyte >= 0: # we optimize STRB/STRH into STR, but this needs care: # it only works if startindex_loc is a constant, otherwise # we'd be doing unaligned accesses. next_group = (-startbyte) & 7 limit = 8 if (isinstance(size_box, ConstInt) and size_box.getint() <= 14 * limit): # same limit as GCC # Inline a series of STR operations, starting at 'dstaddr_loc'. # self.mc.gen_load_int(r.ip0.value, 0) i = 0 adjustment = 0 needs_adjustment = itemsize < 8 and (startbyte % 8) total_size = size_box.getint() while i < total_size: sz = itemsize if i == next_group: next_group += 8 if next_group <= total_size: sz = 8 if sz == 8: if needs_adjustment: self.mc.ADD_ri(dstaddr_loc.value, dstaddr_loc.value, i) adjustment = -i needs_adjustment = False self.mc.STR_ri(r.ip0.value, dstaddr_loc.value, i + adjustment) elif sz == 4: self.mc.STRW_ri(r.ip0.value, dstaddr_loc.value, i + adjustment) elif sz == 2: self.mc.STRH_ri(r.ip0.value, dstaddr_loc.value, i + adjustment) else: self.mc.STRB_ri(r.ip0.value, dstaddr_loc.value, i + adjustment) i += sz else: if isinstance(size_box, ConstInt): size_loc = self.imm(size_box.getint()) else: # load size_loc in a register different than dstaddr_loc size_loc = self._regalloc.rm.make_sure_var_in_reg(size_box, []) # # call memset() self._regalloc.before_call() self.simple_call_no_collect(self.imm(self.memset_addr), [dstaddr_loc, self.imm(0), size_loc]) self._regalloc.rm.possibly_free_var(size_box)
def transform_to_gc_load(self, op): NOT_SIGNED = 0 CINT_ZERO = ConstInt(0) opnum = op.getopnum() #if opnum == rop.CALL_MALLOC_NURSERY_VARSIZE: # v_length = op.getarg(2) # scale = op.getarg(1).getint() # if scale not in self.cpu.load_supported_factors: # scale, offset, v_length = \ # self._emit_mul_if_factor_offset_not_supported(v_length, scale, 0) # op.setarg(1, ConstInt(scale)) # op.setarg(2, v_length) if rop.is_getarrayitem(opnum) or \ opnum in (rop.GETARRAYITEM_RAW_I, rop.GETARRAYITEM_RAW_F): self.handle_getarrayitem(op) elif opnum in (rop.SETARRAYITEM_GC, rop.SETARRAYITEM_RAW): self.handle_setarrayitem(op) elif opnum == rop.RAW_STORE: itemsize, ofs, _ = unpack_arraydescr(op.getdescr()) ptr_box = op.getarg(0) index_box = op.getarg(1) value_box = op.getarg(2) self.emit_gc_store_or_indexed(op, ptr_box, index_box, value_box, itemsize, 1, ofs) elif opnum in (rop.RAW_LOAD_I, rop.RAW_LOAD_F): itemsize, ofs, sign = unpack_arraydescr(op.getdescr()) ptr_box = op.getarg(0) index_box = op.getarg(1) self.emit_gc_load_or_indexed(op, ptr_box, index_box, itemsize, 1, ofs, sign) elif opnum in (rop.GETINTERIORFIELD_GC_I, rop.GETINTERIORFIELD_GC_R, rop.GETINTERIORFIELD_GC_F): ofs, itemsize, fieldsize, sign = unpack_interiorfielddescr(op.getdescr()) ptr_box = op.getarg(0) index_box = op.getarg(1) self.emit_gc_load_or_indexed(op, ptr_box, index_box, fieldsize, itemsize, ofs, sign) elif opnum in (rop.SETINTERIORFIELD_RAW, rop.SETINTERIORFIELD_GC): ofs, itemsize, fieldsize, sign = unpack_interiorfielddescr(op.getdescr()) ptr_box = op.getarg(0) index_box = op.getarg(1) value_box = op.getarg(2) self.emit_gc_store_or_indexed(op, ptr_box, index_box, value_box, fieldsize, itemsize, ofs) elif opnum in (rop.GETFIELD_GC_I, rop.GETFIELD_GC_F, rop.GETFIELD_GC_R, rop.GETFIELD_RAW_I, rop.GETFIELD_RAW_F, rop.GETFIELD_RAW_R): ofs, itemsize, sign = unpack_fielddescr(op.getdescr()) ptr_box = op.getarg(0) if op.getopnum() in (rop.GETFIELD_GC_F, rop.GETFIELD_GC_I, rop.GETFIELD_GC_R): # See test_zero_ptr_field_before_getfield(). We hope there is # no getfield_gc in the middle of initialization code, but there # shouldn't be, given that a 'new' is already delayed by previous # optimization steps. In practice it should immediately be # followed by a bunch of 'setfields', and the 'pending_zeros' # optimization we do here is meant for this case. self.emit_pending_zeros() self.emit_gc_load_or_indexed(op, ptr_box, ConstInt(0), itemsize, 1, ofs, sign) self.emit_op(op) return True self.emit_gc_load_or_indexed(op, ptr_box, ConstInt(0), itemsize, 1, ofs, sign) elif opnum in (rop.SETFIELD_GC, rop.SETFIELD_RAW): ofs, itemsize, sign = unpack_fielddescr(op.getdescr()) ptr_box = op.getarg(0) value_box = op.getarg(1) self.emit_gc_store_or_indexed(op, ptr_box, ConstInt(0), value_box, itemsize, 1, ofs) elif opnum == rop.ARRAYLEN_GC: descr = op.getdescr() assert isinstance(descr, ArrayDescr) ofs = descr.lendescr.offset self.emit_gc_load_or_indexed(op, op.getarg(0), ConstInt(0), WORD, 1, ofs, NOT_SIGNED) elif opnum == rop.STRLEN: basesize, itemsize, ofs_length = get_array_token(rstr.STR, self.cpu.translate_support_code) self.emit_gc_load_or_indexed(op, op.getarg(0), ConstInt(0), WORD, 1, ofs_length, NOT_SIGNED) elif opnum == rop.UNICODELEN: basesize, itemsize, ofs_length = get_array_token(rstr.UNICODE, self.cpu.translate_support_code) self.emit_gc_load_or_indexed(op, op.getarg(0), ConstInt(0), WORD, 1, ofs_length, NOT_SIGNED) elif opnum == rop.STRGETITEM: basesize, itemsize, ofs_length = get_array_token(rstr.STR, self.cpu.translate_support_code) assert itemsize == 1 self.emit_gc_load_or_indexed(op, op.getarg(0), op.getarg(1), itemsize, itemsize, basesize, NOT_SIGNED) elif opnum == rop.UNICODEGETITEM: basesize, itemsize, ofs_length = get_array_token(rstr.UNICODE, self.cpu.translate_support_code) self.emit_gc_load_or_indexed(op, op.getarg(0), op.getarg(1), itemsize, itemsize, basesize, NOT_SIGNED) elif opnum == rop.STRSETITEM: basesize, itemsize, ofs_length = get_array_token(rstr.STR, self.cpu.translate_support_code) assert itemsize == 1 self.emit_gc_store_or_indexed(op, op.getarg(0), op.getarg(1), op.getarg(2), itemsize, itemsize, basesize) elif opnum == rop.UNICODESETITEM: basesize, itemsize, ofs_length = get_array_token(rstr.UNICODE, self.cpu.translate_support_code) self.emit_gc_store_or_indexed(op, op.getarg(0), op.getarg(1), op.getarg(2), itemsize, itemsize, basesize) return False
def handle_rawload(self, op): itemsize, ofs, sign = unpack_arraydescr(op.getdescr()) ptr_box = op.getarg(0) index_box = op.getarg(1) self.emit_gc_load_or_indexed(op, ptr_box, index_box, itemsize, 1, ofs, sign)
def emit_op_zero_array(self, op, arglocs, regalloc, fcond): from rpython.jit.backend.llsupport.descr import unpack_arraydescr assert len(arglocs) == 0 size_box = op.getarg(2) if isinstance(size_box, ConstInt) and size_box.getint() == 0: return fcond # nothing to do itemsize, baseofs, _ = unpack_arraydescr(op.getdescr()) args = op.getarglist() # # ZERO_ARRAY(base_loc, start, size, 1, 1) # 'start' and 'size' are both expressed in bytes, # and the two scaling arguments should always be ConstInt(1) on ARM. assert args[3].getint() == 1 assert args[4].getint() == 1 # base_loc = regalloc.rm.make_sure_var_in_reg(args[0], args) startbyte_box = args[1] if isinstance(startbyte_box, ConstInt): startbyte_loc = None startbyte = startbyte_box.getint() assert startbyte >= 0 else: startbyte_loc = regalloc.rm.make_sure_var_in_reg(startbyte_box, args) startbyte = -1 # base_loc and startbyte_loc are in two regs here (or startbyte_loc # is an immediate). Compute the dstaddr_loc, which is the raw # address that we will pass as first argument to memset(). # It can be in the same register as either one, but not in # args[2], because we're still needing the latter. dstaddr_box = TempVar() dstaddr_loc = regalloc.rm.force_allocate_reg(dstaddr_box, [args[2]]) if startbyte >= 0: # a constant ofs = baseofs + startbyte reg = base_loc.value else: self.mc.ADD_rr(dstaddr_loc.value, base_loc.value, startbyte_loc.value) ofs = baseofs reg = dstaddr_loc.value if check_imm_arg(ofs): self.mc.ADD_ri(dstaddr_loc.value, reg, imm=ofs) else: self.mc.gen_load_int(r.ip.value, ofs) self.mc.ADD_rr(dstaddr_loc.value, reg, r.ip.value) # We use STRB, STRH or STR based on whether we know the array # item size is a multiple of 1, 2 or 4. if itemsize & 1: itemsize = 1 elif itemsize & 2: itemsize = 2 else: itemsize = 4 limit = itemsize next_group = -1 if itemsize < 4 and startbyte >= 0: # we optimize STRB/STRH into STR, but this needs care: # it only works if startindex_loc is a constant, otherwise # we'd be doing unaligned accesses. next_group = (-startbyte) & 3 limit = 4 if isinstance(size_box, ConstInt) and size_box.getint() <= 14 * limit: # same limit as GCC # Inline a series of STR operations, starting at 'dstaddr_loc'. # self.mc.gen_load_int(r.ip.value, 0) i = 0 total_size = size_box.getint() while i < total_size: sz = itemsize if i == next_group: next_group += 4 if next_group <= total_size: sz = 4 if sz == 4: self.mc.STR_ri(r.ip.value, dstaddr_loc.value, imm=i) elif sz == 2: self.mc.STRH_ri(r.ip.value, dstaddr_loc.value, imm=i) else: self.mc.STRB_ri(r.ip.value, dstaddr_loc.value, imm=i) i += sz else: if isinstance(size_box, ConstInt): size_loc = imm(size_box.getint()) else: # load size_loc in a register different than dstaddr_loc size_loc = regalloc.rm.make_sure_var_in_reg(size_box, [dstaddr_box]) # # call memset() regalloc.before_call() self.simple_call_no_collect(imm(self.memset_addr), [dstaddr_loc, imm(0), size_loc]) regalloc.rm.possibly_free_var(size_box) regalloc.rm.possibly_free_var(dstaddr_box) return fcond