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(p, x, y, z): p.x = x if p.yep: z *= p.callme(y) return z def f(x, y, z): p = lltype.malloc(S) return g(p, 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 test_staticadtmeths(): ll_func = lltype.staticAdtMethod(lambda x: x + 42) S = lltype.GcStruct('S', adtmeths={'ll_func': ll_func}) def f(): return lltype.malloc(S).ll_func(5) s, t = ll_rtype(f, []) graphf = t.graphs[0] for op in graphf.startblock.operations: assert op.opname != 'getfield'
def test_staticadtmeths(): ll_func = lltype.staticAdtMethod(lambda x: x + 42) S = lltype.GcStruct('S', adtmeths={'ll_func': ll_func}) def f(): return lltype.malloc(S).ll_func(5) s, t = ll_rtype(f, []) graphf = t.graphs[0] for op in graphf.startblock.operations: assert op.opname != 'getfield'
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(p, x, y, z): p.x = x if p.yep: z *= p.callme(y) return z def f(x, y, z): p = lltype.malloc(S) return g(p, 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")]
TEMP = GcArray(Ptr(STR)) TEMP_UNICODE = GcArray(Ptr(UNICODE)) # ____________________________________________________________ STR.become( GcStruct( 'rpy_string', ('hash', Signed), ('chars', Array(Char, hints={ 'immutable': True, 'extra_item_after_alloc': 1 })), adtmeths={ 'malloc': staticAdtMethod(mallocstr), 'empty': staticAdtMethod(emptystrfun), 'copy_contents': staticAdtMethod(copy_string_contents), 'copy_contents_from_str': staticAdtMethod(copy_string_contents), 'gethash': LLHelpers.ll_strhash, 'length': LLHelpers.ll_length, 'find': LLHelpers.ll_find, 'rfind': LLHelpers.ll_rfind }, hints={'remove_hash': True})) UNICODE.become( GcStruct('rpy_unicode', ('hash', Signed), ('chars', Array(UniChar, hints={'immutable': True})), adtmeths={ 'malloc': staticAdtMethod(mallocunicode), 'empty': staticAdtMethod(emptyunicodefun),
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 getattr(self.key_repr.get_ll_eq_function(), 'no_direct_compare', False): entrymeths['no_direct_compare'] = True 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))
return lltype.malloc(BYTEARRAY, size) _, _, copy_bytearray_contents = rstr._new_copy_contents_fun(BYTEARRAY, BYTEARRAY, lltype.Char, 'bytearray') _, _, copy_bytearray_contents_from_str = rstr._new_copy_contents_fun(rstr.STR, BYTEARRAY, lltype.Char, 'bytearray_from_str') def _empty_bytearray(): return empty BYTEARRAY.become(lltype.GcStruct('rpy_bytearray', ('chars', lltype.Array(lltype.Char)), adtmeths={ 'malloc' : lltype.staticAdtMethod(mallocbytearray), 'copy_contents' : lltype.staticAdtMethod(copy_bytearray_contents), 'copy_contents_from_str': lltype.staticAdtMethod( copy_bytearray_contents_from_str), 'length': rstr.LLHelpers.ll_length, 'empty': lltype.staticAdtMethod(_empty_bytearray), })) empty = lltype.malloc(BYTEARRAY, 0, immortal=True) class LLHelpers(rstr.LLHelpers): @classmethod def ll_strsetitem(cls, s, i, item): if i < 0: i += s.length() cls.ll_strsetitem_nonneg(s, i, item)
STRINGPIECE = lltype.GcStruct( 'stringpiece', ('buf', lltype.Ptr(STR)), ('prev_piece', lltype.Ptr(lltype.GcForwardReference()))) STRINGPIECE.prev_piece.TO.become(STRINGPIECE) STRINGBUILDER = lltype.GcStruct('stringbuilder', ('current_buf', lltype.Ptr(STR)), ('current_pos', lltype.Signed), ('current_end', lltype.Signed), ('total_size', lltype.Signed), ('extra_pieces', lltype.Ptr(STRINGPIECE)), adtmeths={ 'copy_string_contents': staticAdtMethod(rstr.copy_string_contents), 'copy_raw_to_string': staticAdtMethod(rstr.copy_raw_to_string), 'mallocfn': staticAdtMethod(rstr.mallocstr), }) UNICODEPIECE = lltype.GcStruct( 'unicodepiece', ('buf', lltype.Ptr(UNICODE)), ('prev_piece', lltype.Ptr(lltype.GcForwardReference()))) UNICODEPIECE.prev_piece.TO.become(UNICODEPIECE) UNICODEBUILDER = lltype.GcStruct( 'unicodebuilder', ('current_buf', lltype.Ptr(UNICODE)), ('current_pos', lltype.Signed), ('current_end', lltype.Signed), ('total_size', lltype.Signed), ('extra_pieces', lltype.Ptr(UNICODEPIECE)),
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))
def get_ll_dict( DICTKEY, DICTVALUE, get_custom_eq_hash=None, DICT=None, ll_fasthash_function=None, ll_hash_function=None, ll_eq_function=None, method_cache={}, dummykeyobj=None, dummyvalueobj=None, rtyper=None, ): # get the actual DICT type. if DICT is None, it's created, otherwise # forward reference is becoming DICT if DICT is None: DICT = lltype.GcForwardReference() # compute the shape of the DICTENTRY structure entryfields = [] entrymeths = { "allocate": lltype.typeMethod(_ll_malloc_entries), "delete": _ll_free_entries, "must_clear_key": (isinstance(DICTKEY, lltype.Ptr) and DICTKEY._needsgc()), "must_clear_value": (isinstance(DICTVALUE, lltype.Ptr) and DICTVALUE._needsgc()), } if getattr(ll_eq_function, "no_direct_compare", False): entrymeths["no_direct_compare"] = True # * the key entryfields.append(("key", DICTKEY)) # * the state of the entry - trying to encode it as dummy objects if dummykeyobj: # all the state can be encoded in the 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 dummyvalueobj: # all the state can be encoded in the 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 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", DICTVALUE)) if ll_fasthash_function is None: entryfields.append(("f_hash", lltype.Signed)) entrymeths["hash"] = ll_hash_from_cache else: entrymeths["hash"] = ll_hash_recomputed entrymeths["fasthashfn"] = ll_fasthash_function # Build the lltype data structures DICTENTRY = lltype.Struct("odictentry", *entryfields) DICTENTRYARRAY = lltype.GcArray(DICTENTRY, adtmeths=entrymeths) fields = [ ("num_live_items", lltype.Signed), ("num_ever_used_items", lltype.Signed), ("resize_counter", lltype.Signed), ("indexes", llmemory.GCREF), ("lookup_function_no", lltype.Signed), ("entries", lltype.Ptr(DICTENTRYARRAY)), ] if get_custom_eq_hash is not None: r_rdict_eqfn, r_rdict_hashfn = get_custom_eq_hash() fields.extend([("fnkeyeq", r_rdict_eqfn.lowleveltype), ("fnkeyhash", r_rdict_hashfn.lowleveltype)]) adtmeths = { "keyhash": ll_keyhash_custom, "keyeq": ll_keyeq_custom, "r_rdict_eqfn": r_rdict_eqfn, "r_rdict_hashfn": r_rdict_hashfn, "paranoia": True, } else: # figure out which functions must be used to hash and compare ll_keyhash = ll_hash_function ll_keyeq = ll_eq_function 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"] = DICTKEY adtmeths["VALUE"] = DICTVALUE adtmeths["lookup_function"] = lltype.staticAdtMethod(ll_call_lookup_function) adtmeths["allocate"] = lltype.typeMethod(_ll_malloc_dict) DICT.become(lltype.GcStruct("dicttable", adtmeths=adtmeths, *fields)) return DICT
copycontentsfn(ll_builder.buf, newbuf, 0, 0, ll_builder.used) 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), 'copy_raw_to_string': staticAdtMethod(rstr.copy_raw_to_string), } ) UNICODEBUILDER = lltype.GcStruct('unicodebuilder', ('allocated', lltype.Signed), ('used', lltype.Signed), ('buf', lltype.Ptr(UNICODE)), adtmeths={ 'grow': staticAdtMethod(unicodebuilder_grow), 'copy_raw_to_string': staticAdtMethod(rstr.copy_raw_to_unicode), } ) MAX = 16*1024*1024
_, _, copy_bytearray_contents = rstr._new_copy_contents_fun( BYTEARRAY, BYTEARRAY, lltype.Char, 'bytearray') _, _, copy_bytearray_contents_from_str = rstr._new_copy_contents_fun( rstr.STR, BYTEARRAY, lltype.Char, 'bytearray_from_str') def _empty_bytearray(): return empty BYTEARRAY.become( lltype.GcStruct( 'rpy_bytearray', ('chars', lltype.Array(lltype.Char)), adtmeths={ 'malloc': lltype.staticAdtMethod(mallocbytearray), 'copy_contents': lltype.staticAdtMethod(copy_bytearray_contents), 'copy_contents_from_str': lltype.staticAdtMethod(copy_bytearray_contents_from_str), 'length': rstr.LLHelpers.ll_length, 'empty': lltype.staticAdtMethod(_empty_bytearray), })) empty = lltype.malloc(BYTEARRAY, 0, immortal=True) class LLHelpers(rstr.LLHelpers): @classmethod
adst = llmemory.cast_ptr_to_adr(dst) + llmemory.itemoffsetof(DST, 0) llmemory.raw_memcopy(asrc, adst, llmemory.sizeof(DST.OF) * length) # end of "no GC" section keepalive_until_here(src) keepalive_until_here(dst) return lst TEMP = GcArray(Ptr(STR)) TEMP_UNICODE = GcArray(Ptr(UNICODE)) # ____________________________________________________________ STR.become(GcStruct('rpy_string', ('hash', Signed), ('chars', Array(Char, hints={'immutable': True, 'extra_item_after_alloc': 1})), adtmeths={'malloc' : staticAdtMethod(mallocstr), 'empty' : staticAdtMethod(emptystrfun), 'copy_contents' : staticAdtMethod(copy_string_contents), 'copy_contents_from_str' : staticAdtMethod(copy_string_contents), 'gethash': LLHelpers.ll_strhash, 'length': LLHelpers.ll_length, 'find': LLHelpers.ll_find, 'rfind': LLHelpers.ll_rfind})) 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), 'copy_contents_from_str' : staticAdtMethod(copy_unicode_contents), 'gethash': LLHelpers.ll_strhash, 'length': LLHelpers.ll_length}
return func STRINGPIECE = lltype.GcStruct('stringpiece', ('buf', lltype.Ptr(STR)), ('prev_piece', lltype.Ptr(lltype.GcForwardReference()))) STRINGPIECE.prev_piece.TO.become(STRINGPIECE) STRINGBUILDER = lltype.GcStruct('stringbuilder', ('current_buf', lltype.Ptr(STR)), ('current_pos', lltype.Signed), ('current_end', lltype.Signed), ('total_size', lltype.Signed), ('extra_pieces', lltype.Ptr(STRINGPIECE)), adtmeths={ 'copy_string_contents': staticAdtMethod(rstr.copy_string_contents), 'copy_raw_to_string': staticAdtMethod(rstr.copy_raw_to_string), 'mallocfn': staticAdtMethod(rstr.mallocstr), } ) UNICODEPIECE = lltype.GcStruct('unicodepiece', ('buf', lltype.Ptr(UNICODE)), ('prev_piece', lltype.Ptr(lltype.GcForwardReference()))) UNICODEPIECE.prev_piece.TO.become(UNICODEPIECE) UNICODEBUILDER = lltype.GcStruct('unicodebuilder', ('current_buf', lltype.Ptr(UNICODE)), ('current_pos', lltype.Signed), ('current_end', lltype.Signed), ('total_size', lltype.Signed),
def get_ll_dict(DICTKEY, DICTVALUE, get_custom_eq_hash=None, DICT=None, ll_fasthash_function=None, ll_hash_function=None, ll_eq_function=None, method_cache={}, dummykeyobj=None, dummyvalueobj=None, rtyper=None): # get the actual DICT type. if DICT is None, it's created, otherwise # forward reference is becoming DICT if DICT is None: DICT = lltype.GcForwardReference() # compute the shape of the DICTENTRY structure entryfields = [] entrymeths = { 'allocate': lltype.typeMethod(_ll_malloc_entries), 'delete': _ll_free_entries, 'must_clear_key': (isinstance(DICTKEY, lltype.Ptr) and DICTKEY._needsgc()), 'must_clear_value': (isinstance(DICTVALUE, lltype.Ptr) and DICTVALUE._needsgc()), } if getattr(ll_eq_function, 'no_direct_compare', False): entrymeths['no_direct_compare'] = True # * the key entryfields.append(("key", DICTKEY)) # * the state of the entry - trying to encode it as dummy objects if dummykeyobj: # all the state can be encoded in the 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 dummyvalueobj: # all the state can be encoded in the 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 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", DICTVALUE)) if ll_fasthash_function is None: entryfields.append(("f_hash", lltype.Signed)) entrymeths['hash'] = ll_hash_from_cache else: entrymeths['hash'] = ll_hash_recomputed entrymeths['fasthashfn'] = ll_fasthash_function # Build the lltype data structures DICTENTRY = lltype.Struct("odictentry", *entryfields) DICTENTRYARRAY = lltype.GcArray(DICTENTRY, adtmeths=entrymeths) fields = [("num_live_items", lltype.Signed), ("num_ever_used_items", lltype.Signed), ("resize_counter", lltype.Signed), ("indexes", llmemory.GCREF), ("lookup_function_no", lltype.Signed), ("entries", lltype.Ptr(DICTENTRYARRAY))] if get_custom_eq_hash is not None: r_rdict_eqfn, r_rdict_hashfn = get_custom_eq_hash() fields.extend([("fnkeyeq", r_rdict_eqfn.lowleveltype), ("fnkeyhash", r_rdict_hashfn.lowleveltype)]) adtmeths = { 'keyhash': ll_keyhash_custom, 'keyeq': ll_keyeq_custom, 'r_rdict_eqfn': r_rdict_eqfn, 'r_rdict_hashfn': r_rdict_hashfn, 'paranoia': True, } else: # figure out which functions must be used to hash and compare ll_keyhash = ll_hash_function ll_keyeq = ll_eq_function 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'] = DICTKEY adtmeths['VALUE'] = DICTVALUE adtmeths['lookup_function'] = lltype.staticAdtMethod( ll_call_lookup_function) adtmeths['allocate'] = lltype.typeMethod(_ll_malloc_dict) DICT.become(lltype.GcStruct("dicttable", adtmeths=adtmeths, *fields)) return DICT