Author: Maciej Fijalkowski <[email protected]>
Branch: non-null-app-dict
Changeset: r45130:0ead19d1d201
Date: 2011-06-26 10:26 +0200
http://bitbucket.org/pypy/pypy/changeset/0ead19d1d201/
Log: A branch to implement forcing of non-nullness on dict keys/values
diff --git a/pypy/annotation/bookkeeper.py b/pypy/annotation/bookkeeper.py
--- a/pypy/annotation/bookkeeper.py
+++ b/pypy/annotation/bookkeeper.py
@@ -299,12 +299,13 @@
listdef.generalize_range_step(flags['range_step'])
return SomeList(listdef)
- def getdictdef(self, is_r_dict=False):
+ def getdictdef(self, is_r_dict=False, force_non_null=False):
"""Get the DictDef associated with the current position."""
try:
dictdef = self.dictdefs[self.position_key]
except KeyError:
- dictdef = DictDef(self, is_r_dict=is_r_dict)
+ dictdef = DictDef(self, is_r_dict=is_r_dict,
+ force_non_null=force_non_null)
self.dictdefs[self.position_key] = dictdef
return dictdef
diff --git a/pypy/annotation/builtin.py b/pypy/annotation/builtin.py
--- a/pypy/annotation/builtin.py
+++ b/pypy/annotation/builtin.py
@@ -311,8 +311,10 @@
def robjmodel_we_are_translated():
return immutablevalue(True)
-def robjmodel_r_dict(s_eqfn, s_hashfn):
- dictdef = getbookkeeper().getdictdef(is_r_dict=True)
+def robjmodel_r_dict(s_eqfn, s_hashfn, s_force_non_null):
+ assert s_force_non_null.is_constant()
+ dictdef = getbookkeeper().getdictdef(is_r_dict=True,
+ force_non_null=s_force_non_null.const)
dictdef.dictkey.update_rdict_annotations(s_eqfn, s_hashfn)
return SomeDict(dictdef)
diff --git a/pypy/annotation/dictdef.py b/pypy/annotation/dictdef.py
--- a/pypy/annotation/dictdef.py
+++ b/pypy/annotation/dictdef.py
@@ -85,12 +85,14 @@
def __init__(self, bookkeeper, s_key = s_ImpossibleValue,
s_value = s_ImpossibleValue,
- is_r_dict = False):
+ is_r_dict = False,
+ force_non_null = False):
self.dictkey = DictKey(bookkeeper, s_key, is_r_dict)
self.dictkey.itemof[self] = True
self.dictvalue = DictValue(bookkeeper, s_value)
self.dictvalue.itemof[self] = True
self.bookkeeper = bookkeeper
+ self.force_non_null = force_non_null
def read_key(self, position_key=None):
if position_key is None:
diff --git a/pypy/rlib/objectmodel.py b/pypy/rlib/objectmodel.py
--- a/pypy/rlib/objectmodel.py
+++ b/pypy/rlib/objectmodel.py
@@ -448,10 +448,11 @@
The functions key_eq() and key_hash() are used by the key comparison
algorithm."""
- def __init__(self, key_eq, key_hash):
+ def __init__(self, key_eq, key_hash, force_non_null=False):
self._dict = {}
self.key_eq = key_eq
self.key_hash = key_hash
+ self.force_non_null = force_non_null
def __getitem__(self, key):
return self._dict[_r_dictkey(self, key)]
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
@@ -9,6 +9,7 @@
from pypy.rpython import robject
from pypy.rlib import objectmodel, jit
from pypy.rpython import rmodel
+from pypy.rpython.error import TyperError
HIGHEST_BIT = intmask(1 << (LONG_BIT - 1))
MASK = intmask(HIGHEST_BIT - 1)
@@ -42,7 +43,7 @@
class DictRepr(AbstractDictRepr):
def __init__(self, rtyper, key_repr, value_repr, dictkey, dictvalue,
- custom_eq_hash=None):
+ custom_eq_hash=None, force_non_null=False):
self.rtyper = rtyper
self.DICT = lltype.GcForwardReference()
self.lowleveltype = lltype.Ptr(self.DICT)
@@ -61,6 +62,7 @@
self.dictvalue = dictvalue
self.dict_cache = {}
self._custom_eq_hash_repr = custom_eq_hash
+ self.force_non_null = force_non_null
# setup() needs to be called to finish this initialization
def _externalvsinternal(self, rtyper, item_repr):
@@ -97,6 +99,13 @@
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,
@@ -640,12 +649,13 @@
pass
-def rtype_r_dict(hop):
+def rtype_r_dict(hop, i_force_non_null=-1):
r_dict = hop.r_result
if not r_dict.custom_eq_hash:
raise TyperError("r_dict() call does not return an r_dict instance")
- v_eqfn, v_hashfn = hop.inputargs(r_dict.r_rdict_eqfn,
- r_dict.r_rdict_hashfn)
+ v_eqfn, v_hashfn, _ = hop.inputargs(r_dict.r_rdict_eqfn,
+ r_dict.r_rdict_hashfn,
+ lltype.Void)
cDICT = hop.inputconst(lltype.Void, r_dict.DICT)
hop.exception_cannot_occur()
v_result = hop.gendirectcall(ll_newdict, cDICT)
diff --git a/pypy/rpython/ootypesystem/rdict.py
b/pypy/rpython/ootypesystem/rdict.py
--- a/pypy/rpython/ootypesystem/rdict.py
+++ b/pypy/rpython/ootypesystem/rdict.py
@@ -18,7 +18,7 @@
class DictRepr(AbstractDictRepr):
def __init__(self, rtyper, key_repr, value_repr, dictkey, dictvalue,
- custom_eq_hash=None):
+ custom_eq_hash=None, force_non_null=False):
self.rtyper = rtyper
self.custom_eq_hash = custom_eq_hash is not None
diff --git a/pypy/rpython/rdict.py b/pypy/rpython/rdict.py
--- a/pypy/rpython/rdict.py
+++ b/pypy/rpython/rdict.py
@@ -15,6 +15,7 @@
dictvalue = self.dictdef.dictvalue
s_key = dictkey .s_value
s_value = dictvalue.s_value
+ force_non_null = self.dictdef.force_non_null
if (s_key.__class__ is annmodel.SomeObject and s_key.knowntype ==
object and
s_value.__class__ is annmodel.SomeObject and s_value.knowntype ==
object):
return robject.pyobj_repr
@@ -29,7 +30,8 @@
lambda:
rtyper.getrepr(s_value),
dictkey,
dictvalue,
- custom_eq_hash)
+ custom_eq_hash,
+ force_non_null)
def rtyper_makekey(self):
self.dictdef.dictkey .dont_change_any_more = True
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
@@ -598,7 +598,6 @@
res = self.interpret(func, [])
assert res in [5263, 6352]
-
class TestLLtype(BaseTestRdict, LLRtypeMixin):
def test_dict_but_not_with_char_keys(self):
def func(i):
@@ -860,6 +859,25 @@
res = f()
assert res == 1
+ def test_nonnull_hint(self):
+ def eq(a, b):
+ return a == b
+ def rhash(a):
+ return 3
+
+ def func(i):
+ d = r_dict(eq, rhash, force_non_null=True)
+ if not i:
+ d[None] = i
+ else:
+ d[str(i)] = i
+ return "12" in d, d
+
+ llres = self.interpret(func, [12])
+ assert llres.item0 == 1
+ DICT = lltype.typeOf(llres.item1)
+ assert sorted(DICT.TO.entries.TO.OF._flds) == ['f_hash', 'key',
'value']
+
# ____________________________________________________________
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit