Author: Maciej Fijalkowski <fij...@gmail.com> Branch: rdict-experiments-2 Changeset: r59813:0d9d5d21c955 Date: 2013-01-06 20:28 +0200 http://bitbucket.org/pypy/pypy/changeset/0d9d5d21c955/
Log: hack hack fix fix test test diff --git a/pypy/rpython/lltypesystem/opimpl.py b/pypy/rpython/lltypesystem/opimpl.py --- a/pypy/rpython/lltypesystem/opimpl.py +++ b/pypy/rpython/lltypesystem/opimpl.py @@ -525,6 +525,8 @@ A = lltype.typeOf(source) assert A == lltype.typeOf(dest) assert isinstance(A.TO, lltype.GcArray) + if isinstance(A.TO.OF, lltype.Struct): + return True assert isinstance(A.TO.OF, lltype.Ptr) assert A.TO.OF.TO._gckind == 'gc' assert type(source_start) is int diff --git a/pypy/rpython/lltypesystem/rdict.py b/pypy/rpython/lltypesystem/rdict.py --- a/pypy/rpython/lltypesystem/rdict.py +++ b/pypy/rpython/lltypesystem/rdict.py @@ -78,10 +78,12 @@ DICTENTRY = lltype.Struct("dictentry", *entryfields) DICTENTRYARRAY = lltype.GcArray(DICTENTRY, adtmeths=entrymeths) + array_adtmeths = {'allocate': lltype.typeMethod(_ll_malloc_items)} fields = [("num_items", lltype.Signed), ("resize_counter", lltype.Signed), ("entries", lltype.Ptr(DICTENTRYARRAY)), - ("indexes", lltype.Ptr(lltype.GcArray(lltype.Signed)))] + ("indexes", lltype.Ptr(lltype.GcArray(lltype.Signed, + adtmeths=array_adtmeths)))] 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), @@ -368,9 +370,12 @@ i = ll_dict_lookup(d, key, hash) return _ll_dict_setitem_lookup_done(d, key, value, hash, i) +def _look_inside_setitem(d, key, value, hash, i): + return jit.isvirtual(d) and jit.isconstant(key) + # It may be safe to look inside always, it has a few branches though, and their # frequencies needs to be investigated. -@jit.look_inside_iff(lambda d, key, value, hash, i: jit.isvirtual(d) and jit.isconstant(key)) +@jit.look_inside_iff(_look_inside_setitem) def _ll_dict_setitem_lookup_done(d, key, value, hash, i): valid = (i & HIGHEST_BIT) == 0 i = i & MASK @@ -384,7 +389,7 @@ rc = d.resize_counter - 3 if rc <= 0: # if needed, resize the dict -- before the insertion ll_dict_resize(d) - index = d.indexes[ll_dict_lookup_clean(d, hash)] + i = ll_dict_lookup_clean(d, hash) # then redo the lookup for 'key' entry = d.entries[index] rc = d.resize_counter - 3 @@ -483,7 +488,7 @@ # new_item_size = new_size // 3 * 2 + 1 d.entries = lltype.typeOf(old_entries).TO.allocate(new_item_size) - d.indexes = lltype.malloc(lltype.typeOf(d).TO.indexes.TO, new_size) + d.indexes = lltype.typeOf(d).TO.indexes.TO.allocate(new_size) d.num_items = len(old_entries) d.resize_counter = new_size * 2 i = 0 @@ -499,11 +504,13 @@ # ------- a port of CPython's dictobject.c's lookdict implementation ------- PERTURB_SHIFT = 5 -@jit.look_inside_iff(lambda d, key, hash: jit.isvirtual(d) and jit.isconstant(key)) +_look_inside_lookup = lambda d, key, hash: jit.isvirtual(d) and jit.isconstant(key) + +@jit.look_inside_iff(_look_inside_lookup) def ll_dict_lookup(d, key, hash): entries = d.entries indexes = d.indexes - mask = len(entries) - 1 + mask = len(indexes) - 1 i = hash & mask # do the first try before any looping index = indexes[i] @@ -572,7 +579,7 @@ mask = len(indexes) - 1 i = hash & mask perturb = r_uint(hash) - while i != FREE: + while d.indexes[i] != FREE: i = r_uint(i) i = (i << 2) + i + perturb + 1 i = intmask(i) & mask @@ -584,11 +591,13 @@ # Irregular operations. DICT_INITSIZE = 8 -DICT_ITEMS_INITSIZE = 5 +DICT_ITEMS_INITSIZE = 6 @jit.unroll_safe # we always unroll the small allocation def ll_newdict(DICT): d = DICT.allocate() + # XXX don't use _ll_items_allocate because of jit.unroll_safe, + # should be *really* jit_unroll_iff d.indexes = lltype.malloc(DICT.indexes.TO, DICT_INITSIZE) for i in range(DICT_INITSIZE): d.indexes[i] = FREE @@ -605,7 +614,7 @@ items_size = n // 3 * 2 + 1 d = DICT.allocate() d.entries = DICT.entries.TO.allocate(items_size) - d.indexes = lltype.malloc(DICT.indexes.TO, n) + d.indexes = DICT.indexes.TO.allocate(n) d.num_items = 0 d.resize_counter = n * 2 return d @@ -617,7 +626,13 @@ return lltype.malloc(DICT) def _ll_malloc_entries(ENTRIES, n): return lltype.malloc(ENTRIES, n, zero=True) - +def _ll_malloc_items(ITEMS, n): + res = lltype.malloc(ITEMS, n) + i = 0 + while i < n: + res[i] = FREE + i += 1 + return res def rtype_r_dict(hop): r_dict = hop.r_result @@ -739,12 +754,12 @@ ll_copy.oopspec = 'dict.copy(dict)' def ll_clear(d): - xxx - if (len(d.entries) == DICT_INITSIZE and + if (len(d.indexes) == DICT_INITSIZE and d.resize_counter == DICT_INITSIZE * 2): return old_entries = d.entries - d.entries = lltype.typeOf(old_entries).TO.allocate(DICT_INITSIZE) + d.entries = lltype.typeOf(old_entries).TO.allocate(DICT_ITEMS_INITSIZE) + d.indexes = lltype.typeOf(d).TO.indexes.TO.allocate(DICT_INITSIZE) d.num_items = 0 d.resize_counter = DICT_INITSIZE * 2 ll_clear.oopspec = 'dict.clear(d)' diff --git a/pypy/rpython/test/test_rdict.py b/pypy/rpython/test/test_rdict.py --- a/pypy/rpython/test/test_rdict.py +++ b/pypy/rpython/test/test_rdict.py @@ -63,6 +63,18 @@ rdict.DICT_INITSIZE - 2) assert (len([i for i in ll_d.indexes if i == rdict.DELETED]) == 1) + def test_dict_resize(self): + DICT = self._get_str_dict() + ll_d = rdict.ll_newdict(DICT) + rdict.ll_dict_setitem(ll_d, llstr("a"), 1) + rdict.ll_dict_setitem(ll_d, llstr("b"), 2) + rdict.ll_dict_setitem(ll_d, llstr("c"), 3) + rdict.ll_dict_setitem(ll_d, llstr("d"), 4) + rdict.ll_dict_setitem(ll_d, llstr("e"), 5) + assert len(ll_d.indexes) == 8 + rdict.ll_dict_setitem(ll_d, llstr("f"), 6) + assert len(ll_d.indexes) == 32 + class BaseTestRdict(BaseRtypingTest): def test_dict_creation(self): _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit