def create_lowlevel_type(self): entry_methods = { "valid": LLOrderedDict.ll_valid_from_flag, "everused": LLOrderedDict.ll_everused_from_flag, "mark_deleted": LLOrderedDict.ll_mark_deleted_in_flag, "must_clear_key": self._must_clear(self.key_repr.lowleveltype), "must_clear_value": self._must_clear(self.value_repr.lowleveltype), } fields = [ ("key", self.key_repr.lowleveltype), ("value", self.value_repr.lowleveltype), ("next", lltype.Signed), ("prev", lltype.Signed), ("everused", lltype.Bool), ("valid", lltype.Bool), ] fast_hash_func = None if not self.hash_func_repr: fast_hash_func = self.key_repr.get_ll_hash_function() if fast_hash_func is None: fields.append(("hash", lltype.Signed)) entry_methods["hash"] = LLOrderedDict.ll_hash_from_cache else: entry_methods["hash"] = LLOrderedDict.ll_hash_recompute entry_methods["fast_hash_func"] = fast_hash_func DICTENTRY = lltype.Struct("ORDEREDDICTENTRY", *fields) fields = [ ("num_items", lltype.Signed), ("resize_counter", lltype.Signed), ("first_entry", lltype.Signed), ("last_entry", lltype.Signed), ("entries", lltype.Ptr(lltype.GcArray(DICTENTRY, adtmeths=entry_methods))), ] dict_methods = {} if self.eq_func_repr and self.hash_func_repr: dict_methods["paranoia"] = True dict_methods["hashkey"] = LLOrderedDict.ll_hashkey_custom dict_methods["keyeq"] = LLOrderedDict.ll_keyeq_custom dict_methods["r_hashkey"] = self.hash_func_repr dict_methods["r_keyeq"] = self.eq_func_repr fields.append(("hashkey_func", self.hash_func_repr.lowleveltype)) fields.append(("keyeq_func", self.eq_func_repr.lowleveltype)) else: dict_methods["paranoia"] = False dict_methods["hashkey"] = lltype.staticAdtMethod( self.key_repr.get_ll_hash_function()) ll_keyeq = self.key_repr.get_ll_eq_function() if ll_keyeq is not None: ll_keyeq = lltype.staticAdtMethod(ll_keyeq) dict_methods["keyeq"] = ll_keyeq DICT = lltype.GcStruct("ORDEREDDICT", *fields, adtmeths=dict_methods) return lltype.Ptr(DICT)
def create_lowlevel_type(self): entry_methods = { "valid": LLOrderedDict.ll_valid_from_flag, "everused": LLOrderedDict.ll_everused_from_flag, "mark_deleted": LLOrderedDict.ll_mark_deleted_in_flag, "must_clear_key": self._must_clear(self.key_repr.lowleveltype), "must_clear_value": self._must_clear(self.value_repr.lowleveltype), } fields = [ ("key", self.key_repr.lowleveltype), ("value", self.value_repr.lowleveltype), ("next", lltype.Signed), ("prev", lltype.Signed), ("everused", lltype.Bool), ("valid", lltype.Bool), ] fast_hash_func = None if not self.hash_func_repr: fast_hash_func = self.key_repr.get_ll_hash_function() if fast_hash_func is None: fields.append(("hash", lltype.Signed)) entry_methods["hash"] = LLOrderedDict.ll_hash_from_cache else: entry_methods["hash"] = LLOrderedDict.ll_hash_recompute entry_methods["fast_hash_func"] = fast_hash_func DICTENTRY = lltype.Struct("ORDEREDDICTENTRY", *fields) fields = [ ("num_items", lltype.Signed), ("resize_counter", lltype.Signed), ("first_entry", lltype.Signed), ("last_entry", lltype.Signed), ("entries", lltype.Ptr(lltype.GcArray(DICTENTRY, adtmeths=entry_methods))), ] dict_methods = {} if self.eq_func_repr and self.hash_func_repr: dict_methods["paranoia"] = True dict_methods["hashkey"] = LLOrderedDict.ll_hashkey_custom dict_methods["keyeq"] = LLOrderedDict.ll_keyeq_custom dict_methods["r_hashkey"] = self.hash_func_repr dict_methods["r_keyeq"] = self.eq_func_repr fields.append(("hashkey_func", self.hash_func_repr.lowleveltype)) fields.append(("keyeq_func", self.eq_func_repr.lowleveltype)) else: dict_methods["paranoia"] = False dict_methods["hashkey"] = lltype.staticAdtMethod(self.key_repr.get_ll_hash_function()) ll_keyeq = self.key_repr.get_ll_eq_function() if ll_keyeq is not None: ll_keyeq = lltype.staticAdtMethod(ll_keyeq) dict_methods["keyeq"] = ll_keyeq DICT = lltype.GcStruct("ORDEREDDICT", *fields, adtmeths=dict_methods) return lltype.Ptr(DICT)
def test_adt_method(self): def ll_callme(n): return n ll_callme = lltype.staticAdtMethod(ll_callme) S = lltype.GcStruct('S', ('x', lltype.Signed), adtmeths={ 'yep': True, 'callme': ll_callme }) def g(x, y, z): p = lltype.malloc(S) p.x = x if p.yep: z *= p.callme(y) return z def f(x, y, z): return g(x, y, z) t, wa = self.translate(f, [int, int, int]) fgraph = graphof(t, f) assert fgraph.startblock.operations[-1].opname == 'direct_call' result = wa.analyze(fgraph.startblock.operations[-1]) assert list(result) == [("struct", lltype.Ptr(S), "x")]
def __init__(self, rtyper, r_key): self.rtyper = rtyper self.r_key = r_key fasthashfn = r_key.get_ll_fasthash_function() self.ll_keyhash = r_key.get_ll_hash_function() ll_keyeq = lltype.staticAdtMethod(r_key.get_ll_eq_function()) def ll_valid(entries, i): value = entries[i].value return bool(value) and bool(weakref_deref(rclass.OBJECTPTR, value)) def ll_everused(entries, i): return bool(entries[i].value) def ll_hash(entries, i): return fasthashfn(entries[i].key) entrymeths = { 'allocate': lltype.typeMethod(rdict._ll_malloc_entries), 'delete': rdict._ll_free_entries, 'valid': ll_valid, 'everused': ll_everused, 'hash': ll_hash, } WEAKDICTENTRY = lltype.Struct("weakdictentry", ("key", r_key.lowleveltype), ("value", llmemory.WeakRefPtr)) WEAKDICTENTRYARRAY = lltype.GcArray(WEAKDICTENTRY, adtmeths=entrymeths, hints={'weakarray': 'value'}) # NB. the 'hints' is not used so far ^^^ dictmeths = { 'll_get': self.ll_get, 'll_set': self.ll_set, 'keyeq': ll_keyeq, 'paranoia': False, } self.WEAKDICT = lltype.GcStruct( "weakvaldict", ("num_items", lltype.Signed), ("num_pristine_entries", lltype.Signed), ("entries", lltype.Ptr(WEAKDICTENTRYARRAY)), adtmeths=dictmeths) self.lowleveltype = lltype.Ptr(self.WEAKDICT) self.dict_cache = {}
def __init__(self, rtyper, r_key): self.rtyper = rtyper self.r_key = r_key fasthashfn = r_key.get_ll_fasthash_function() self.ll_keyhash = r_key.get_ll_hash_function() ll_keyeq = lltype.staticAdtMethod(r_key.get_ll_eq_function()) def ll_valid(entries, i): value = entries[i].value return bool(value) and bool(weakref_deref(rclass.OBJECTPTR, value)) def ll_everused(entries, i): return bool(entries[i].value) def ll_hash(entries, i): return fasthashfn(entries[i].key) entrymeths = { 'allocate': lltype.typeMethod(rdict._ll_malloc_entries), 'delete': rdict._ll_free_entries, 'valid': ll_valid, 'everused': ll_everused, 'hash': ll_hash, } WEAKDICTENTRY = lltype.Struct("weakdictentry", ("key", r_key.lowleveltype), ("value", llmemory.WeakRefPtr)) WEAKDICTENTRYARRAY = lltype.GcArray(WEAKDICTENTRY, adtmeths=entrymeths, hints={'weakarray': 'value'}) # NB. the 'hints' is not used so far ^^^ dictmeths = { 'll_get': self.ll_get, 'll_set': self.ll_set, 'keyeq': ll_keyeq, 'paranoia': False, } self.WEAKDICT = lltype.GcStruct( "weakvaldict", ("num_items", lltype.Signed), ("resize_counter", lltype.Signed), ("entries", lltype.Ptr(WEAKDICTENTRYARRAY)), adtmeths=dictmeths) self.lowleveltype = lltype.Ptr(self.WEAKDICT) self.dict_cache = {}
def __init__(self, rtyper, r_key): self.rtyper = rtyper self.r_key = r_key fasthashfn = r_key.get_ll_fasthash_function() self.ll_keyhash = r_key.get_ll_hash_function() ll_keyeq = lltype.staticAdtMethod(r_key.get_ll_eq_function()) def ll_valid(entries, i): value = entries[i].value return bool(value) and bool(weakref_deref(rclass.OBJECTPTR, value)) def ll_everused(entries, i): return bool(entries[i].value) def ll_hash(entries, i): return fasthashfn(entries[i].key) entrymeths = { "allocate": lltype.typeMethod(rdict._ll_malloc_entries), "delete": rdict._ll_free_entries, "valid": ll_valid, "everused": ll_everused, "hash": ll_hash, } WEAKDICTENTRY = lltype.Struct("weakdictentry", ("key", r_key.lowleveltype), ("value", llmemory.WeakRefPtr)) WEAKDICTENTRYARRAY = lltype.GcArray(WEAKDICTENTRY, adtmeths=entrymeths, hints={"weakarray": "value"}) # NB. the 'hints' is not used so far ^^^ dictmeths = {"ll_get": self.ll_get, "ll_set": self.ll_set, "keyeq": ll_keyeq, "paranoia": False} self.WEAKDICT = lltype.GcStruct( "weakvaldict", ("num_items", lltype.Signed), ("resize_counter", lltype.Signed), ("entries", lltype.Ptr(WEAKDICTENTRYARRAY)), adtmeths=dictmeths, ) self.lowleveltype = lltype.Ptr(self.WEAKDICT) self.dict_cache = {}
def test_adt_method(self): def ll_callme(n): return n ll_callme = lltype.staticAdtMethod(ll_callme) S = lltype.GcStruct('S', ('x', lltype.Signed), adtmeths = {'yep': True, 'callme': ll_callme}) def g(x, y, z): p = lltype.malloc(S) p.x = x if p.yep: z *= p.callme(y) return z def f(x, y, z): return g(x, y, z) t, wa = self.translate(f, [int, int, int]) fgraph = graphof(t, f) assert fgraph.startblock.operations[-1].opname == 'direct_call' result = wa.analyze(fgraph.startblock.operations[-1]) assert list(result) == [("struct", lltype.Ptr(S), "x")]
src = llmemory.cast_ptr_to_adr(s1) + _str_ofs(s1start) dest = llmemory.cast_ptr_to_adr(s2) + _str_ofs(s2start) llmemory.raw_memcopy(src, dest, llmemory.sizeof(CHAR_TP) * lgt) copy_string_contents._always_inline_ = True return func_with_new_name(copy_string_contents, 'copy_%s_contents' % name) copy_string_contents = _new_copy_contents_fun(STR, Char, 'string') copy_unicode_contents = _new_copy_contents_fun(UNICODE, UniChar, 'unicode') STR.become( GcStruct('rpy_string', ('hash', Signed), ('chars', Array(Char, hints={'immutable': True})), adtmeths={ 'malloc': staticAdtMethod(mallocstr), 'empty': staticAdtMethod(emptystrfun), 'copy_contents': staticAdtMethod(copy_string_contents) })) UNICODE.become( GcStruct('rpy_unicode', ('hash', Signed), ('chars', Array(UniChar, hints={'immutable': True})), adtmeths={ 'malloc': staticAdtMethod(mallocunicode), 'empty': staticAdtMethod(emptyunicodefun), 'copy_contents': staticAdtMethod(copy_unicode_contents) })) SIGNED_ARRAY = GcArray(Signed) CONST_STR_CACHE = WeakValueDictionary() CONST_UNICODE_CACHE = WeakValueDictionary()
newbuf = mallocfn(new_allocated) copycontentsfn(ll_builder.buf, newbuf, 0, 0, ll_builder.allocated) ll_builder.buf = newbuf ll_builder.allocated = new_allocated return func_with_new_name(stringbuilder_grow, name) stringbuilder_grow = new_grow_func('stringbuilder_grow', rstr.mallocstr, rstr.copy_string_contents) unicodebuilder_grow = new_grow_func('unicodebuilder_grow', rstr.mallocunicode, rstr.copy_unicode_contents) STRINGBUILDER = lltype.GcStruct('stringbuilder', ('allocated', lltype.Signed), ('used', lltype.Signed), ('buf', lltype.Ptr(STR)), adtmeths={'grow':staticAdtMethod(stringbuilder_grow)}) UNICODEBUILDER = lltype.GcStruct('unicodebuilder', ('allocated', lltype.Signed), ('used', lltype.Signed), ('buf', lltype.Ptr(UNICODE)), adtmeths={'grow':staticAdtMethod(unicodebuilder_grow)}) MAX = 16*1024*1024 class BaseStringBuilderRepr(AbstractStringBuilderRepr): @classmethod def ll_new(cls, init_size): if init_size < 0 or init_size > MAX: init_size = MAX ll_builder = lltype.malloc(cls.lowleveltype.TO)
def _setup_repr(self): if 'key_repr' not in self.__dict__: key_repr = self._key_repr_computer() self.external_key_repr, self.key_repr = self.pickkeyrepr(key_repr) if 'value_repr' not in self.__dict__: self.external_value_repr, self.value_repr = self.pickrepr( self._value_repr_computer()) if isinstance(self.DICT, lltype.GcForwardReference): self.DICTKEY = self.key_repr.lowleveltype self.DICTVALUE = self.value_repr.lowleveltype # compute the shape of the DICTENTRY structure entryfields = [] entrymeths = { 'allocate': lltype.typeMethod(_ll_malloc_entries), 'delete': _ll_free_entries, 'must_clear_key': (isinstance(self.DICTKEY, lltype.Ptr) and self.DICTKEY._needsgc()), 'must_clear_value': (isinstance(self.DICTVALUE, lltype.Ptr) and self.DICTVALUE._needsgc()), } # * the key entryfields.append(("key", self.DICTKEY)) # * if NULL is not a valid ll value for the key or the value # field of the entry, it can be used as a marker for # never-used entries. Otherwise, we need an explicit flag. s_key = self.dictkey.s_value s_value = self.dictvalue.s_value nullkeymarker = not self.key_repr.can_ll_be_null(s_key) nullvaluemarker = not self.value_repr.can_ll_be_null(s_value) dummykeyobj = self.key_repr.get_ll_dummyval_obj(self.rtyper, s_key) dummyvalueobj = self.value_repr.get_ll_dummyval_obj( self.rtyper, s_value) # * the state of the entry - trying to encode it as dummy objects if nullkeymarker and dummykeyobj: # all the state can be encoded in the key entrymeths['everused'] = ll_everused_from_key entrymeths['dummy_obj'] = dummykeyobj entrymeths['valid'] = ll_valid_from_key entrymeths['mark_deleted'] = ll_mark_deleted_in_key # the key is overwritten by 'dummy' when the entry is deleted entrymeths['must_clear_key'] = False elif nullvaluemarker and dummyvalueobj: # all the state can be encoded in the value entrymeths['everused'] = ll_everused_from_value entrymeths['dummy_obj'] = dummyvalueobj entrymeths['valid'] = ll_valid_from_value entrymeths['mark_deleted'] = ll_mark_deleted_in_value # value is overwritten by 'dummy' when entry is deleted entrymeths['must_clear_value'] = False else: # we need a flag to know if the entry was ever used # (we cannot use a NULL as a marker for this, because # the key and value will be reset to NULL to clear their # reference) entryfields.append(("f_everused", lltype.Bool)) entrymeths['everused'] = ll_everused_from_flag # can we still rely on a dummy obj to mark deleted entries? if dummykeyobj: entrymeths['dummy_obj'] = dummykeyobj entrymeths['valid'] = ll_valid_from_key entrymeths['mark_deleted'] = ll_mark_deleted_in_key # key is overwritten by 'dummy' when entry is deleted entrymeths['must_clear_key'] = False elif dummyvalueobj: entrymeths['dummy_obj'] = dummyvalueobj entrymeths['valid'] = ll_valid_from_value entrymeths['mark_deleted'] = ll_mark_deleted_in_value # value is overwritten by 'dummy' when entry is deleted entrymeths['must_clear_value'] = False else: entryfields.append(("f_valid", lltype.Bool)) entrymeths['valid'] = ll_valid_from_flag entrymeths['mark_deleted'] = ll_mark_deleted_in_flag # * the value entryfields.append(("value", self.DICTVALUE)) # * the hash, if needed if self.custom_eq_hash: fasthashfn = None else: fasthashfn = self.key_repr.get_ll_fasthash_function() if fasthashfn is None: entryfields.append(("f_hash", lltype.Signed)) entrymeths['hash'] = ll_hash_from_cache else: entrymeths['hash'] = ll_hash_recomputed entrymeths['fasthashfn'] = fasthashfn # Build the lltype data structures self.DICTENTRY = lltype.Struct("dictentry", *entryfields) self.DICTENTRYARRAY = lltype.GcArray(self.DICTENTRY, adtmeths=entrymeths) fields = [("num_items", lltype.Signed), ("num_pristine_entries", lltype.Signed), ("entries", lltype.Ptr(self.DICTENTRYARRAY))] if self.custom_eq_hash: self.r_rdict_eqfn, self.r_rdict_hashfn = self._custom_eq_hash_repr( ) fields.extend([("fnkeyeq", self.r_rdict_eqfn.lowleveltype), ("fnkeyhash", self.r_rdict_hashfn.lowleveltype) ]) adtmeths = { 'keyhash': ll_keyhash_custom, 'keyeq': ll_keyeq_custom, 'r_rdict_eqfn': self.r_rdict_eqfn, 'r_rdict_hashfn': self.r_rdict_hashfn, 'paranoia': True, } else: # figure out which functions must be used to hash and compare ll_keyhash = self.key_repr.get_ll_hash_function() ll_keyeq = self.key_repr.get_ll_eq_function() # can be None ll_keyhash = lltype.staticAdtMethod(ll_keyhash) if ll_keyeq is not None: ll_keyeq = lltype.staticAdtMethod(ll_keyeq) adtmeths = { 'keyhash': ll_keyhash, 'keyeq': ll_keyeq, 'paranoia': False, } adtmeths['KEY'] = self.DICTKEY adtmeths['VALUE'] = self.DICTVALUE adtmeths['allocate'] = lltype.typeMethod(_ll_malloc_dict) self.DICT.become( lltype.GcStruct("dicttable", adtmeths=adtmeths, *fields))
# the entry must still be marked as everused(). d.entries[i].value = llmemory.dead_wref d.entries[i].key = lltype.nullptr(rstr.STR) #llop.debug_print(lltype.Void, i, 'zero') def ll_weakdict_resize(d): # first set num_items to its correct, up-to-date value entries = d.entries num_items = 0 for i in range(len(entries)): if entries.valid(i): num_items += 1 d.num_items = num_items rdict.ll_dict_resize(d) str_keyeq = lltype.staticAdtMethod(rstr.string_repr.get_ll_eq_function()) dictmeths = { 'll_get': ll_get, 'll_set': ll_set, 'keyeq': str_keyeq, 'paranoia': False, } WEAKDICT = lltype.GcStruct("weakdict", ("num_items", lltype.Signed), ("num_pristine_entries", lltype.Signed), ("entries", lltype.Ptr(WEAKDICTENTRYARRAY)), adtmeths=dictmeths)
new_allocated = ovfcheck(new_allocated + needed) except OverflowError: raise MemoryError ll_builder.buf = rgc.resize_buffer(ll_builder.buf, ll_builder.used, new_allocated) ll_builder.allocated = new_allocated return func_with_new_name(stringbuilder_grow, name) stringbuilder_grow = new_grow_func('stringbuilder_grow') unicodebuilder_grow = new_grow_func('unicodebuilder_grow') STRINGBUILDER = lltype.GcStruct('stringbuilder', ('allocated', lltype.Signed), ('used', lltype.Signed), ('buf', lltype.Ptr(STR)), adtmeths={'grow':staticAdtMethod(stringbuilder_grow)}) UNICODEBUILDER = lltype.GcStruct('unicodebuilder', ('allocated', lltype.Signed), ('used', lltype.Signed), ('buf', lltype.Ptr(UNICODE)), adtmeths={'grow':staticAdtMethod(unicodebuilder_grow)}) MAX = 16*1024*1024 class BaseStringBuilderRepr(AbstractStringBuilderRepr): @classmethod def ll_new(cls, init_size): if init_size < 0 or init_size > MAX: init_size = MAX ll_builder = lltype.malloc(cls.lowleveltype.TO)
def _setup_repr(self): if 'key_repr' not in self.__dict__: key_repr = self._key_repr_computer() self.external_key_repr, self.key_repr = self.pickkeyrepr(key_repr) if 'value_repr' not in self.__dict__: self.external_value_repr, self.value_repr = self.pickrepr(self._value_repr_computer()) if isinstance(self.DICT, lltype.GcForwardReference): self.DICTKEY = self.key_repr.lowleveltype self.DICTVALUE = self.value_repr.lowleveltype # compute the shape of the DICTENTRY structure entryfields = [] entrymeths = { 'allocate': lltype.typeMethod(_ll_malloc_entries), 'delete': _ll_free_entries, 'must_clear_key': (isinstance(self.DICTKEY, lltype.Ptr) and self.DICTKEY._needsgc()), 'must_clear_value': (isinstance(self.DICTVALUE, lltype.Ptr) and self.DICTVALUE._needsgc()), } # * the key entryfields.append(("key", self.DICTKEY)) # * if NULL is not a valid ll value for the key or the value # field of the entry, it can be used as a marker for # never-used entries. Otherwise, we need an explicit flag. s_key = self.dictkey.s_value s_value = self.dictvalue.s_value nullkeymarker = not self.key_repr.can_ll_be_null(s_key) nullvaluemarker = not self.value_repr.can_ll_be_null(s_value) if self.force_non_null: if not nullkeymarker: rmodel.warning("%s can be null, but forcing non-null in dict key" % s_key) nullkeymarker = True if not nullvaluemarker: rmodel.warning("%s can be null, but forcing non-null in dict value" % s_value) nullvaluemarker = True dummykeyobj = self.key_repr.get_ll_dummyval_obj(self.rtyper, s_key) dummyvalueobj = self.value_repr.get_ll_dummyval_obj(self.rtyper, s_value) # * the state of the entry - trying to encode it as dummy objects if nullkeymarker and dummykeyobj: # all the state can be encoded in the key entrymeths['everused'] = ll_everused_from_key entrymeths['dummy_obj'] = dummykeyobj entrymeths['valid'] = ll_valid_from_key entrymeths['mark_deleted'] = ll_mark_deleted_in_key # the key is overwritten by 'dummy' when the entry is deleted entrymeths['must_clear_key'] = False elif nullvaluemarker and dummyvalueobj: # all the state can be encoded in the value entrymeths['everused'] = ll_everused_from_value entrymeths['dummy_obj'] = dummyvalueobj entrymeths['valid'] = ll_valid_from_value entrymeths['mark_deleted'] = ll_mark_deleted_in_value # value is overwritten by 'dummy' when entry is deleted entrymeths['must_clear_value'] = False else: # we need a flag to know if the entry was ever used # (we cannot use a NULL as a marker for this, because # the key and value will be reset to NULL to clear their # reference) entryfields.append(("f_everused", lltype.Bool)) entrymeths['everused'] = ll_everused_from_flag # can we still rely on a dummy obj to mark deleted entries? if dummykeyobj: entrymeths['dummy_obj'] = dummykeyobj entrymeths['valid'] = ll_valid_from_key entrymeths['mark_deleted'] = ll_mark_deleted_in_key # key is overwritten by 'dummy' when entry is deleted entrymeths['must_clear_key'] = False elif dummyvalueobj: entrymeths['dummy_obj'] = dummyvalueobj entrymeths['valid'] = ll_valid_from_value entrymeths['mark_deleted'] = ll_mark_deleted_in_value # value is overwritten by 'dummy' when entry is deleted entrymeths['must_clear_value'] = False else: entryfields.append(("f_valid", lltype.Bool)) entrymeths['valid'] = ll_valid_from_flag entrymeths['mark_deleted'] = ll_mark_deleted_in_flag # * the value entryfields.append(("value", self.DICTVALUE)) # * the hash, if needed if self.custom_eq_hash: fasthashfn = None else: fasthashfn = self.key_repr.get_ll_fasthash_function() if fasthashfn is None: entryfields.append(("f_hash", lltype.Signed)) entrymeths['hash'] = ll_hash_from_cache else: entrymeths['hash'] = ll_hash_recomputed entrymeths['fasthashfn'] = fasthashfn # Build the lltype data structures self.DICTENTRY = lltype.Struct("dictentry", *entryfields) self.DICTENTRYARRAY = lltype.GcArray(self.DICTENTRY, adtmeths=entrymeths) fields = [ ("num_items", lltype.Signed), ("resize_counter", lltype.Signed), ("entries", lltype.Ptr(self.DICTENTRYARRAY)) ] if self.custom_eq_hash: self.r_rdict_eqfn, self.r_rdict_hashfn = self._custom_eq_hash_repr() fields.extend([ ("fnkeyeq", self.r_rdict_eqfn.lowleveltype), ("fnkeyhash", self.r_rdict_hashfn.lowleveltype) ]) adtmeths = { 'keyhash': ll_keyhash_custom, 'keyeq': ll_keyeq_custom, 'r_rdict_eqfn': self.r_rdict_eqfn, 'r_rdict_hashfn': self.r_rdict_hashfn, 'paranoia': True, } else: # figure out which functions must be used to hash and compare ll_keyhash = self.key_repr.get_ll_hash_function() ll_keyeq = self.key_repr.get_ll_eq_function() # can be None ll_keyhash = lltype.staticAdtMethod(ll_keyhash) if ll_keyeq is not None: ll_keyeq = lltype.staticAdtMethod(ll_keyeq) adtmeths = { 'keyhash': ll_keyhash, 'keyeq': ll_keyeq, 'paranoia': False, } adtmeths['KEY'] = self.DICTKEY adtmeths['VALUE'] = self.DICTVALUE adtmeths['allocate'] = lltype.typeMethod(_ll_malloc_dict) self.DICT.become(lltype.GcStruct("dicttable", adtmeths=adtmeths, *fields))
copycontentsfn(ll_builder.buf, newbuf, 0, 0, ll_builder.allocated) ll_builder.buf = newbuf ll_builder.allocated = new_allocated return func_with_new_name(stringbuilder_grow, name) stringbuilder_grow = new_grow_func("stringbuilder_grow", rstr.mallocstr, rstr.copy_string_contents) unicodebuilder_grow = new_grow_func("unicodebuilder_grow", rstr.mallocunicode, rstr.copy_unicode_contents) STRINGBUILDER = lltype.GcStruct( "stringbuilder", ("allocated", lltype.Signed), ("used", lltype.Signed), ("buf", lltype.Ptr(STR)), adtmeths={"grow": staticAdtMethod(stringbuilder_grow)}, ) UNICODEBUILDER = lltype.GcStruct( "unicodebuilder", ("allocated", lltype.Signed), ("used", lltype.Signed), ("buf", lltype.Ptr(UNICODE)), adtmeths={"grow": staticAdtMethod(unicodebuilder_grow)}, ) MAX = 16 * 1024 * 1024 class BaseStringBuilderRepr(AbstractStringBuilderRepr): @classmethod
return hop.gendirectcall(cls.ll_join_strs, size, vtemp) do_stringformat = classmethod(do_stringformat) TEMP = GcArray(Ptr(STR)) # ____________________________________________________________ STR.become( GcStruct( "rpy_string", ("hash", Signed), ("chars", Array(Char, hints={"immutable": True})), adtmeths={ "malloc": staticAdtMethod(mallocstr), "empty": staticAdtMethod(emptystrfun), "copy_contents": staticAdtMethod(copy_string_contents), "gethash": LLHelpers.ll_strhash, }, ) ) UNICODE.become( GcStruct( "rpy_unicode", ("hash", Signed), ("chars", Array(UniChar, hints={"immutable": True})), adtmeths={ "malloc": staticAdtMethod(mallocunicode), "empty": staticAdtMethod(emptyunicodefun), "copy_contents": staticAdtMethod(copy_unicode_contents),
mallocunicode = new_malloc(UNICODE) def emptystrfun(): return emptystr def emptyunicodefun(): return emptyunicode STR.become( GcStruct('rpy_string', ('hash', Signed), ('chars', Array(Char, hints={'immutable': True})), adtmeths={ 'malloc': staticAdtMethod(mallocstr), 'empty': staticAdtMethod(emptystrfun) })) UNICODE.become( GcStruct('rpy_unicode', ('hash', Signed), ('chars', Array(UniChar, hints={'immutable': True})), adtmeths={ 'malloc': staticAdtMethod(mallocunicode), 'empty': staticAdtMethod(emptyunicodefun) })) SIGNED_ARRAY = GcArray(Signed) CONST_STR_CACHE = WeakValueDictionary() CONST_UNICODE_CACHE = WeakValueDictionary() class BaseLLStringRepr(Repr):
# We don't store a NULL value, but a dead weakref, because # the entry must still be marked as everused(). d.entries[i].value = llmemory.dead_wref d.entries[i].key = lltype.nullptr(rstr.STR) #llop.debug_print(lltype.Void, i, 'zero') def ll_weakdict_resize(d): # first set num_items to its correct, up-to-date value entries = d.entries num_items = 0 for i in range(len(entries)): if entries.valid(i): num_items += 1 d.num_items = num_items rdict.ll_dict_resize(d) str_keyeq = lltype.staticAdtMethod(rstr.string_repr.get_ll_eq_function()) dictmeths = { 'll_get': ll_get, 'll_set': ll_set, 'keyeq': str_keyeq, 'paranoia': False, } WEAKDICT = lltype.GcStruct("weakdict", ("num_items", lltype.Signed), ("num_pristine_entries", lltype.Signed), ("entries", lltype.Ptr(WEAKDICTENTRYARRAY)), adtmeths=dictmeths)
from pypy.rpython.lltypesystem.rstr import string_repr vchunk = inputconst(string_repr, thing) i = inputconst(Signed, i) hop.genop('setarrayitem', [vtemp, i, vchunk]) hop.exception_cannot_occur() # to ignore the ZeroDivisionError of '%' return hop.gendirectcall(cls.ll_join_strs, size, vtemp) do_stringformat = classmethod(do_stringformat) TEMP = GcArray(Ptr(STR)) # ____________________________________________________________ STR.become(GcStruct('rpy_string', ('hash', Signed), ('chars', Array(Char, hints={'immutable': True})), adtmeths={'malloc' : staticAdtMethod(mallocstr), 'empty' : staticAdtMethod(emptystrfun), 'copy_contents' : staticAdtMethod(copy_string_contents), 'gethash': LLHelpers.ll_strhash})) UNICODE.become(GcStruct('rpy_unicode', ('hash', Signed), ('chars', Array(UniChar, hints={'immutable': True})), adtmeths={'malloc' : staticAdtMethod(mallocunicode), 'empty' : staticAdtMethod(emptyunicodefun), 'copy_contents' : staticAdtMethod(copy_unicode_contents), 'gethash': LLHelpers.ll_strhash} )) # TODO: make the public interface of the rstr module cleaner ll_strconcat = LLHelpers.ll_strconcat ll_join = LLHelpers.ll_join
return r mallocstr._annspecialcase_ = 'specialize:semierased' return mallocstr mallocstr = new_malloc(STR) mallocunicode = new_malloc(UNICODE) def emptystrfun(): return emptystr def emptyunicodefun(): return emptyunicode STR.become(GcStruct('rpy_string', ('hash', Signed), ('chars', Array(Char, hints={'immutable': True})), adtmeths={'malloc' : staticAdtMethod(mallocstr), 'empty' : staticAdtMethod(emptystrfun)})) UNICODE.become(GcStruct('rpy_unicode', ('hash', Signed), ('chars', Array(UniChar, hints={'immutable': True})), adtmeths={'malloc' : staticAdtMethod(mallocunicode), 'empty' : staticAdtMethod(emptyunicodefun)} )) SIGNED_ARRAY = GcArray(Signed) CONST_STR_CACHE = WeakValueDictionary() CONST_UNICODE_CACHE = WeakValueDictionary() class BaseLLStringRepr(Repr): def convert_const(self, value): if value is None: return nullptr(self.lowleveltype.TO) #value = getattr(value, '__self__', value) # for bound string methods