[pypy-svn] r40858 - in pypy/dist/pypy/rpython: lltypesystem test
arigo at codespeak.net
arigo at codespeak.net
Tue Mar 20 19:33:01 CET 2007
Author: arigo
Date: Tue Mar 20 19:33:00 2007
New Revision: 40858
Modified:
pypy/dist/pypy/rpython/lltypesystem/rdict.py
pypy/dist/pypy/rpython/test/test_rdict.py
Log:
The rdict logic was too clever. Unfortunately some tests check the
details of the cleverness, so here is an attempt to fix the clever
bit. Added stress-tests for more combinations.
Modified: pypy/dist/pypy/rpython/lltypesystem/rdict.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rdict.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/rdict.py Tue Mar 20 19:33:00 2007
@@ -92,30 +92,47 @@
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)
+ dummykeyobj = self.key_repr.get_ll_dummyval_obj(self.rtyper,
+ s_key)
+ dummyvalueobj = self.value_repr.get_ll_dummyval_obj(self.rtyper,
+ s_value)
- if nullkeymarker:
+ # * 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
- elif nullvaluemarker:
- entrymeths['everused'] = ll_everused_from_value
- else:
- entryfields.append(("f_everused", lltype.Bool))
- entrymeths['everused'] = ll_everused_from_flag
-
- # * if the key or the value can also contain a "dummy" non-null
- # marker, we use it for deleted entries.
- rtyper = self.rtyper
- dummy_obj = self.key_repr.get_ll_dummyval_obj(rtyper, s_key)
- if dummy_obj:
- entrymeths['dummy_obj'] = dummy_obj
+ 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:
- dummy_obj = self.value_repr.get_ll_dummyval_obj(rtyper,
- s_value)
- if dummy_obj:
- entrymeths['dummy_obj'] = dummy_obj
+ # 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
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 Tue Mar 20 19:33:00 2007
@@ -602,55 +602,6 @@
# ____________________________________________________________
- def test_stress(self):
- from pypy.annotation.dictdef import DictKey, DictValue
- from pypy.annotation import model as annmodel
- dictrepr = rdict.DictRepr(None, rint.signed_repr, rint.signed_repr,
- DictKey(None, annmodel.SomeInteger()),
- DictValue(None, annmodel.SomeInteger()))
- dictrepr.setup()
- l_dict = rdict.ll_newdict(dictrepr.DICT)
- referencetable = [None] * 400
- referencelength = 0
- value = 0
-
- def complete_check():
- for n, refvalue in zip(range(len(referencetable)), referencetable):
- try:
- gotvalue = rdict.ll_dict_getitem(l_dict, n)
- except KeyError:
- assert refvalue is None
- else:
- assert gotvalue == refvalue
-
- for x in not_really_random():
- n = int(x*100.0) # 0 <= x < 400
- op = repr(x)[-1]
- if op <= '2' and referencetable[n] is not None:
- rdict.ll_dict_delitem(l_dict, n)
- referencetable[n] = None
- referencelength -= 1
- elif op <= '6':
- rdict.ll_dict_setitem(l_dict, n, value)
- if referencetable[n] is None:
- referencelength += 1
- referencetable[n] = value
- value += 1
- else:
- try:
- gotvalue = rdict.ll_dict_getitem(l_dict, n)
- except KeyError:
- assert referencetable[n] is None
- else:
- assert gotvalue == referencetable[n]
- if 1.38 <= x <= 1.39:
- complete_check()
- print 'current dict length:', referencelength
- assert l_dict.num_items == referencelength
- complete_check()
-
- # ____________________________________________________________
-
def test_opt_nullkeymarker(self):
def f():
d = {"hello": None}
@@ -759,3 +710,120 @@
except RuntimeError:
return False
assert self.interpret(func, []) == False
+
+ # ____________________________________________________________
+
+class TestStress:
+
+ def test_stress(self):
+ from pypy.annotation.dictdef import DictKey, DictValue
+ from pypy.annotation import model as annmodel
+ dictrepr = rdict.DictRepr(None, rint.signed_repr, rint.signed_repr,
+ DictKey(None, annmodel.SomeInteger()),
+ DictValue(None, annmodel.SomeInteger()))
+ dictrepr.setup()
+ l_dict = rdict.ll_newdict(dictrepr.DICT)
+ referencetable = [None] * 400
+ referencelength = 0
+ value = 0
+
+ def complete_check():
+ for n, refvalue in zip(range(len(referencetable)), referencetable):
+ try:
+ gotvalue = rdict.ll_dict_getitem(l_dict, n)
+ except KeyError:
+ assert refvalue is None
+ else:
+ assert gotvalue == refvalue
+
+ for x in not_really_random():
+ n = int(x*100.0) # 0 <= x < 400
+ op = repr(x)[-1]
+ if op <= '2' and referencetable[n] is not None:
+ rdict.ll_dict_delitem(l_dict, n)
+ referencetable[n] = None
+ referencelength -= 1
+ elif op <= '6':
+ rdict.ll_dict_setitem(l_dict, n, value)
+ if referencetable[n] is None:
+ referencelength += 1
+ referencetable[n] = value
+ value += 1
+ else:
+ try:
+ gotvalue = rdict.ll_dict_getitem(l_dict, n)
+ except KeyError:
+ assert referencetable[n] is None
+ else:
+ assert gotvalue == referencetable[n]
+ if 1.38 <= x <= 1.39:
+ complete_check()
+ print 'current dict length:', referencelength
+ assert l_dict.num_items == referencelength
+ complete_check()
+
+ def test_stress_2(self):
+ yield self.stress_combination, True, False
+ yield self.stress_combination, False, True
+ yield self.stress_combination, False, False
+ yield self.stress_combination, True, True
+
+ def stress_combination(self, key_can_be_none, value_can_be_none):
+ from pypy.rpython.lltypesystem.rstr import string_repr
+ from pypy.annotation.dictdef import DictKey, DictValue
+ from pypy.annotation import model as annmodel
+
+ print
+ print "Testing combination with can_be_None: keys %s, values %s" % (
+ key_can_be_none, value_can_be_none)
+
+ class PseudoRTyper:
+ cache_dummy_values = {}
+ dictrepr = rdict.DictRepr(PseudoRTyper(), string_repr, string_repr,
+ DictKey(None, annmodel.SomeString(key_can_be_none)),
+ DictValue(None, annmodel.SomeString(value_can_be_none)))
+ dictrepr.setup()
+ print dictrepr.lowleveltype
+ for key, value in dictrepr.DICTENTRY._adtmeths.items():
+ print ' %s = %s' % (key, value)
+ l_dict = rdict.ll_newdict(dictrepr.DICT)
+ referencetable = [None] * 400
+ referencelength = 0
+ values = not_really_random()
+ keytable = [string_repr.convert_const("foo%d" % n)
+ for n in range(len(referencetable))]
+
+ def complete_check():
+ for n, refvalue in zip(range(len(referencetable)), referencetable):
+ try:
+ gotvalue = rdict.ll_dict_getitem(l_dict, keytable[n])
+ except KeyError:
+ assert refvalue is None
+ else:
+ assert gotvalue == refvalue
+
+ for x in not_really_random():
+ n = int(x*100.0) # 0 <= x < 400
+ op = repr(x)[-1]
+ if op <= '2' and referencetable[n] is not None:
+ rdict.ll_dict_delitem(l_dict, keytable[n])
+ referencetable[n] = None
+ referencelength -= 1
+ elif op <= '6':
+ ll_value = string_repr.convert_const(str(values.next()))
+ rdict.ll_dict_setitem(l_dict, keytable[n], ll_value)
+ if referencetable[n] is None:
+ referencelength += 1
+ referencetable[n] = ll_value
+ else:
+ try:
+ gotvalue = rdict.ll_dict_getitem(l_dict, keytable[n])
+ except KeyError:
+ assert referencetable[n] is None
+ else:
+ assert gotvalue == referencetable[n]
+ if 1.38 <= x <= 1.39:
+ complete_check()
+ print 'current dict length:', referencelength
+ assert l_dict.num_items == referencelength
+ complete_check()
More information about the Pypy-commit
mailing list