Source

pypy / pypy / rpython / memory / lldict.py

Full commit
Maciej Fijalkows… 66e4dc3 


Armin Rigo 96e2837 
Maciej Fijalkows… 66e4dc3 






































Armin Rigo 96e2837 

Maciej Fijalkows… 66e4dc3 







































Armin Rigo aab5186 
Maciej Fijalkows… 66e4dc3 












from pypy.rpython.lltypesystem import lltype, llmemory
from pypy.rpython.lltypesystem import rdict
from pypy.rlib.objectmodel import we_are_translated
from pypy.rpython.memory.support import mangle_hash

# This is a low-level AddressDict, reusing a lot of the logic from rdict.py.
# xxx this is very dependent on the details of rdict.py

alloc_count = 0     # for debugging

def count_alloc(delta):
    "NOT_RPYTHON"
    global alloc_count
    alloc_count += delta


def newdict(length_estimate=0):
    return rdict.ll_newdict_size(DICT, length_estimate)

def dict_allocate():
    if not we_are_translated(): count_alloc(+1)
    return lltype.malloc(DICT, flavor="raw")

def dict_delete(d):
    dict_delete_entries(d.entries)
    lltype.free(d, flavor="raw")
    if not we_are_translated(): count_alloc(-1)

def dict_allocate_entries(n):
    if not we_are_translated(): count_alloc(+1)
    # 'raw zero varsize malloc with length field' is not really implemented.
    # we can initialize the memory to zero manually
    entries = lltype.malloc(ENTRIES, n, flavor="raw")
    i = 0
    while i < n:
        entries[i].key = llmemory.NULL
        i += 1
    return entries

def dict_delete_entries(entries):
    lltype.free(entries, flavor="raw")
    if not we_are_translated(): count_alloc(-1)

def _hash(adr):
    return mangle_hash(llmemory.cast_adr_to_int(adr))

def dict_keyhash(d, key):
    return _hash(key)

def dict_entry_valid(entries, i):
    return entries[i].key != llmemory.NULL

def dict_entry_hash(entries, i):
    return _hash(entries[i].key)

def dict_get(d, key, default=llmemory.NULL):
    return rdict.ll_get(d, key, default)

def dict_add(d, key):
    rdict.ll_dict_setitem(d, key, llmemory.NULL)

def dict_insertclean(d, key, value):
    rdict.ll_dict_insertclean(d, key, value, _hash(key))

def dict_foreach(d, callback, arg):
    entries = d.entries
    i = len(entries) - 1
    while i >= 0:
        if dict_entry_valid(entries, i):
            callback(entries[i].key, entries[i].value, arg)
        i -= 1
dict_foreach._annspecialcase_ = 'specialize:arg(1)'

ENTRY = lltype.Struct('ENTRY', ('key', llmemory.Address),
                               ('value', llmemory.Address))
ENTRIES = lltype.Array(ENTRY,
                       adtmeths = {
                           'allocate': dict_allocate_entries,
                           'delete': dict_delete_entries,
                           'valid': dict_entry_valid,
                           'everused': dict_entry_valid,
                           'hash': dict_entry_hash,
                       })
DICT = lltype.Struct('DICT', ('entries', lltype.Ptr(ENTRIES)),
                             ('num_items', lltype.Signed),
                             ('resize_counter', lltype.Signed),
                     adtmeths = {
                         'allocate': dict_allocate,
                         'delete': dict_delete,
                         'length': rdict.ll_dict_len,
                         'contains': rdict.ll_contains,
                         'setitem': rdict.ll_dict_setitem,
                         'get': dict_get,
                         'add': dict_add,
                         'insertclean': dict_insertclean,
                         'clear': rdict.ll_clear,
                         'foreach': dict_foreach,
                         'keyhash': dict_keyhash,
                         'keyeq': None,
                     })