[pypy-svn] r13753 - in pypy/dist/pypy/rpython: . test
arigo at codespeak.net
arigo at codespeak.net
Thu Jun 23 22:00:05 CEST 2005
Author: arigo
Date: Thu Jun 23 22:00:03 2005
New Revision: 13753
Modified:
pypy/dist/pypy/rpython/llinterp.py
pypy/dist/pypy/rpython/rdict.py
pypy/dist/pypy/rpython/rstr.py
pypy/dist/pypy/rpython/test/test_rdict.py
Log:
(arigo, arre, hpk)
- CPython-style resizing of rdictionaries.
- added support for r_uint and intmask in llinterp
- fixed the hash for rstrings.
Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py (original)
+++ pypy/dist/pypy/rpython/llinterp.py Thu Jun 23 22:00:03 2005
@@ -265,6 +265,10 @@
from pypy.objspace.flow.operation import FunctionByName
opimpls = FunctionByName.copy()
opimpls['is_true'] = bool
+ops_returning_a_bool = {'gt': True, 'ge': True,
+ 'lt': True, 'le': True,
+ 'eq': True, 'ne': True,
+ 'is_true': True}
for typ in (float, int, r_uint):
typname = typ.__name__
@@ -277,21 +281,29 @@
optup += 'truediv', 'floordiv', 'and_', 'or_', 'lshift', 'rshift', 'xor'
for opname in optup:
assert opname in opimpls
+ if typ is int and opname not in ops_returning_a_bool:
+ adjust_result = 'intmask'
+ else:
+ adjust_result = ''
pureopname = opname.rstrip('_')
exec py.code.Source("""
def %(opnameprefix)s_%(pureopname)s(x, y):
assert isinstance(x, %(typname)s)
assert isinstance(y, %(typname)s)
func = opimpls[%(opname)r]
- return func(x, y)
+ return %(adjust_result)s(func(x, y))
""" % locals()).compile()
for opname in 'is_true', 'neg':
assert opname in opimpls
+ if typ is int and opname not in ops_returning_a_bool:
+ adjust_result = 'intmask'
+ else:
+ adjust_result = ''
exec py.code.Source("""
def %(opnameprefix)s_%(opname)s(x):
assert isinstance(x, %(typname)s)
func = opimpls[%(opname)r]
- return func(x)
+ return %(adjust_result)s(func(x))
""" % locals()).compile()
for opname in ('gt', 'lt', 'ge', 'ne', 'le', 'eq'):
Modified: pypy/dist/pypy/rpython/rdict.py
==============================================================================
--- pypy/dist/pypy/rpython/rdict.py (original)
+++ pypy/dist/pypy/rpython/rdict.py Thu Jun 23 22:00:03 2005
@@ -17,7 +17,8 @@
# }
#
# struct dicttable {
-# int num_used_entries;
+# int num_items;
+# int num_pristine_entries; # never used entries
# Array *entries;
# }
#
@@ -59,7 +60,8 @@
('value', self.DICTVALUE))
self.DICTENTRYARRAY = lltype.GcArray(self.DICTENTRY)
self.STRDICT.become(lltype.GcStruct("dicttable",
- ("num_used_entries", lltype.Signed),
+ ("num_items", lltype.Signed),
+ ("num_pristine_entries", lltype.Signed),
("entries", lltype.Ptr(self.DICTENTRYARRAY))))
#def convert_const(self, dictobj):
@@ -126,7 +128,7 @@
deleted_entry_marker = lltype.malloc(STR, 0, immortal=True)
def ll_strdict_len(d):
- return d.num_used_entries
+ return d.num_items
def ll_strdict_getitem(d, key):
entry = ll_strdict_lookup(d, key)
@@ -137,13 +139,17 @@
def ll_strdict_setitem(d, key, value):
entry = ll_strdict_lookup(d, key)
- if not entry.key or entry.key == deleted_entry_marker:
+ if not entry.key:
+ entry.key = key
+ entry.value = value
+ d.num_items += 1
+ d.num_pristine_entries -= 1
+ if d.num_pristine_entries <= len(d.entries) / 3:
+ ll_strdict_resize(d)
+ elif entry.key == deleted_entry_marker:
entry.key = key
entry.value = value
- d.num_used_entries += 1
- if d.num_used_entries / 2 > len(d.entries) / 3:
- ll_strdict_resize(d, len(d.entries) * 2)
-
+ d.num_items += 1
else:
entry.value = value
@@ -152,13 +158,19 @@
if not entry.key or entry.key == deleted_entry_marker:
raise KeyError
entry.key = deleted_entry_marker
- d.num_used_entries -= 1
+ d.num_items -= 1
# XXX: entry.value = ???
-def ll_strdict_resize(d, new_size):
+def ll_strdict_resize(d):
old_entries = d.entries
old_size = len(old_entries)
+ # make a 'new_size' estimate and shrink it if there are many
+ # deleted entry markers
+ new_size = old_size * 2
+ while new_size >= 8 and d.num_items < new_size / 4:
+ new_size /= 2
d.entries = lltype.malloc(lltype.typeOf(old_entries).TO, new_size)
+ d.num_pristine_entries = new_size - d.num_items
i = 0
while i < old_size:
entry = old_entries[i]
@@ -207,11 +219,13 @@
# ____________________________________________________________
#
# Irregular operations.
+STRDICT_INITSIZE = 8
def ll_newstrdict(DICTPTR):
d = lltype.malloc(DICTPTR.TO)
- d.entries = lltype.malloc(DICTPTR.TO.entries.TO, 8) # everything is zeroed
- d.num_used_entries = 0 # but still be explicit
+ d.entries = lltype.malloc(DICTPTR.TO.entries.TO, STRDICT_INITSIZE)
+ d.num_items = 0 # but still be explicit
+ d.num_pristine_entries = STRDICT_INITSIZE
return d
def rtype_newdict(hop):
@@ -222,52 +236,3 @@
v_result = hop.gendirectcall(ll_newstrdict, c1)
return v_result
-# ____________________________________________________________
-#
-# Iteration.
-
-if 0:
- class ListIteratorRepr(Repr):
-
- def __init__(self, r_list):
- self.r_list = r_list
- self.lowleveltype = lltype.Ptr(GcStruct('listiter',
- ('list', r_list.lowleveltype),
- ('index', Signed)))
-
- def newiter(self, hop):
- v_lst, = hop.inputargs(self.r_list)
- citerptr = hop.inputconst(Void, self.lowleveltype)
- return hop.gendirectcall(ll_listiter, citerptr, v_lst)
-
- def rtype_next(self, hop):
- v_iter, = hop.inputargs(self)
- return hop.gendirectcall(ll_listnext, v_iter)
-
- def ll_listiter(ITERPTR, lst):
- iter = malloc(ITERPTR.TO)
- iter.list = lst
- iter.index = 0
- return iter
-
- def ll_listnext(iter):
- l = iter.list
- index = iter.index
- if index >= len(l.items):
- raise StopIteration
- iter.index = index + 1
- return l.items[index]
-
-
- keyhash = rstr.ll_strhash(key)
- n = len(d.entries)
- index = keyhash & (n - 1)
- while 1:
- entry = d.entries[index]
- if not entry.key or en:
- break
- if entry.key != deleted_entry_marker and rstr.ll_streq(entry.key, key):
- break
- index = (index + 1) & (n-1)
- #return entry
-
Modified: pypy/dist/pypy/rpython/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/rstr.py (original)
+++ pypy/dist/pypy/rpython/rstr.py Thu Jun 23 22:00:03 2005
@@ -365,7 +365,7 @@
x = -1
else:
x = ord(s.chars[0]) << 7
- i = 1
+ i = 0
while i < length:
x = (1000003*x) ^ ord(s.chars[i])
i += 1
Modified: pypy/dist/pypy/rpython/test/test_rdict.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rdict.py (original)
+++ pypy/dist/pypy/rpython/test/test_rdict.py Thu Jun 23 22:00:03 2005
@@ -77,16 +77,16 @@
del d[c1]
return d[c2]
+ char_by_hash = {}
base = 8
- x = 'a'
- xh = lowlevelhash(x) % base
- for y in range(ord('b'), ord('z')):
- if lowlevelhash(chr(y)) % base == xh:
- break
- else:
- py.test.skip("XXX improve hash finding algo")
+ for y in range(0, 256):
+ y = chr(y)
+ y_hash = lowlevelhash(y) % base
+ char_by_hash.setdefault(y_hash, []).append(y)
+
+ x, y = char_by_hash[0][:2] # find a collision
- res = interpret(func, [ord(x), y])
+ res = interpret(func, [ord(x), ord(y)])
assert res == 2
def func2(c1, c2):
@@ -99,10 +99,29 @@
d[c1] = 3
return d
- res = interpret(func2, [ord(x), y])
+ res = interpret(func2, [ord(x), ord(y)])
for i in range(len(res.entries)):
assert res.entries[i].key != rdict.deleted_entry_marker
+ def func3(c0, c1, c2, c3, c4, c5, c6, c7):
+ d = {}
+ c0 = chr(c0) ; d[c0] = 1; del d[c0]
+ c1 = chr(c1) ; d[c1] = 1; del d[c1]
+ c2 = chr(c2) ; d[c2] = 1; del d[c2]
+ c3 = chr(c3) ; d[c3] = 1; del d[c3]
+ c4 = chr(c4) ; d[c4] = 1; del d[c4]
+ c5 = chr(c5) ; d[c5] = 1; del d[c5]
+ c6 = chr(c6) ; d[c6] = 1; del d[c6]
+ c7 = chr(c7) ; d[c7] = 1; del d[c7]
+ return d
+
+ res = interpret(func3, [ord(char_by_hash[i][0]) for i in range(8)])
+ count_frees = 0
+ for i in range(len(res.entries)):
+ if not res.entries[i].key:
+ count_frees += 1
+ assert count_frees >= 3
+
def test_dict_resize():
def func():
d = {}
More information about the Pypy-commit
mailing list