def test_boehm(): gc_ll_descr = 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 = 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 = get_array_descr(gc_ll_descr, A) p = gc_ll_descr.gc_malloc_array(arraydescr, 10) 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 test_boehm(): gc_ll_descr = GcLLDescr_boehm(None, None) # record = [] prev_funcptr_for_new = gc_ll_descr.funcptr_for_new def my_funcptr_for_new(size): p = prev_funcptr_for_new(size) record.append((size, p)) return p gc_ll_descr.funcptr_for_new = my_funcptr_for_new # # ---------- gc_malloc ---------- S = lltype.GcStruct('S', ('x', lltype.Signed)) sizedescr = 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 = get_array_descr(gc_ll_descr, A) p = gc_ll_descr.gc_malloc_array(arraydescr, 10) assert record == [(arraydescr.get_base_size(False) + 10 * arraydescr.get_item_size(False), 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 __init__(self, rtyper, stats=None, translate_support_code=False, annmixlevel=None, gcdescr=None): self.rtyper = rtyper self.translate_support_code = translate_support_code self.compiled_functions = [] self.fail_ops = [] self.in_out_args = [] if translate_support_code: get_size = llmemory.sizeof else: get_size = rffi.sizeof self._arraydescrs = [ ArrayDescr(get_size(llmemory.GCREF), self.SIZE_GCPTR), # 0 ArrayDescr(get_size(lltype.Signed), self.SIZE_INT), # 1 ArrayDescr(get_size(lltype.Char), self.SIZE_CHAR), # 2 ArrayDescr(get_size(lltype.UniChar), self.SIZE_UNICHAR), # 3 ] self._descr_caches = {} self.fielddescr_vtable = self.fielddescrof(rclass.OBJECT, 'typeptr') if sys.maxint == 2147483647: self.size_of_int = 4 else: self.size_of_int = 8 if runicode.MAXUNICODE > 0xffff: self.size_of_unicode = 4 else: self.size_of_unicode = 2 self.gcarray_gcref = lltype.GcArray(llmemory.GCREF) self.gcarray_signed = lltype.GcArray(lltype.Signed) self.gcarray_char = lltype.GcArray(lltype.Char) self.gcarray_unichar = lltype.GcArray(lltype.UniChar) basesize, _, ofs_length = symbolic.get_array_token( self.gcarray_signed, self.translate_support_code) self.array_index_array = basesize self.array_index_length = ofs_length basesize, _, ofs_length = symbolic.get_array_token( rstr.STR, self.translate_support_code) self.string_index_array = basesize self.string_index_length = ofs_length basesize, _, ofs_length = symbolic.get_array_token( rstr.UNICODE, self.translate_support_code) self.unicode_index_array = basesize self.unicode_index_length = ofs_length self.vtable_descr = self.fielddescrof(rclass.OBJECT, 'typeptr') self._ovf_error_instance = self._get_prebuilt_error(OverflowError) self._zer_error_instance = self._get_prebuilt_error(ZeroDivisionError) # # temporary (Boehm only) from pypy.translator.tool.cbuild import ExternalCompilationInfo compilation_info = ExternalCompilationInfo(libraries=['gc']) self.malloc_fn_ptr = rffi.llexternal("GC_malloc", [rffi.SIZE_T], llmemory.GCREF, compilation_info=compilation_info, sandboxsafe=True, _nowrapper=True) assert rffi.sizeof(rffi.SIZE_T) == self.size_of_int
def __init__(self, gcdescr, translator, rtyper): GcLLDescription.__init__(self, gcdescr, translator, rtyper) # grab a pointer to the Boehm 'malloc' function malloc_fn_ptr = self.configure_boehm_once() self.funcptr_for_new = malloc_fn_ptr def malloc_array(basesize, itemsize, ofs_length, num_elem): try: size = ovfcheck(basesize + ovfcheck(itemsize * num_elem)) except OverflowError: return lltype.nullptr(llmemory.GCREF.TO) res = self.funcptr_for_new(size) if not res: return res rffi.cast(rffi.CArrayPtr(lltype.Signed), res)[ofs_length/WORD] = num_elem return res self.malloc_array = malloc_array self.GC_MALLOC_ARRAY = lltype.Ptr(lltype.FuncType( [lltype.Signed] * 4, llmemory.GCREF)) (str_basesize, str_itemsize, str_ofs_length ) = symbolic.get_array_token(rstr.STR, self.translate_support_code) (unicode_basesize, unicode_itemsize, unicode_ofs_length ) = symbolic.get_array_token(rstr.UNICODE, self.translate_support_code) def malloc_str(length): return self.malloc_array( str_basesize, str_itemsize, str_ofs_length, length ) def malloc_unicode(length): return self.malloc_array( unicode_basesize, unicode_itemsize, unicode_ofs_length, length ) self.malloc_str = malloc_str self.malloc_unicode = malloc_unicode self.GC_MALLOC_STR_UNICODE = lltype.Ptr(lltype.FuncType( [lltype.Signed], llmemory.GCREF)) # on some platform GC_init is required before any other # GC_* functions, call it here for the benefit of tests # XXX move this to tests init_fn_ptr = rffi.llexternal("GC_init", [], lltype.Void, compilation_info=self.compilation_info, sandboxsafe=True, _nowrapper=True) init_fn_ptr()
def do_strgetitem(self, stringbox, indexbox): basesize, itemsize, ofs_length = symbolic.get_array_token( rstr.STR, self.translate_support_code) gcref = stringbox.getref_base() i = indexbox.getint() v = rffi.cast(rffi.CArrayPtr(lltype.Char), gcref)[basesize + i] return BoxInt(ord(v))
def genop_discard_strsetitem(self, op, arglocs): base_loc, ofs_loc, val_loc = arglocs basesize, itemsize, ofs_length = symbolic.get_array_token( rstr.STR, self.cpu.translate_support_code) assert itemsize == 1 self.mc.MOV(addr8_add(base_loc, ofs_loc, basesize), lower_byte(val_loc))
def do_strlen(self, stringbox): basesize, itemsize, ofs_length = symbolic.get_array_token( TP, self.translate_support_code) gcref = stringbox.getref_base() v = rffi.cast(rffi.CArrayPtr(lltype.Signed), gcref)[ofs_length / WORD] return BoxInt(v)
def do_strsetitem(self, stringbox, indexbox, vbox): basesize, itemsize, ofs_length = symbolic.get_array_token( rstr.STR, self.translate_support_code) index = indexbox.getint() v = vbox.getint() a = stringbox.getref_base() rffi.cast(rffi.CArrayPtr(lltype.Char), a)[index + basesize] = chr(v)
def gc_malloc_unicode(self, num_elem): basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE, self.translate_support_code) size = basesize + num_elem * itemsize res = self.funcptr_for_new(size) rffi.cast(rffi.CArrayPtr(lltype.Signed), res)[ofs_length/WORD] = num_elem return res
def do_strgetitem(self, stringbox, indexbox): basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, self.translate_support_code) gcref = stringbox.getref_base() i = indexbox.getint() v = rffi.cast(rffi.CArrayPtr(lltype.Char), gcref)[basesize + i] return BoxInt(ord(v))
def do_strsetitem(self, stringbox, indexbox, vbox): basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, self.translate_support_code) index = indexbox.getint() v = vbox.getint() a = stringbox.getref_base() rffi.cast(rffi.CArrayPtr(lltype.Char), a)[index + basesize] = chr(v)
def gc_malloc_unicode(self, num_elem): basesize, itemsize, ofs_length = symbolic.get_array_token( rstr.UNICODE, self.translate_support_code) size = basesize + num_elem * itemsize res = self.funcptr_for_new(size) rffi.cast(rffi.CArrayPtr(lltype.Signed), res)[ofs_length / WORD] = num_elem return res
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 arraydescrof(self, A): basesize, _, ofs_length = symbolic.get_array_token(A, self.translate_support_code) if isinstance(basesize, int): # else Symbolics, can't be compared... assert self.array_index_array == basesize assert self.array_index_length == ofs_length itemsize_index = self._get_size_index(A.OF) return self._arraydescrs[itemsize_index]
def do_unicodesetitem(self, stringbox, indexbox, vbox): basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE, self.translate_support_code) index = indexbox.getint() v = vbox.getint() a = stringbox.getref_base() basesize = basesize // itemsize rffi.cast(rffi.CArrayPtr(lltype.UniChar), a)[index + basesize] = unichr(v)
def do_unicodesetitem(self, stringbox, indexbox, vbox): basesize, itemsize, ofs_length = symbolic.get_array_token( rstr.UNICODE, self.translate_support_code) index = indexbox.getint() v = vbox.getint() a = stringbox.getref_base() basesize = basesize // itemsize rffi.cast(rffi.CArrayPtr(lltype.UniChar), a)[index + basesize] = unichr(v)
def genop_discard_unicodesetitem(self, op, arglocs): base_loc, ofs_loc, val_loc = arglocs basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE, self.cpu.translate_support_code) if itemsize == 4: self.mc.MOV(addr_add(base_loc, ofs_loc, basesize, 2), val_loc) elif itemsize == 2: self.mc.MOV16(addr_add(base_loc, ofs_loc, basesize, 1), val_loc) else: assert 0, itemsize
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 genop_unicodegetitem(self, op, arglocs, resloc): base_loc, ofs_loc = arglocs basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE, self.cpu.translate_support_code) if itemsize == 4: self.mc.MOV(resloc, addr_add(base_loc, ofs_loc, basesize, 2)) elif itemsize == 2: self.mc.MOVZX(resloc, addr_add(base_loc, ofs_loc, basesize, 1)) else: assert 0, itemsize
def genop_discard_unicodesetitem(self, op, arglocs): base_loc, ofs_loc, val_loc = arglocs basesize, itemsize, ofs_length = symbolic.get_array_token( rstr.UNICODE, self.cpu.translate_support_code) if itemsize == 4: self.mc.MOV(addr_add(base_loc, ofs_loc, basesize, 2), val_loc) elif itemsize == 2: self.mc.MOV16(addr_add(base_loc, ofs_loc, basesize, 1), val_loc) else: assert 0, itemsize
def genop_unicodegetitem(self, op, arglocs, resloc): base_loc, ofs_loc = arglocs basesize, itemsize, ofs_length = symbolic.get_array_token( rstr.UNICODE, self.cpu.translate_support_code) if itemsize == 4: self.mc.MOV(resloc, addr_add(base_loc, ofs_loc, basesize, 2)) elif itemsize == 2: self.mc.MOVZX(resloc, addr_add(base_loc, ofs_loc, basesize, 1)) else: assert 0, itemsize
def consider_newstr(self, op): gc_ll_descr = self.assembler.cpu.gc_ll_descr if gc_ll_descr.get_funcptr_for_newstr is not None: # framework GC loc = self.loc(op.args[0]) return self._call(op, [loc]) # boehm GC (XXX kill the following code at some point) ofs_items, itemsize, ofs = symbolic.get_array_token(rstr.STR, self.translate_support_code) assert itemsize == 1 return self._malloc_varsize(ofs_items, ofs, 0, op.args[0], op.result)
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 consider_newstr(self, op, ignored): gc_ll_descr = self.assembler.cpu.gc_ll_descr if gc_ll_descr.get_funcptr_for_newstr is not None: # framework GC loc = self.loc(op.args[0]) return self._call(op, [loc]) # boehm GC (XXX kill the following code at some point) ofs_items, itemsize, ofs = symbolic.get_array_token(rstr.STR, self.translate_support_code) assert itemsize == 1 return self._malloc_varsize(ofs_items, ofs, 0, op.args[0], op.result)
def consider_newunicode(self, op): gc_ll_descr = self.assembler.cpu.gc_ll_descr if gc_ll_descr.get_funcptr_for_newunicode is not None: # framework GC loc = self.loc(op.args[0]) return self._call(op, [loc]) # boehm GC (XXX kill the following code at some point) ofs_items, itemsize, ofs = symbolic.get_array_token(rstr.UNICODE, self.translate_support_code) if itemsize == 4: return self._malloc_varsize(ofs_items, ofs, 2, op.args[0], op.result) elif itemsize == 2: return self._malloc_varsize(ofs_items, ofs, 1, op.args[0], op.result) else: assert False, itemsize
def get_array_descr(gccache, ARRAY): cache = gccache._cache_array try: return cache[ARRAY] except KeyError: arraydescr = getArrayDescrClass(ARRAY)() # verify basic assumption that all arrays' basesize and ofslength # are equal basesize, itemsize, ofslength = symbolic.get_array_token(ARRAY, False) assert basesize == arraydescr.get_base_size(False) assert itemsize == arraydescr.get_item_size(False) assert ofslength == arraydescr.get_ofs_length(False) gccache.init_array_descr(ARRAY, arraydescr) cache[ARRAY] = arraydescr return arraydescr
def consider_newunicode(self, op, ignored): gc_ll_descr = self.assembler.cpu.gc_ll_descr if gc_ll_descr.get_funcptr_for_newunicode is not None: # framework GC loc = self.loc(op.args[0]) return self._call(op, [loc]) # boehm GC (XXX kill the following code at some point) ofs_items, itemsize, ofs = symbolic.get_array_token(rstr.UNICODE, self.translate_support_code) if itemsize == 4: return self._malloc_varsize(ofs_items, ofs, 2, op.args[0], op.result) elif itemsize == 2: return self._malloc_varsize(ofs_items, ofs, 1, op.args[0], op.result) else: assert False, itemsize
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 get_array_descr(gccache, ARRAY): cache = gccache._cache_array try: return cache[ARRAY] except KeyError: # we only support Arrays that are either GcArrays, or raw no-length # non-gc Arrays. if ARRAY._hints.get('nolength', False): assert not isinstance(ARRAY, lltype.GcArray) arraydescr = getArrayNoLengthDescrClass(ARRAY)() else: assert isinstance(ARRAY, lltype.GcArray) arraydescr = getArrayDescrClass(ARRAY)() # verify basic assumption that all arrays' basesize and ofslength # are equal basesize, itemsize, ofslength = symbolic.get_array_token(ARRAY, False) assert basesize == arraydescr.get_base_size(False) assert itemsize == arraydescr.get_item_size(False) if not ARRAY._hints.get('nolength', False): assert ofslength == arraydescr.get_ofs_length(False) if isinstance(ARRAY, lltype.GcArray): gccache.init_array_descr(ARRAY, arraydescr) cache[ARRAY] = arraydescr return arraydescr
def genop_unicodelen(self, op, arglocs, resloc): base_loc = arglocs[0] basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE, self.cpu.translate_support_code) self.mc.MOV(resloc, addr_add_const(base_loc, ofs_length))
def genop_unicodelen(self, op, arglocs, resloc): base_loc = arglocs[0] basesize, itemsize, ofs_length = symbolic.get_array_token( rstr.UNICODE, self.cpu.translate_support_code) self.mc.MOV(resloc, addr_add_const(base_loc, ofs_length))
def _make_functions(self, really_not_translated): from pypy.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.""" if self.DEBUG: self._random_usage_of_xmm_registers() type_id = rffi.cast(llgroup.HALFWORD, 0) # missing here return llop1.do_malloc_fixedsize_clear(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.""" 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): return llop1.do_malloc_varsize_clear( llmemory.GCREF, str_type_id, length, str_basesize, str_itemsize, str_ofs_length) self.generate_function('malloc_str', malloc_str, [lltype.Signed]) def malloc_unicode(length): return llop1.do_malloc_varsize_clear( llmemory.GCREF, unicode_type_id, length, unicode_basesize, unicode_itemsize, unicode_ofs_length) self.generate_function('malloc_unicode', malloc_unicode, [lltype.Signed]) # Rarely called: allocate a fixed-size amount of bytes, but # not in the nursery, because it is too big. Implemented like # malloc_nursery_slowpath() above. self.generate_function('malloc_fixedsize', malloc_nursery_slowpath, [lltype.Signed])
def __init__(self, gcdescr, translator, rtyper, llop1=llop): from pypy.rpython.memory.gctypelayout import check_typeid from pypy.rpython.memory.gcheader import GCHeaderBuilder from pypy.rpython.memory.gctransform import framework GcLLDescription.__init__(self, gcdescr, translator, rtyper) assert self.translate_support_code, "required with the framework GC" self.translator = translator self.llop1 = llop1 # we need the hybrid or minimark GC for rgc._make_sure_does_not_move() # to work if gcdescr.config.translation.gc not in ('hybrid', 'minimark'): raise NotImplementedError("--gc=%s not implemented with the JIT" % (gcdescr.config.translation.gc,)) # to find roots in the assembler, make a GcRootMap name = gcdescr.config.translation.gcrootfinder try: cls = globals()['GcRootMap_' + name] except KeyError: raise NotImplementedError("--gcrootfinder=%s not implemented" " with the JIT" % (name,)) gcrootmap = cls(gcdescr) self.gcrootmap = gcrootmap # make a TransformerLayoutBuilder and save it on the translator # where it can be fished and reused by the FrameworkGCTransformer self.layoutbuilder = framework.TransformerLayoutBuilder(translator) self.layoutbuilder.delay_encoding() self.translator._jit2gc = {'layoutbuilder': self.layoutbuilder} gcrootmap.add_jit2gc_hooks(self.translator._jit2gc) self.GCClass = self.layoutbuilder.GCClass self.moving_gc = self.GCClass.moving_gc self.HDRPTR = lltype.Ptr(self.GCClass.HDR) self.gcheaderbuilder = GCHeaderBuilder(self.HDRPTR.TO) (self.array_basesize, _, self.array_length_ofs) = \ symbolic.get_array_token(lltype.GcArray(lltype.Signed), True) self.max_size_of_young_obj = self.GCClass.JIT_max_size_of_young_obj() self.minimal_size_in_nursery=self.GCClass.JIT_minimal_size_in_nursery() # for the fast path of mallocs, the following must be true, at least assert self.GCClass.inline_simple_malloc assert self.GCClass.inline_simple_malloc_varsize # make a malloc function, with two arguments def malloc_basic(size, tid): type_id = llop.extract_ushort(llgroup.HALFWORD, tid) check_typeid(type_id) res = llop1.do_malloc_fixedsize_clear(llmemory.GCREF, type_id, size, False, False, False) # In case the operation above failed, we are returning NULL # from this function to assembler. There is also an RPython # exception set, typically MemoryError; but it's easier and # faster to check for the NULL return value, as done by # translator/exceptiontransform.py. #llop.debug_print(lltype.Void, "\tmalloc_basic", size, type_id, # "-->", res) return res self.malloc_basic = malloc_basic self.GC_MALLOC_BASIC = lltype.Ptr(lltype.FuncType( [lltype.Signed, lltype.Signed], llmemory.GCREF)) self.WB_FUNCPTR = lltype.Ptr(lltype.FuncType( [llmemory.Address, llmemory.Address], lltype.Void)) self.WB_ARRAY_FUNCPTR = lltype.Ptr(lltype.FuncType( [llmemory.Address, lltype.Signed, llmemory.Address], lltype.Void)) self.write_barrier_descr = WriteBarrierDescr(self) # def malloc_array(itemsize, tid, num_elem): 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.array_basesize, itemsize, self.array_length_ofs) self.malloc_array = malloc_array self.GC_MALLOC_ARRAY = lltype.Ptr(lltype.FuncType( [lltype.Signed] * 3, llmemory.GCREF)) # (str_basesize, str_itemsize, str_ofs_length ) = symbolic.get_array_token(rstr.STR, True) (unicode_basesize, unicode_itemsize, unicode_ofs_length ) = symbolic.get_array_token(rstr.UNICODE, True) str_type_id = self.layoutbuilder.get_type_id(rstr.STR) unicode_type_id = self.layoutbuilder.get_type_id(rstr.UNICODE) # def malloc_str(length): return llop1.do_malloc_varsize_clear( llmemory.GCREF, str_type_id, length, str_basesize, str_itemsize, str_ofs_length) def malloc_unicode(length): return llop1.do_malloc_varsize_clear( llmemory.GCREF, unicode_type_id, length, unicode_basesize,unicode_itemsize, unicode_ofs_length) self.malloc_str = malloc_str self.malloc_unicode = malloc_unicode self.GC_MALLOC_STR_UNICODE = lltype.Ptr(lltype.FuncType( [lltype.Signed], llmemory.GCREF)) # class ForTestOnly: pass for_test_only = ForTestOnly() for_test_only.x = 1.23 def random_usage_of_xmm_registers(): x0 = for_test_only.x x1 = x0 * 0.1 x2 = x0 * 0.2 x3 = x0 * 0.3 for_test_only.x = x0 + x1 + x2 + x3 # def malloc_slowpath(size): if self.DEBUG: random_usage_of_xmm_registers() assert size >= self.minimal_size_in_nursery # NB. although we call do_malloc_fixedsize_clear() here, # it's a bit of a hack because we set tid to 0 and may # also use it to allocate varsized objects. The tid # and possibly the length are both set afterward. gcref = llop1.do_malloc_fixedsize_clear(llmemory.GCREF, 0, size, False, False, False) return rffi.cast(lltype.Signed, gcref) self.malloc_slowpath = malloc_slowpath self.MALLOC_SLOWPATH = lltype.FuncType([lltype.Signed], lltype.Signed)
def genop_strgetitem(self, op, arglocs, resloc): base_loc, ofs_loc = arglocs basesize, itemsize, ofs_length = symbolic.get_array_token( rstr.STR, self.cpu.translate_support_code) assert itemsize == 1 self.mc.MOVZX(resloc, addr8_add(base_loc, ofs_loc, basesize))
def get_base_size(self, translate_support_code): basesize, _, _ = symbolic.get_array_token(_AF, translate_support_code) return basesize
def do_strlen(self, stringbox): basesize, itemsize, ofs_length = symbolic.get_array_token(TP, self.translate_support_code) gcref = stringbox.getref_base() v = rffi.cast(rffi.CArrayPtr(lltype.Signed), gcref)[ofs_length/WORD] return BoxInt(v)
def get_ofs_length(self, translate_support_code): _, _, ofslength = symbolic.get_array_token(_A, translate_support_code) return ofslength
def __init__(self, gcdescr, translator, llop1=llop): from pypy.rpython.memory.gctypelayout import _check_typeid from pypy.rpython.memory.gcheader import GCHeaderBuilder from pypy.rpython.memory.gctransform import framework GcLLDescription.__init__(self, gcdescr, translator) assert self.translate_support_code, "required with the framework GC" self.translator = translator self.llop1 = llop1 # we need the hybrid GC for GcRefList.alloc_gcref_list() to work if gcdescr.config.translation.gc != 'hybrid': raise NotImplementedError("--gc=%s not implemented with the JIT" % (gcdescr.config.translation.gc,)) # to find roots in the assembler, make a GcRootMap name = gcdescr.config.translation.gcrootfinder try: cls = globals()['GcRootMap_' + name] except KeyError: raise NotImplementedError("--gcrootfinder=%s not implemented" " with the JIT" % (name,)) gcrootmap = cls() self.gcrootmap = gcrootmap self.gcrefs = GcRefList() self.single_gcref_descr = GcPtrFieldDescr(0) # make a TransformerLayoutBuilder and save it on the translator # where it can be fished and reused by the FrameworkGCTransformer self.layoutbuilder = framework.JITTransformerLayoutBuilder( gcdescr.config) self.layoutbuilder.delay_encoding() self.translator._jit2gc = { 'layoutbuilder': self.layoutbuilder, 'gcmapstart': lambda: gcrootmap.gcmapstart(), 'gcmapend': lambda: gcrootmap.gcmapend(), } self.GCClass = self.layoutbuilder.GCClass self.moving_gc = self.GCClass.moving_gc self.HDRPTR = lltype.Ptr(self.GCClass.HDR) self.gcheaderbuilder = GCHeaderBuilder(self.HDRPTR.TO) self.fielddescr_tid = get_field_descr(self, self.GCClass.HDR, 'tid') self.c_jit_wb_if_flag = ConstInt(self.GCClass.JIT_WB_IF_FLAG) self.calldescr_jit_wb = get_call_descr(self, [llmemory.GCREF, llmemory.GCREF], lltype.Void) (self.array_basesize, _, self.array_length_ofs) = \ symbolic.get_array_token(lltype.GcArray(lltype.Signed), True) min_ns = self.GCClass.TRANSLATION_PARAMS['min_nursery_size'] self.max_size_of_young_obj = self.GCClass.get_young_fixedsize(min_ns) # make a malloc function, with three arguments def malloc_basic(size, tid): type_id = llop.extract_ushort(rffi.USHORT, tid) has_finalizer = bool(tid & (1<<16)) _check_typeid(type_id) res = llop1.do_malloc_fixedsize_clear(llmemory.GCREF, type_id, size, True, has_finalizer, False) #llop.debug_print(lltype.Void, "\tmalloc_basic", size, type_id, # "-->", res) return res self.malloc_basic = malloc_basic self.GC_MALLOC_BASIC = lltype.Ptr(lltype.FuncType( [lltype.Signed, lltype.Signed], llmemory.GCREF)) self.WB_FUNCPTR = lltype.Ptr(lltype.FuncType( [llmemory.Address, llmemory.Address], lltype.Void)) # def malloc_array(itemsize, tid, num_elem): type_id = llop.extract_ushort(rffi.USHORT, tid) _check_typeid(type_id) return llop1.do_malloc_varsize_clear( llmemory.GCREF, type_id, num_elem, self.array_basesize, itemsize, self.array_length_ofs, True) self.malloc_array = malloc_array self.GC_MALLOC_ARRAY = lltype.Ptr(lltype.FuncType( [lltype.Signed] * 3, llmemory.GCREF)) # (str_basesize, str_itemsize, str_ofs_length ) = symbolic.get_array_token(rstr.STR, True) (unicode_basesize, unicode_itemsize, unicode_ofs_length ) = symbolic.get_array_token(rstr.UNICODE, True) str_type_id = self.layoutbuilder.get_type_id(rstr.STR) unicode_type_id = self.layoutbuilder.get_type_id(rstr.UNICODE) # def malloc_str(length): return llop1.do_malloc_varsize_clear( llmemory.GCREF, str_type_id, length, str_basesize, str_itemsize, str_ofs_length, True) def malloc_unicode(length): return llop1.do_malloc_varsize_clear( llmemory.GCREF, unicode_type_id, length, unicode_basesize, unicode_itemsize, unicode_ofs_length, True) self.malloc_str = malloc_str self.malloc_unicode = malloc_unicode self.GC_MALLOC_STR_UNICODE = lltype.Ptr(lltype.FuncType( [lltype.Signed], llmemory.GCREF)) def malloc_fixedsize_slowpath(size): gcref = llop1.do_malloc_fixedsize_clear(llmemory.GCREF, 0, size, True, False, False) res = rffi.cast(lltype.Signed, gcref) nurs_free = llop1.gc_adr_of_nursery_free(llmemory.Address).signed[0] return r_ulonglong(nurs_free) << 32 | r_ulonglong(r_uint(res)) self.malloc_fixedsize_slowpath = malloc_fixedsize_slowpath self.MALLOC_FIXEDSIZE_SLOWPATH = lltype.FuncType([lltype.Signed], lltype.UnsignedLongLong)
def genop_strgetitem(self, op, arglocs, resloc): base_loc, ofs_loc = arglocs basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, self.cpu.translate_support_code) assert itemsize == 1 self.mc.MOVZX(resloc, addr8_add(base_loc, ofs_loc, basesize))
def get_base_size(self, translate_support_code): basesize, _, _ = symbolic.get_array_token(_A, translate_support_code) return basesize
def _make_functions(self, really_not_translated): from pypy.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.""" if self.DEBUG: self._random_usage_of_xmm_registers() type_id = rffi.cast(llgroup.HALFWORD, 0) # missing here return llop1.do_malloc_fixedsize_clear(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.""" 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): return llop1.do_malloc_varsize_clear( llmemory.GCREF, str_type_id, length, str_basesize, str_itemsize, str_ofs_length) self.generate_function('malloc_str', malloc_str, [lltype.Signed]) def malloc_unicode(length): return llop1.do_malloc_varsize_clear( llmemory.GCREF, unicode_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 __init__(self, gcdescr, translator, llop1=llop): from pypy.rpython.memory.gctypelayout import _check_typeid from pypy.rpython.memory.gcheader import GCHeaderBuilder from pypy.rpython.memory.gctransform import framework GcLLDescription.__init__(self, gcdescr, translator) assert self.translate_support_code, "required with the framework GC" self.translator = translator self.llop1 = llop1 # we need the hybrid GC for GcRefList.alloc_gcref_list() to work if gcdescr.config.translation.gc != 'hybrid': raise NotImplementedError("--gc=%s not implemented with the JIT" % (gcdescr.config.translation.gc, )) # to find roots in the assembler, make a GcRootMap name = gcdescr.config.translation.gcrootfinder try: cls = globals()['GcRootMap_' + name] except KeyError: raise NotImplementedError("--gcrootfinder=%s not implemented" " with the JIT" % (name, )) gcrootmap = cls() self.gcrootmap = gcrootmap self.gcrefs = GcRefList() self.single_gcref_descr = GcPtrFieldDescr(0) # make a TransformerLayoutBuilder and save it on the translator # where it can be fished and reused by the FrameworkGCTransformer self.layoutbuilder = framework.TransformerLayoutBuilder(translator) self.layoutbuilder.delay_encoding() self.translator._jit2gc = { 'layoutbuilder': self.layoutbuilder, 'gcmapstart': lambda: gcrootmap.gcmapstart(), 'gcmapend': lambda: gcrootmap.gcmapend(), } self.GCClass = self.layoutbuilder.GCClass self.moving_gc = self.GCClass.moving_gc self.HDRPTR = lltype.Ptr(self.GCClass.HDR) self.gcheaderbuilder = GCHeaderBuilder(self.HDRPTR.TO) (self.array_basesize, _, self.array_length_ofs) = \ symbolic.get_array_token(lltype.GcArray(lltype.Signed), True) min_ns = self.GCClass.TRANSLATION_PARAMS['min_nursery_size'] self.max_size_of_young_obj = self.GCClass.get_young_fixedsize(min_ns) # make a malloc function, with three arguments def malloc_basic(size, tid): type_id = llop.extract_ushort(rffi.USHORT, tid) has_finalizer = bool(tid & (1 << 16)) _check_typeid(type_id) try: res = llop1.do_malloc_fixedsize_clear(llmemory.GCREF, type_id, size, True, has_finalizer, False) except MemoryError: fatalerror("out of memory (from JITted code)") res = lltype.nullptr(llmemory.GCREF.TO) #llop.debug_print(lltype.Void, "\tmalloc_basic", size, type_id, # "-->", res) return res self.malloc_basic = malloc_basic self.GC_MALLOC_BASIC = lltype.Ptr( lltype.FuncType([lltype.Signed, lltype.Signed], llmemory.GCREF)) self.WB_FUNCPTR = lltype.Ptr( lltype.FuncType([llmemory.Address, llmemory.Address], lltype.Void)) self.write_barrier_descr = WriteBarrierDescr(self) # def malloc_array(itemsize, tid, num_elem): type_id = llop.extract_ushort(rffi.USHORT, tid) _check_typeid(type_id) try: return llop1.do_malloc_varsize_clear( llmemory.GCREF, type_id, num_elem, self.array_basesize, itemsize, self.array_length_ofs, True) except MemoryError: fatalerror("out of memory (from JITted code)") return lltype.nullptr(llmemory.GCREF.TO) self.malloc_array = malloc_array self.GC_MALLOC_ARRAY = lltype.Ptr( lltype.FuncType([lltype.Signed] * 3, llmemory.GCREF)) # (str_basesize, str_itemsize, str_ofs_length) = symbolic.get_array_token(rstr.STR, True) (unicode_basesize, unicode_itemsize, unicode_ofs_length) = symbolic.get_array_token(rstr.UNICODE, True) str_type_id = self.layoutbuilder.get_type_id(rstr.STR) unicode_type_id = self.layoutbuilder.get_type_id(rstr.UNICODE) # def malloc_str(length): try: return llop1.do_malloc_varsize_clear(llmemory.GCREF, str_type_id, length, str_basesize, str_itemsize, str_ofs_length, True) except MemoryError: fatalerror("out of memory (from JITted code)") return lltype.nullptr(llmemory.GCREF.TO) def malloc_unicode(length): try: return llop1.do_malloc_varsize_clear(llmemory.GCREF, unicode_type_id, length, unicode_basesize, unicode_itemsize, unicode_ofs_length, True) except MemoryError: fatalerror("out of memory (from JITted code)") return lltype.nullptr(llmemory.GCREF.TO) self.malloc_str = malloc_str self.malloc_unicode = malloc_unicode self.GC_MALLOC_STR_UNICODE = lltype.Ptr( lltype.FuncType([lltype.Signed], llmemory.GCREF)) def malloc_fixedsize_slowpath(size): try: gcref = llop1.do_malloc_fixedsize_clear( llmemory.GCREF, 0, size, True, False, False) except MemoryError: fatalerror("out of memory (from JITted code)") return r_ulonglong(0) res = rffi.cast(lltype.Signed, gcref) nurs_free = llop1.gc_adr_of_nursery_free( llmemory.Address).signed[0] return r_ulonglong(nurs_free) << 32 | r_ulonglong(r_uint(res)) self.malloc_fixedsize_slowpath = malloc_fixedsize_slowpath self.MALLOC_FIXEDSIZE_SLOWPATH = lltype.FuncType( [lltype.Signed], lltype.UnsignedLongLong)
def genop_discard_strsetitem(self, op, arglocs): base_loc, ofs_loc, val_loc = arglocs basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, self.cpu.translate_support_code) assert itemsize == 1 self.mc.MOV(addr8_add(base_loc, ofs_loc, basesize), lower_byte(val_loc))