[pypy-svn] r73955 - in pypy/branch/cpython-extension/pypy: rlib rlib/test rpython/lltypesystem
arigo at codespeak.net
arigo at codespeak.net
Thu Apr 22 10:06:34 CEST 2010
Author: arigo
Date: Thu Apr 22 10:06:32 2010
New Revision: 73955
Added:
pypy/branch/cpython-extension/pypy/rlib/_rweakkeydict.py
- copied, changed from r73882, pypy/trunk/pypy/rlib/rweakrefimpl.py
pypy/branch/cpython-extension/pypy/rlib/_rweakvaldict.py
- copied, changed from r73882, pypy/trunk/pypy/rlib/rweakrefimpl.py
pypy/branch/cpython-extension/pypy/rlib/test/test_rweakkeydict.py (contents, props changed)
pypy/branch/cpython-extension/pypy/rlib/test/test_rweakvaldict.py
- copied, changed from r73882, pypy/trunk/pypy/rlib/test/test_rweakref.py
Removed:
pypy/branch/cpython-extension/pypy/rlib/rweakrefimpl.py
pypy/branch/cpython-extension/pypy/rlib/test/test_rweakref.py
Modified:
pypy/branch/cpython-extension/pypy/rlib/rweakref.py
pypy/branch/cpython-extension/pypy/rpython/lltypesystem/rdict.py
Log:
Add an RPython variant of WeakKeyDictionary. Currently limited to value
objects that don't have references to too many other objects (see
comment in rlib/_rweakkeydict.py).
Copied: pypy/branch/cpython-extension/pypy/rlib/_rweakkeydict.py (from r73882, pypy/trunk/pypy/rlib/rweakrefimpl.py)
==============================================================================
--- pypy/trunk/pypy/rlib/rweakrefimpl.py (original)
+++ pypy/branch/cpython-extension/pypy/rlib/_rweakkeydict.py Thu Apr 22 10:06:32 2010
@@ -1,44 +1,46 @@
from pypy.objspace.flow.model import Constant
-from pypy.rpython.lltypesystem import lltype, llmemory, rstr, rclass, rdict
+from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rdict
from pypy.rpython.lltypesystem.llmemory import weakref_create, weakref_deref
from pypy.rpython.lltypesystem.lloperation import llop
from pypy.rpython.rclass import getinstancerepr
from pypy.rpython.rmodel import Repr
-from pypy.rlib.rweakref import RWeakValueDictionary
+from pypy.rlib.rweakref import RWeakKeyDictionary
from pypy.rlib import jit
+from pypy.rlib.objectmodel import compute_identity_hash
+from pypy.rlib.objectmodel import we_are_translated
-class WeakValueDictRepr(Repr):
+# Warning: this implementation of RWeakKeyDictionary is not exactly
+# leaking, but can keep around some values for a long time, even after
+# the corresponding keys were freed. They will be eventually freed if
+# you continue to manipulate the dictionary. Avoid to use this if the
+# values are objects that might keep alive tons of memory.
+
+
+class WeakKeyDictRepr(Repr):
def __init__(self, rtyper):
self.rtyper = rtyper
self.lowleveltype = lltype.Ptr(WEAKDICT)
self.dict_cache = {}
def convert_const(self, weakdict):
- if not isinstance(weakdict, RWeakValueDictionary):
- raise TyperError("expected an RWeakValueDictionary: %r" % (
+ if not isinstance(weakdict, RWeakKeyDictionary):
+ raise TyperError("expected an RWeakKeyDictionary: %r" % (
weakdict,))
try:
key = Constant(weakdict)
return self.dict_cache[key]
except KeyError:
self.setup()
+ if weakdict.length() != 0:
+ raise TyperError("got a non-empty prebuilt RWeakKeyDictionary")
l_dict = ll_new_weakdict()
self.dict_cache[key] = l_dict
- bk = self.rtyper.annotator.bookkeeper
- classdef = bk.getuniqueclassdef(weakdict._valueclass)
- r_key = rstr.string_repr
- r_value = getinstancerepr(self.rtyper, classdef)
- for dictkey, dictvalue in weakdict._dict.items():
- llkey = r_key.convert_const(dictkey)
- llvalue = r_value.convert_const(dictvalue)
- if llvalue:
- llvalue = lltype.cast_pointer(rclass.OBJECTPTR, llvalue)
- ll_set_nonnull(l_dict, llkey, llvalue)
return l_dict
def rtype_method_get(self, hop):
- v_d, v_key = hop.inputargs(self, rstr.string_repr)
+ r_object = getinstancerepr(self.rtyper, None)
+ v_d, v_key = hop.inputargs(self, r_object)
hop.exception_cannot_occur()
v_result = hop.gendirectcall(ll_get, v_d, v_key)
v_result = hop.genop("cast_pointer", [v_result],
@@ -46,16 +48,19 @@
return v_result
def rtype_method_set(self, hop):
- v_d, v_key, v_value = hop.inputargs(self, rstr.string_repr,
- hop.args_r[2])
+ r_object = getinstancerepr(self.rtyper, None)
+ v_d, v_key, v_value = hop.inputargs(self, r_object, r_object)
hop.exception_cannot_occur()
if hop.args_s[2].is_constant() and hop.args_s[2].const is None:
hop.gendirectcall(ll_set_null, v_d, v_key)
else:
- v_value = hop.genop("cast_pointer", [v_value],
- resulttype=rclass.OBJECTPTR)
hop.gendirectcall(ll_set, v_d, v_key, v_value)
+ def rtype_method_length(self, hop):
+ v_d, = hop.inputargs(self)
+ hop.exception_cannot_occur()
+ return hop.gendirectcall(ll_length, v_d)
+
def specialize_make_weakdict(hop):
hop.exception_cannot_occur()
@@ -65,33 +70,47 @@
# ____________________________________________________________
+NULLVALUE = lltype.nullptr(rclass.OBJECTPTR.TO)
WEAKDICTENTRY = lltype.Struct("weakdictentry",
- ("key", lltype.Ptr(rstr.STR)),
- ("value", llmemory.WeakRefPtr))
+ ("key", llmemory.WeakRefPtr),
+ ("value", rclass.OBJECTPTR),
+ ("f_hash", lltype.Signed))
+
+def ll_debugrepr(x):
+ if x:
+ h = compute_identity_hash(x)
+ else:
+ h = 0
+ return '<%x>' % (h,)
def ll_valid(entries, i):
- return (bool(entries[i].value) and
- bool(weakref_deref(rclass.OBJECTPTR, entries[i].value)))
+ key = entries[i].key
+ if not key:
+ return False
+ elif weakref_deref(rclass.OBJECTPTR, key):
+ return True
+ else:
+ # The entry might be a dead weakref still holding a strong
+ # reference to the value; for this case, we clear the old
+ # value from the entry, if any.
+ entries[i].value = NULLVALUE
+ return False
def ll_everused(entries, i):
- return bool(entries[i].value)
-
-def ll_hash(entries, i):
- return str_fasthashfn(entries[i].key)
-str_fasthashfn = rstr.string_repr.get_ll_fasthash_function()
+ return bool(entries[i].key)
entrymeths = {
'allocate': lltype.typeMethod(rdict._ll_malloc_entries),
'delete': rdict._ll_free_entries,
'valid': ll_valid,
'everused': ll_everused,
- 'hash': ll_hash,
+ 'hash': rdict.ll_hash_from_cache,
+ 'no_direct_compare': True,
}
WEAKDICTENTRYARRAY = lltype.GcArray(WEAKDICTENTRY,
adtmeths=entrymeths,
- hints={'weakarray': 'value'})
-
-ll_strhash = rstr.LLHelpers.ll_strhash
+ hints={'weakarray': 'key'})
+# NB. the 'hints' is not used so far ^^^
@jit.dont_look_inside
def ll_new_weakdict():
@@ -103,14 +122,15 @@
@jit.dont_look_inside
def ll_get(d, llkey):
- hash = ll_strhash(llkey)
+ hash = compute_identity_hash(llkey)
i = rdict.ll_dict_lookup(d, llkey, hash)
- #llop.debug_print(lltype.Void, i, 'get')
- valueref = d.entries[i].value
- if valueref:
- return weakref_deref(rclass.OBJECTPTR, valueref)
- else:
- return lltype.nullptr(rclass.OBJECTPTR.TO)
+ #llop.debug_print(lltype.Void, i, 'get', hex(hash),
+ # ll_debugrepr(d.entries[i].key),
+ # ll_debugrepr(d.entries[i].value))
+ # NB. ll_valid() above was just called at least on entry i, so if
+ # it is an invalid entry with a dead weakref, the value was reset
+ # to NULLVALUE.
+ return d.entries[i].value
@jit.dont_look_inside
def ll_set(d, llkey, llvalue):
@@ -121,51 +141,70 @@
@jit.dont_look_inside
def ll_set_nonnull(d, llkey, llvalue):
- hash = ll_strhash(llkey)
- valueref = weakref_create(llvalue) # GC effects here, before the rest
+ hash = compute_identity_hash(llkey)
+ keyref = weakref_create(llkey) # GC effects here, before the rest
i = rdict.ll_dict_lookup(d, llkey, hash)
everused = d.entries.everused(i)
- d.entries[i].key = llkey
- d.entries[i].value = valueref
- #llop.debug_print(lltype.Void, i, 'stored')
+ d.entries[i].key = keyref
+ d.entries[i].value = llvalue
+ d.entries[i].f_hash = hash
+ #llop.debug_print(lltype.Void, i, 'stored', hex(hash),
+ # ll_debugrepr(llkey),
+ # ll_debugrepr(llvalue))
if not everused:
d.num_pristine_entries -= 1
- if d.num_pristine_entries <= len(d.entries) / 3:
+ if d.num_pristine_entries * 3 <= len(d.entries):
#llop.debug_print(lltype.Void, 'RESIZE')
ll_weakdict_resize(d)
@jit.dont_look_inside
def ll_set_null(d, llkey):
- hash = ll_strhash(llkey)
+ hash = compute_identity_hash(llkey)
i = rdict.ll_dict_lookup(d, llkey, hash)
if d.entries.everused(i):
# If the entry was ever used, clean up its key and value.
# We don't store a NULL value, but a dead weakref, because
# the entry must still be marked as everused().
- d.entries[i].value = llmemory.dead_wref
- d.entries[i].key = lltype.nullptr(rstr.STR)
+ d.entries[i].key = llmemory.dead_wref
+ d.entries[i].value = NULLVALUE
#llop.debug_print(lltype.Void, i, 'zero')
-def ll_weakdict_resize(d):
- # first set num_items to its correct, up-to-date value
+def ll_update_num_items(d):
entries = d.entries
num_items = 0
for i in range(len(entries)):
if entries.valid(i):
num_items += 1
d.num_items = num_items
+
+def ll_weakdict_resize(d):
+ # first set num_items to its correct, up-to-date value
+ ll_update_num_items(d)
rdict.ll_dict_resize(d)
-str_keyeq = lltype.staticAdtMethod(rstr.string_repr.get_ll_eq_function())
+def ll_keyeq(d, weakkey1, realkey2):
+ # only called by ll_dict_lookup() with the first arg coming from an
+ # entry.key, and the 2nd arg being the argument to ll_dict_lookup().
+ if not weakkey1:
+ assert bool(realkey2)
+ return False
+ return weakref_deref(rclass.OBJECTPTR, weakkey1) == realkey2
+
+ at jit.dont_look_inside
+def ll_length(d):
+ # xxx slow, but it's only for debugging
+ ll_update_num_items(d)
+ #llop.debug_print(lltype.Void, 'length:', d.num_items)
+ return d.num_items
dictmeths = {
'll_get': ll_get,
'll_set': ll_set,
- 'keyeq': str_keyeq,
+ 'keyeq': ll_keyeq,
'paranoia': False,
}
-WEAKDICT = lltype.GcStruct("weakdict",
+WEAKDICT = lltype.GcStruct("weakkeydict",
("num_items", lltype.Signed),
("num_pristine_entries", lltype.Signed),
("entries", lltype.Ptr(WEAKDICTENTRYARRAY)),
Copied: pypy/branch/cpython-extension/pypy/rlib/_rweakvaldict.py (from r73882, pypy/trunk/pypy/rlib/rweakrefimpl.py)
==============================================================================
--- pypy/trunk/pypy/rlib/rweakrefimpl.py (original)
+++ pypy/branch/cpython-extension/pypy/rlib/_rweakvaldict.py Thu Apr 22 10:06:32 2010
@@ -46,14 +46,13 @@
return v_result
def rtype_method_set(self, hop):
+ r_object = getinstancerepr(self.rtyper, None)
v_d, v_key, v_value = hop.inputargs(self, rstr.string_repr,
- hop.args_r[2])
+ r_object)
hop.exception_cannot_occur()
if hop.args_s[2].is_constant() and hop.args_s[2].const is None:
hop.gendirectcall(ll_set_null, v_d, v_key)
else:
- v_value = hop.genop("cast_pointer", [v_value],
- resulttype=rclass.OBJECTPTR)
hop.gendirectcall(ll_set, v_d, v_key, v_value)
@@ -70,8 +69,8 @@
("value", llmemory.WeakRefPtr))
def ll_valid(entries, i):
- return (bool(entries[i].value) and
- bool(weakref_deref(rclass.OBJECTPTR, entries[i].value)))
+ value = entries[i].value
+ return bool(value) and bool(weakref_deref(rclass.OBJECTPTR, value))
def ll_everused(entries, i):
return bool(entries[i].value)
@@ -90,6 +89,7 @@
WEAKDICTENTRYARRAY = lltype.GcArray(WEAKDICTENTRY,
adtmeths=entrymeths,
hints={'weakarray': 'value'})
+# NB. the 'hints' is not used so far ^^^
ll_strhash = rstr.LLHelpers.ll_strhash
@@ -130,7 +130,7 @@
#llop.debug_print(lltype.Void, i, 'stored')
if not everused:
d.num_pristine_entries -= 1
- if d.num_pristine_entries <= len(d.entries) / 3:
+ if d.num_pristine_entries * 3 <= len(d.entries):
#llop.debug_print(lltype.Void, 'RESIZE')
ll_weakdict_resize(d)
@@ -165,7 +165,7 @@
'paranoia': False,
}
-WEAKDICT = lltype.GcStruct("weakdict",
+WEAKDICT = lltype.GcStruct("weakvaldict",
("num_items", lltype.Signed),
("num_pristine_entries", lltype.Signed),
("entries", lltype.Ptr(WEAKDICTENTRYARRAY)),
Modified: pypy/branch/cpython-extension/pypy/rlib/rweakref.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/rlib/rweakref.py (original)
+++ pypy/branch/cpython-extension/pypy/rlib/rweakref.py Thu Apr 22 10:06:32 2010
@@ -1,6 +1,7 @@
"""
Weakref support in RPython. Supports ref() without callbacks,
-and a limited version of WeakValueDictionary. LLType only for now!
+a form of WeakKeyDictionary, and a limited version of WeakValueDictionary.
+LLType only for now!
"""
import weakref
@@ -27,6 +28,36 @@
self._dict[key] = value
+class RWeakKeyDictionary(object):
+ """A dictionary containing weak keys.
+ Keys and values must be instances.
+ Prebuilt RWeakKeyDictionaries must be empty.
+ """
+
+ def __init__(self, keyclass, valueclass):
+ self._dict = weakref.WeakKeyDictionary()
+ self._keyclass = keyclass
+ self._valueclass = valueclass
+
+ def get(self, key):
+ """Get the value associated to 'key', or None by default."""
+ assert isinstance(key, self._keyclass)
+ return self._dict.get(key, None)
+
+ def set(self, key, value):
+ """Set the key/value pair (or delete it if value is None)."""
+ assert isinstance(key, self._keyclass)
+ if value is None:
+ self._dict.pop(key, None)
+ else:
+ assert isinstance(value, self._valueclass)
+ self._dict[key] = value
+
+ def length(self):
+ """Mostly for debugging. Slow, don't use in real code."""
+ return len(self._dict)
+
+
# ____________________________________________________________
from pypy.rpython import extregistry
@@ -41,8 +72,8 @@
self.valueclassdef = valueclassdef
def rtyper_makerepr(self, rtyper):
- from pypy.rlib import rweakrefimpl
- return rweakrefimpl.WeakValueDictRepr(rtyper)
+ from pypy.rlib import _rweakvaldict
+ return _rweakvaldict.WeakValueDictRepr(rtyper)
def rtyper_makekey_ex(self, rtyper):
return self.__class__,
@@ -65,14 +96,11 @@
_about_ = RWeakValueDictionary
def compute_result_annotation(self, s_valueclass):
- assert isinstance(s_valueclass, annmodel.SomePBC)
- assert s_valueclass.is_constant()
- [desc] = s_valueclass.descriptions
- return SomeWeakValueDict(desc.getuniqueclassdef())
+ return SomeWeakValueDict(_getclassdef(s_valueclass))
def specialize_call(self, hop):
- from pypy.rlib import rweakrefimpl
- return rweakrefimpl.specialize_make_weakdict(hop)
+ from pypy.rlib import _rweakvaldict
+ return _rweakvaldict.specialize_make_weakdict(hop)
class Entry(extregistry.ExtRegistryEntry):
_type_ = RWeakValueDictionary
@@ -81,3 +109,65 @@
bk = self.bookkeeper
x = self.instance
return SomeWeakValueDict(bk.getuniqueclassdef(x._valueclass))
+
+def _getclassdef(s_instance):
+ assert isinstance(s_instance, annmodel.SomePBC)
+ assert s_instance.is_constant()
+ [desc] = s_instance.descriptions
+ return desc.getuniqueclassdef()
+
+# ____________________________________________________________
+
+class SomeWeakKeyDict(annmodel.SomeObject):
+ knowntype = RWeakKeyDictionary
+
+ def __init__(self, keyclassdef, valueclassdef):
+ self.keyclassdef = keyclassdef
+ self.valueclassdef = valueclassdef
+
+ def rtyper_makerepr(self, rtyper):
+ from pypy.rlib import _rweakkeydict
+ return _rweakkeydict.WeakKeyDictRepr(rtyper)
+
+ def rtyper_makekey_ex(self, rtyper):
+ return self.__class__,
+
+ def method_get(self, s_key):
+ assert isinstance(s_key, annmodel.SomeInstance)
+ assert s_key.classdef.issubclass(self.keyclassdef)
+ return annmodel.SomeInstance(self.valueclassdef, can_be_None=True)
+
+ def method_set(self, s_key, s_value):
+ s_oldvalue = self.method_get(s_key)
+ assert s_oldvalue.contains(s_value)
+
+ def method_length(self):
+ return annmodel.SomeInteger(nonneg=True)
+
+class __extend__(pairtype(SomeWeakKeyDict, SomeWeakKeyDict)):
+ def union((s_wkd1, s_wkd2)):
+ if s_wkd1.keyclassdef is not s_wkd2.keyclassdef:
+ return SomeObject() # not the same key class! complain...
+ if s_wkd1.valueclassdef is not s_wkd2.valueclassdef:
+ return SomeObject() # not the same value class! complain...
+ return SomeWeakKeyDict(s_wkd1.keyclassdef, s_wkd1.valueclassdef)
+
+class Entry(extregistry.ExtRegistryEntry):
+ _about_ = RWeakKeyDictionary
+
+ def compute_result_annotation(self, s_keyclass, s_valueclass):
+ return SomeWeakKeyDict(_getclassdef(s_keyclass),
+ _getclassdef(s_valueclass))
+
+ def specialize_call(self, hop):
+ from pypy.rlib import _rweakkeydict
+ return _rweakkeydict.specialize_make_weakdict(hop)
+
+class Entry(extregistry.ExtRegistryEntry):
+ _type_ = RWeakKeyDictionary
+
+ def compute_annotation(self):
+ bk = self.bookkeeper
+ x = self.instance
+ return SomeWeakKeyDict(bk.getuniqueclassdef(x._keyclass),
+ bk.getuniqueclassdef(x._valueclass))
Added: pypy/branch/cpython-extension/pypy/rlib/test/test_rweakkeydict.py
==============================================================================
--- (empty file)
+++ pypy/branch/cpython-extension/pypy/rlib/test/test_rweakkeydict.py Thu Apr 22 10:06:32 2010
@@ -0,0 +1,137 @@
+import py
+from pypy.rlib import rgc
+from pypy.rlib.rweakref import RWeakKeyDictionary
+from pypy.rpython.test.test_llinterp import interpret
+
+class KX(object):
+ pass
+
+class KY(KX):
+ pass
+
+class VX(object):
+ pass
+
+class VY(VX):
+ pass
+
+
+def make_test(loop=100, prebuilt=None):
+ def g(d):
+ assert d.get(KX()) is None
+ assert d.get(KY()) is None
+ k1 = KX(); k2 = KX(); k3 = KX()
+ v1 = VX(); v2 = VX(); v3 = VX()
+ d.set(k1, v1)
+ d.set(k2, v2)
+ d.set(k3, v3)
+ assert d.get(k1) is v1
+ assert d.get(k2) is v2
+ assert d.get(k3) is v3
+ assert d.get(KX()) is None
+ assert d.length() == 3
+ return k1, k3, v1, v2, v3 # k2 dies
+ def f():
+ d = prebuilt
+ if d is None:
+ d = RWeakKeyDictionary(KX, VX)
+ k1, k3, v1, v2, v3 = g(d)
+ rgc.collect(); rgc.collect()
+ assert d.get(k1) is v1
+ assert d.get(k3) is v3
+ assert d.get(k1) is not v2
+ assert d.get(k3) is not v2
+ assert d.length() == 2
+ d.set(k1, None)
+ assert d.get(k1) is None
+ assert d.get(k3) is v3
+ assert d.length() == 1
+ # resizing should also work
+ lots_of_keys = [KX() for i in range(loop)]
+ for k in lots_of_keys:
+ d.set(k, v1)
+ for k in lots_of_keys:
+ assert d.get(k) is v1
+ assert d.get(k1) is None
+ assert d.get(k3) is v3
+ assert d.length() == loop + 1
+ # a subclass
+ ky = KY()
+ vy = VY()
+ d.set(ky, vy)
+ assert d.get(ky) is vy
+ assert d.length() == loop + 2
+ # deleting by storing Nones
+ for k in lots_of_keys:
+ d.set(k, None)
+ for k in lots_of_keys:
+ assert d.get(k) is None
+ assert d.get(k1) is None
+ assert d.get(k3) is v3
+ assert d.get(ky) is vy
+ assert d.length() == 2
+ return f
+
+def test_RWeakKeyDictionary():
+ make_test()()
+
+def test_rpython_RWeakKeyDictionary():
+ interpret(make_test(loop=12), [])
+
+def test_rpython_prebuilt():
+ f = make_test(loop=12, prebuilt=RWeakKeyDictionary(KX, VX))
+ interpret(f, [])
+
+def test_rpython_merge_RWeakKeyDictionary():
+ empty = RWeakKeyDictionary(KX, VX)
+ def f(n):
+ k = KX()
+ v = VX()
+ if n:
+ d = empty
+ else:
+ d = RWeakKeyDictionary(KX, VX)
+ d.set(k, v)
+ return d.get(k) is v
+ assert f(0)
+ assert interpret(f, [0])
+ assert not f(1)
+ assert not interpret(f, [1])
+
+
+def test_rpython_merge_RWeakKeyDictionary2():
+ class A(object):
+ def __init__(self):
+ self.d = RWeakKeyDictionary(KX, A)
+ def f(self, key):
+ a = A()
+ self.d.set(key, a)
+ return a
+ empty = A()
+ def f(x):
+ a = A()
+ if x:
+ a = empty
+ k = KX()
+ a2 = a.f(k)
+ assert a.d.get(k) is a2
+ f(0)
+ interpret(f, [0])
+ f(1)
+ interpret(f, [1])
+
+ def g(x):
+ if x:
+ d = RWeakKeyDictionary(KX, VX)
+ else:
+ d = RWeakKeyDictionary(KY, VX)
+ d.set(KX(), VX())
+ py.test.raises(Exception, interpret, g, [1])
+
+ def g(x):
+ if x:
+ d = RWeakKeyDictionary(KX, VX)
+ else:
+ d = RWeakKeyDictionary(KX, VY)
+ d.set(KX(), VX())
+ py.test.raises(Exception, interpret, g, [1])
Copied: pypy/branch/cpython-extension/pypy/rlib/test/test_rweakvaldict.py (from r73882, pypy/trunk/pypy/rlib/test/test_rweakref.py)
==============================================================================
--- pypy/trunk/pypy/rlib/test/test_rweakref.py (original)
+++ pypy/branch/cpython-extension/pypy/rlib/test/test_rweakvaldict.py Thu Apr 22 10:06:32 2010
@@ -130,5 +130,4 @@
else:
d = RWeakValueDictionary(Y)
d.set("x", X())
- return 41
py.test.raises(Exception, interpret, g, [1])
Modified: pypy/branch/cpython-extension/pypy/rpython/lltypesystem/rdict.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/rpython/lltypesystem/rdict.py (original)
+++ pypy/branch/cpython-extension/pypy/rpython/lltypesystem/rdict.py Thu Apr 22 10:06:32 2010
@@ -508,12 +508,14 @@
def ll_dict_lookup(d, key, hash):
entries = d.entries
+ ENTRIES = lltype.typeOf(entries).TO
+ direct_compare = not hasattr(ENTRIES, 'no_direct_compare')
mask = len(entries) - 1
i = hash & mask
# do the first try before any looping
if entries.valid(i):
checkingkey = entries[i].key
- if checkingkey == key:
+ if direct_compare and checkingkey == key:
return i # found the entry
if d.keyeq is not None and entries.hash(i) == hash:
# correct hash, maybe the key is e.g. a different pointer to
@@ -548,7 +550,7 @@
return freeslot
elif entries.valid(i):
checkingkey = entries[i].key
- if checkingkey == key:
+ if direct_compare and checkingkey == key:
return i
if d.keyeq is not None and entries.hash(i) == hash:
# correct hash, maybe the key is e.g. a different pointer to
More information about the Pypy-commit
mailing list