Author: Armin Rigo <[email protected]>
Branch: rpython-hash
Changeset: r89815:1efada6f7e36
Date: 2017-01-28 09:19 +0100
http://bitbucket.org/pypy/pypy/changeset/1efada6f7e36/
Log: Rehash cffi's prebuilt function types after translation.
diff --git a/pypy/module/_cffi_backend/newtype.py
b/pypy/module/_cffi_backend/newtype.py
--- a/pypy/module/_cffi_backend/newtype.py
+++ b/pypy/module/_cffi_backend/newtype.py
@@ -31,6 +31,26 @@
self.ctchara = None # Cache for the 'char[]' type
self.primitives = {} # Cache for {name: primitive_type}
self.functions = [] # see _new_function_type()
+ self.functions_packed = None # only across translation
+
+ def _cleanup_(self):
+ import gc
+ assert self.functions_packed is None
+ # Note: a full PyPy translation may still have
+ # 'self.functions == []' at this point, possibly depending
+ # on details. Code tested directly in test_ffi_obj
+ gc.collect()
+ funcs = []
+ for weakdict in self.functions:
+ funcs += weakdict._dict.values()
+ del self.functions[:]
+ self.functions_packed = funcs if len(funcs) > 0 else None
+
+ def unpack_functions(self):
+ for fct in self.functions_packed:
+ _record_function_type(self, fct)
+ self.functions_packed = None
+
def _clean_cache(space):
"NOT_RPYTHON"
@@ -623,7 +643,7 @@
for w_arg in fargs:
y = compute_identity_hash(w_arg)
x = intmask((1000003 * x) ^ y)
- x ^= (ellipsis - abi)
+ x ^= ellipsis + 2 * abi
if unique_cache.for_testing: # constant-folded to False in translation;
x &= 3 # but for test, keep only 2 bits of hash
return x
@@ -647,6 +667,8 @@
# one such dict, but in case of hash collision, there might be
# more.
unique_cache = space.fromcache(UniqueCache)
+ if unique_cache.functions_packed is not None:
+ unique_cache.unpack_functions()
func_hash = _func_key_hash(unique_cache, fargs, fresult, ellipsis, abi)
for weakdict in unique_cache.functions:
ctype = weakdict.get(func_hash)
@@ -675,13 +697,18 @@
#
fct = ctypefunc.W_CTypeFunc(space, fargs, fresult, ellipsis, abi)
unique_cache = space.fromcache(UniqueCache)
- func_hash = _func_key_hash(unique_cache, fargs, fresult, ellipsis, abi)
+ _record_function_type(unique_cache, fct)
+ return fct
+
+def _record_function_type(unique_cache, fct):
+ from pypy.module._cffi_backend import ctypefunc
+ #
+ func_hash = _func_key_hash(unique_cache, fct.fargs, fct.ctitem,
+ fct.ellipsis, fct.abi)
for weakdict in unique_cache.functions:
if weakdict.get(func_hash) is None:
- weakdict.set(func_hash, fct)
break
else:
weakdict = rweakref.RWeakValueDictionary(int, ctypefunc.W_CTypeFunc)
unique_cache.functions.append(weakdict)
- weakdict.set(func_hash, fct)
- return fct
+ weakdict.set(func_hash, fct)
diff --git a/pypy/module/_cffi_backend/test/test_ffi_obj.py
b/pypy/module/_cffi_backend/test/test_ffi_obj.py
--- a/pypy/module/_cffi_backend/test/test_ffi_obj.py
+++ b/pypy/module/_cffi_backend/test/test_ffi_obj.py
@@ -1,5 +1,23 @@
+from pypy.module._cffi_backend import newtype
from pypy.module._cffi_backend.newtype import _clean_cache
+
+class TestFFIObj:
+ spaceconfig = dict(usemodules=('_cffi_backend', 'array'))
+
+ def teardown_method(self, meth):
+ _clean_cache(self.space)
+
+ def test_new_function_type_during_translation(self):
+ space = self.space
+ BInt = newtype.new_primitive_type(space, "int")
+ BFunc = newtype.new_function_type(space, space.wrap([BInt]), BInt)
+ assert BFunc is
newtype.new_function_type(space,space.wrap([BInt]),BInt)
+ unique_cache = space.fromcache(newtype.UniqueCache)
+ unique_cache._cleanup_()
+ assert BFunc is
newtype.new_function_type(space,space.wrap([BInt]),BInt)
+
+
class AppTestFFIObj:
spaceconfig = dict(usemodules=('_cffi_backend', 'array'))
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit