def test_boehm(): gc_ll_descr = gc.GcLLDescr_boehm(None, None, None) # record = [] prev_malloc_fn_ptr = gc_ll_descr.malloc_fn_ptr def my_malloc_fn_ptr(size): p = prev_malloc_fn_ptr(size) record.append((size, p)) return p gc_ll_descr.malloc_fn_ptr = my_malloc_fn_ptr # # ---------- gc_malloc ---------- S = lltype.GcStruct('S', ('x', lltype.Signed)) sizedescr = descr.get_size_descr(gc_ll_descr, S) p = gc_ll_descr.gc_malloc(sizedescr) assert record == [(sizedescr.size, p)] del record[:] # ---------- gc_malloc_array ---------- A = lltype.GcArray(lltype.Signed) arraydescr = descr.get_array_descr(gc_ll_descr, A) p = gc_ll_descr.gc_malloc_array(10, arraydescr) assert record == [(arraydescr.basesize + 10 * arraydescr.itemsize, p)] del record[:] # ---------- gc_malloc_str ---------- p = gc_ll_descr.gc_malloc_str(10) basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, False) assert record == [(basesize + 10 * itemsize, p)] del record[:] # ---------- gc_malloc_unicode ---------- p = gc_ll_descr.gc_malloc_unicode(10) basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE, False) assert record == [(basesize + 10 * itemsize, p)] del record[:]
def _gen_address_inside_string(self, baseloc, ofsloc, resloc, is_unicode): if is_unicode: ofs_items, _, _ = symbolic.get_array_token(rstr.UNICODE, self.cpu.translate_support_code) scale = self._get_unicode_item_scale() else: ofs_items, itemsize, _ = symbolic.get_array_token(rstr.STR, self.cpu.translate_support_code) assert itemsize == 1 scale = 0 self._gen_address(resloc, baseloc, ofsloc, scale, ofs_items)
def get_array_descr(gccache, ARRAY_OR_STRUCT): cache = gccache._cache_array try: return cache[ARRAY_OR_STRUCT] except KeyError: tsc = gccache.translate_support_code basesize, itemsize, _ = symbolic.get_array_token(ARRAY_OR_STRUCT, tsc) if isinstance(ARRAY_OR_STRUCT, lltype.Array): ARRAY_INSIDE = ARRAY_OR_STRUCT else: ARRAY_INSIDE = ARRAY_OR_STRUCT._flds[ARRAY_OR_STRUCT._arrayfld] if ARRAY_INSIDE._hints.get('nolength', False): lendescr = None else: lendescr = get_field_arraylen_descr(gccache, ARRAY_OR_STRUCT) flag = get_type_flag(ARRAY_INSIDE.OF) is_pure = bool(ARRAY_INSIDE._immutable_field(None)) arraydescr = ArrayDescr(basesize, itemsize, lendescr, flag, is_pure) if ARRAY_INSIDE.OF is lltype.SingleFloat or \ ARRAY_INSIDE.OF is lltype.Float: # it would be better to set the flag as FLOAT_TYPE # for single float -> leads to problems arraydescr = ArrayDescr(basesize, itemsize, lendescr, flag, is_pure, concrete_type='f') cache[ARRAY_OR_STRUCT] = arraydescr if isinstance(ARRAY_INSIDE.OF, lltype.Struct): descrs = heaptracker.all_interiorfielddescrs(gccache, ARRAY_INSIDE, get_field_descr=get_interiorfield_descr) arraydescr.all_interiorfielddescrs = descrs if ARRAY_OR_STRUCT._gckind == 'gc': gccache.init_array_descr(ARRAY_OR_STRUCT, arraydescr) return arraydescr
def prepare_unicodelen(self, op): basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE, self.cpu.translate_support_code) base_loc = self.ensure_reg(op.getarg(0)) self.free_op_vars() result_loc = self.force_allocate_reg(op) return [base_loc, imm(ofs_length), result_loc, imm(WORD), imm(0)]
def _emit_copycontent(self, arglocs, is_unicode): [src_ptr_loc, dst_ptr_loc, src_ofs_loc, dst_ofs_loc, length_loc] = arglocs if is_unicode: basesize, itemsize, _ = symbolic.get_array_token( rstr.UNICODE, self.cpu.translate_support_code) if itemsize == 2: scale = 1 elif itemsize == 4: scale = 2 else: raise AssertionError else: basesize, itemsize, _ = symbolic.get_array_token( rstr.STR, self.cpu.translate_support_code) assert itemsize == 1 basesize -= 1 # for the extra null character scale = 0 # src and src_len are tmp registers src = src_ptr_loc src_len = r.odd_reg(src) dst = r.r0 dst_len = r.r1 self._emit_load_for_copycontent(src, src_ptr_loc, src_ofs_loc, scale) self._emit_load_for_copycontent(dst, dst_ptr_loc, dst_ofs_loc, scale) if length_loc.is_imm(): length = length_loc.getint() self.mc.load_imm(dst_len, length << scale) else: if scale > 0: self.mc.SLLG(dst_len, length_loc, l.addr(scale)) else: self.mc.LGR(dst_len, length_loc) # ensure that src_len is as long as dst_len, otherwise # padding bytes are written to dst self.mc.LGR(src_len, dst_len) self.mc.AGHI(src, l.imm(basesize)) self.mc.AGHI(dst, l.imm(basesize)) # s390x has memset directly as a hardware instruction!! # 0xB8 means we might reference dst later self.mc.MVCLE(dst, src, l.addr(0xB8)) # NOTE this instruction can (determined by the cpu), just # quit the movement any time, thus it is looped until all bytes # are copied! self.mc.BRC(c.OF, l.imm(-self.mc.MVCLE_byte_count))
def unpack_arraydescr_size(self, arraydescr): from rpython.jit.backend.llsupport.symbolic import get_array_token from rpython.jit.backend.llsupport.descr import get_type_flag, FLAG_SIGNED assert isinstance(arraydescr, ArrayDescr) basesize, itemsize, _ = get_array_token(arraydescr.A, False) flag = get_type_flag(arraydescr.A.OF) is_signed = (flag == FLAG_SIGNED) return basesize, itemsize, is_signed
def test_gc_malloc_unicode(self): p = self.gc_ll_descr.gc_malloc_unicode(10) type_id = self.gc_ll_descr.layoutbuilder.get_type_id(rstr.UNICODE) tid = llop.combine_ushort(lltype.Signed, type_id, 0) basesize, itemsize, ofs_length = symbolic.get_array_token( rstr.UNICODE, True) assert self.llop1.record == [("varsize", tid, 10, repr(basesize), repr(itemsize), repr(ofs_length), p)]
def _emit_copycontent(self, arglocs, is_unicode): [src_ptr_loc, dst_ptr_loc, src_ofs_loc, dst_ofs_loc, length_loc] = arglocs if is_unicode: basesize, itemsize, _ = symbolic.get_array_token(rstr.UNICODE, self.cpu.translate_support_code) if itemsize == 2: scale = 1 elif itemsize == 4: scale = 2 else: raise AssertionError else: basesize, itemsize, _ = symbolic.get_array_token(rstr.STR, self.cpu.translate_support_code) assert itemsize == 1 scale = 0 # src and src_len are tmp registers src = src_ptr_loc src_len = r.odd_reg(src) dst = r.r0 dst_len = r.r1 self._emit_load_for_copycontent(src, src_ptr_loc, src_ofs_loc, scale) self._emit_load_for_copycontent(dst, dst_ptr_loc, dst_ofs_loc, scale) if length_loc.is_imm(): length = length_loc.getint() self.mc.load_imm(dst_len, length << scale) else: if scale > 0: self.mc.SLLG(dst_len, length_loc, l.addr(scale)) else: self.mc.LGR(dst_len, length_loc) # ensure that src_len is as long as dst_len, otherwise # padding bytes are written to dst self.mc.LGR(src_len, dst_len) self.mc.AGHI(src, l.imm(basesize)) self.mc.AGHI(dst, l.imm(basesize)) # s390x has memset directly as a hardware instruction!! # 0xB8 means we might reference dst later self.mc.MVCLE(dst, src, l.addr(0xB8)) # NOTE this instruction can (determined by the cpu), just # quit the movement any time, thus it is looped until all bytes # are copied! self.mc.BRC(c.OF, l.imm(-self.mc.MVCLE_byte_count))
def _get_unicode_item_scale(self): _, itemsize, _ = symbolic.get_array_token(rstr.UNICODE, self.cpu.translate_support_code) if itemsize == 4: return 2 elif itemsize == 2: return 1 else: raise AssertionError("bad unicode item size")
def test_gc_malloc_unicode(self): p = self.gc_ll_descr.gc_malloc_unicode(10) type_id = self.gc_ll_descr.layoutbuilder.get_type_id(rstr.UNICODE) tid = llop.combine_ushort(lltype.Signed, type_id, 0) basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE, True) assert self.llop1.record == [("varsize", tid, 10, repr(basesize), repr(itemsize), repr(ofs_length), p)]
def prepare_unicodesetitem(self, op): basesize, itemsize, _ = symbolic.get_array_token(rstr.UNICODE, self.cpu.translate_support_code) 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(basesize)) imm_size = imm(itemsize) return [base_loc, index_loc, value_loc, ofs_loc, imm_size, imm_size]
def prepare_unicodegetitem(self, op): basesize, itemsize, _ = symbolic.get_array_token(rstr.UNICODE, self.cpu.translate_support_code) 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(basesize)) self.free_op_vars() result_loc = self.force_allocate_reg(op) imm_size = imm(itemsize) return [base_loc, index_loc, result_loc, ofs_loc, imm_size, imm_size, imm(0)]
def get_field_arraylen_descr(gccache, ARRAY_OR_STRUCT): cache = gccache._cache_arraylen try: return cache[ARRAY_OR_STRUCT] except KeyError: tsc = gccache.translate_support_code (_, _, ofs) = symbolic.get_array_token(ARRAY_OR_STRUCT, tsc) size = symbolic.get_size(lltype.Signed, tsc) result = FieldDescr("len", ofs, size, get_type_flag(lltype.Signed)) cache[ARRAY_OR_STRUCT] = result return result
def get_array_descr(gccache, ARRAY_OR_STRUCT): cache = gccache._cache_array try: return cache[ARRAY_OR_STRUCT] except KeyError: tsc = gccache.translate_support_code basesize, itemsize, _ = symbolic.get_array_token(ARRAY_OR_STRUCT, tsc) if isinstance(ARRAY_OR_STRUCT, lltype.Array): ARRAY_INSIDE = ARRAY_OR_STRUCT else: ARRAY_INSIDE = ARRAY_OR_STRUCT._flds[ARRAY_OR_STRUCT._arrayfld] if ARRAY_INSIDE._hints.get('nolength', False): lendescr = None else: lendescr = get_field_arraylen_descr(gccache, ARRAY_OR_STRUCT) flag = get_type_flag(ARRAY_INSIDE.OF) arraydescr = ArrayDescr(basesize, itemsize, lendescr, flag) if ARRAY_OR_STRUCT._gckind == 'gc': gccache.init_array_descr(ARRAY_OR_STRUCT, arraydescr) cache[ARRAY_OR_STRUCT] = arraydescr return arraydescr
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 _make_functions(self, really_not_translated): from rpython.memory.gctypelayout import check_typeid llop1 = self.llop1 (self.standard_array_basesize, _, self.standard_array_length_ofs) = \ symbolic.get_array_token(lltype.GcArray(lltype.Signed), not really_not_translated) def malloc_nursery_slowpath(size): """Allocate 'size' null bytes out of the nursery. Note that the fast path is typically inlined by the backend.""" assert size >= self.minimal_size_in_nursery if self.DEBUG: self._random_usage_of_xmm_registers() type_id = rffi.cast(llgroup.HALFWORD, 0) # missing here return llop1.do_malloc_fixedsize(llmemory.GCREF, type_id, size, False, False, False) self.generate_function('malloc_nursery', malloc_nursery_slowpath, [lltype.Signed]) def malloc_array(itemsize, tid, num_elem): """Allocate an array with a variable-size num_elem. Only works for standard arrays.""" assert num_elem >= 0, 'num_elem should be >= 0' type_id = llop.extract_ushort(llgroup.HALFWORD, tid) check_typeid(type_id) return llop1.do_malloc_varsize_clear( llmemory.GCREF, type_id, num_elem, self.standard_array_basesize, itemsize, self.standard_array_length_ofs) self.generate_function('malloc_array', malloc_array, [lltype.Signed] * 3) def malloc_array_nonstandard(basesize, itemsize, lengthofs, tid, num_elem): """For the rare case of non-standard arrays, i.e. arrays where self.standard_array_{basesize,length_ofs} is wrong. It can occur e.g. with arrays of floats on Win32.""" type_id = llop.extract_ushort(llgroup.HALFWORD, tid) check_typeid(type_id) return llop1.do_malloc_varsize_clear(llmemory.GCREF, type_id, num_elem, basesize, itemsize, lengthofs) self.generate_function('malloc_array_nonstandard', malloc_array_nonstandard, [lltype.Signed] * 5) str_type_id = self.str_descr.tid str_basesize = self.str_descr.basesize str_itemsize = self.str_descr.itemsize str_ofs_length = self.str_descr.lendescr.offset unicode_type_id = self.unicode_descr.tid unicode_basesize = self.unicode_descr.basesize unicode_itemsize = self.unicode_descr.itemsize unicode_ofs_length = self.unicode_descr.lendescr.offset def malloc_str(length): type_id = llop.extract_ushort(llgroup.HALFWORD, str_type_id) return llop1.do_malloc_varsize(llmemory.GCREF, type_id, length, str_basesize, str_itemsize, str_ofs_length) self.generate_function('malloc_str', malloc_str, [lltype.Signed]) def malloc_unicode(length): type_id = llop.extract_ushort(llgroup.HALFWORD, unicode_type_id) return llop1.do_malloc_varsize(llmemory.GCREF, type_id, length, unicode_basesize, unicode_itemsize, unicode_ofs_length) self.generate_function('malloc_unicode', malloc_unicode, [lltype.Signed]) # Never called as far as I can tell, but there for completeness: # allocate a fixed-size object, but not in the nursery, because # it is too big. def malloc_big_fixedsize(size, tid): if self.DEBUG: self._random_usage_of_xmm_registers() type_id = llop.extract_ushort(llgroup.HALFWORD, tid) check_typeid(type_id) return llop1.do_malloc_fixedsize_clear(llmemory.GCREF, type_id, size, False, False, False) self.generate_function('malloc_big_fixedsize', malloc_big_fixedsize, [lltype.Signed] * 2)
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 _make_functions(self, really_not_translated): from rpython.memory.gctypelayout import check_typeid llop1 = self.llop1 (self.standard_array_basesize, _, self.standard_array_length_ofs) = \ symbolic.get_array_token(lltype.GcArray(lltype.Signed), not really_not_translated) def malloc_nursery_slowpath(size): """Allocate 'size' null bytes out of the nursery. Note that the fast path is typically inlined by the backend.""" assert size >= self.minimal_size_in_nursery if self.DEBUG: self._random_usage_of_xmm_registers() type_id = rffi.cast(llgroup.HALFWORD, 0) # missing here return llop1.do_malloc_fixedsize(llmemory.GCREF, type_id, size, False, False, False) self.generate_function('malloc_nursery', malloc_nursery_slowpath, [lltype.Signed]) def malloc_array(itemsize, tid, num_elem): """Allocate an array with a variable-size num_elem. Only works for standard arrays.""" assert num_elem >= 0, 'num_elem should be >= 0' type_id = llop.extract_ushort(llgroup.HALFWORD, tid) check_typeid(type_id) return llop1.do_malloc_varsize_clear( llmemory.GCREF, type_id, num_elem, self.standard_array_basesize, itemsize, self.standard_array_length_ofs) self.generate_function('malloc_array', malloc_array, [lltype.Signed] * 3) def malloc_array_nonstandard(basesize, itemsize, lengthofs, tid, num_elem): """For the rare case of non-standard arrays, i.e. arrays where self.standard_array_{basesize,length_ofs} is wrong. It can occur e.g. with arrays of floats on Win32.""" type_id = llop.extract_ushort(llgroup.HALFWORD, tid) check_typeid(type_id) return llop1.do_malloc_varsize_clear( llmemory.GCREF, type_id, num_elem, basesize, itemsize, lengthofs) self.generate_function('malloc_array_nonstandard', malloc_array_nonstandard, [lltype.Signed] * 5) str_type_id = self.str_descr.tid str_basesize = self.str_descr.basesize str_itemsize = self.str_descr.itemsize str_ofs_length = self.str_descr.lendescr.offset unicode_type_id = self.unicode_descr.tid unicode_basesize = self.unicode_descr.basesize unicode_itemsize = self.unicode_descr.itemsize unicode_ofs_length = self.unicode_descr.lendescr.offset def malloc_str(length): type_id = llop.extract_ushort(llgroup.HALFWORD, str_type_id) return llop1.do_malloc_varsize( llmemory.GCREF, type_id, length, str_basesize, str_itemsize, str_ofs_length) self.generate_function('malloc_str', malloc_str, [lltype.Signed]) def malloc_unicode(length): type_id = llop.extract_ushort(llgroup.HALFWORD, unicode_type_id) return llop1.do_malloc_varsize( llmemory.GCREF, type_id, length, unicode_basesize, unicode_itemsize, unicode_ofs_length) self.generate_function('malloc_unicode', malloc_unicode, [lltype.Signed]) # Never called as far as I can tell, but there for completeness: # allocate a fixed-size object, but not in the nursery, because # it is too big. def malloc_big_fixedsize(size, tid): if self.DEBUG: self._random_usage_of_xmm_registers() type_id = llop.extract_ushort(llgroup.HALFWORD, tid) check_typeid(type_id) return llop1.do_malloc_fixedsize_clear(llmemory.GCREF, type_id, size, False, False, False) self.generate_function('malloc_big_fixedsize', malloc_big_fixedsize, [lltype.Signed] * 2)