Пример #1
0
    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)
Пример #2
0
    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)
Пример #3
0
    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")]
Пример #4
0
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'
Пример #5
0
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'
Пример #6
0
    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 = {}
Пример #7
0
    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")]
Пример #8
0
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),
Пример #9
0
    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))
Пример #10
0
    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)
Пример #11
0

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)),
Пример #12
0
    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))
Пример #13
0
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
Пример #14
0
        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
Пример #15
0
_, _, 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
Пример #16
0
        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}
Пример #17
0
    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),
Пример #18
0
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