[pypy-commit] pypy cffi-1.0: Caching of types inside the _cffi_backend
arigo
noreply at buildbot.pypy.org
Sat May 2 21:55:23 CEST 2015
Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-1.0
Changeset: r76985:d50e9027d0c7
Date: 2015-05-02 21:42 +0200
http://bitbucket.org/pypy/pypy/changeset/d50e9027d0c7/
Log: Caching of types inside the _cffi_backend
diff --git a/pypy/module/_cffi_backend/ctypefunc.py b/pypy/module/_cffi_backend/ctypefunc.py
--- a/pypy/module/_cffi_backend/ctypefunc.py
+++ b/pypy/module/_cffi_backend/ctypefunc.py
@@ -30,12 +30,13 @@
cif_descr = lltype.nullptr(CIF_DESCRIPTION)
def __init__(self, space, fargs, fresult, ellipsis):
+ assert isinstance(ellipsis, bool)
extra = self._compute_extra_text(fargs, fresult, ellipsis)
size = rffi.sizeof(rffi.VOIDP)
W_CTypePtrBase.__init__(self, space, size, extra, 2, fresult,
could_cast_anything=False)
self.fargs = fargs
- self.ellipsis = bool(ellipsis)
+ self.ellipsis = ellipsis
# fresult is stored in self.ctitem
if not ellipsis:
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
@@ -2,8 +2,8 @@
from pypy.interpreter.error import OperationError, oefmt
from pypy.interpreter.gateway import unwrap_spec
-from rpython.rlib.objectmodel import specialize
-from rpython.rlib.rarithmetic import ovfcheck
+from rpython.rlib.objectmodel import specialize, r_dict, compute_identity_hash
+from rpython.rlib.rarithmetic import ovfcheck, intmask
from rpython.rtyper.lltypesystem import lltype, rffi
from rpython.rtyper.tool import rffi_platform
@@ -20,6 +20,30 @@
# ____________________________________________________________
+class UniqueCache:
+ def __init__(self, space):
+ self.ctvoid = None # There can be only one
+ self.primitives = {} # Keys: name
+ self.pointers = {} # Keys: base_ctype
+ self.arrays = {} # Keys: (ptr_ctype, length_or_-1)
+ self.functions = r_dict(# Keys: (fargs, w_fresult, ellipsis)
+ _func_key_eq, _func_key_hash)
+
+def _func_key_eq((fargs1, w_fresult1, ellipsis1),
+ (fargs2, w_fresult2, ellipsis2)):
+ return (fargs1 == fargs2 and # list equality here
+ w_fresult1 is w_fresult2 and
+ ellipsis1 == ellipsis2)
+
+def _func_key_hash((fargs, w_fresult, ellipsis)):
+ x = compute_identity_hash(w_fresult) ^ ellipsis
+ for w_arg in fargs:
+ y = compute_identity_hash(w_arg)
+ x = intmask((1000003 * x) ^ y)
+ return x
+
+# ____________________________________________________________
+
PRIMITIVE_TYPES = {}
@@ -112,24 +136,53 @@
@unwrap_spec(name=str)
def new_primitive_type(space, name):
+ unique_cache = space.fromcache(UniqueCache)
+ try:
+ return unique_cache.primitives[name]
+ except KeyError:
+ pass
try:
ctypecls, size, align = PRIMITIVE_TYPES[name]
except KeyError:
raise OperationError(space.w_KeyError, space.wrap(name))
ctype = ctypecls(space, size, name, len(name), align)
+ unique_cache.primitives[name] = ctype
return ctype
# ____________________________________________________________
@unwrap_spec(w_ctype=ctypeobj.W_CType)
def new_pointer_type(space, w_ctype):
+ unique_cache = space.fromcache(UniqueCache)
+ try:
+ return unique_cache.pointers[w_ctype]
+ except KeyError:
+ pass
ctypepointer = ctypeptr.W_CTypePointer(space, w_ctype)
+ unique_cache.pointers[w_ctype] = ctypepointer
return ctypepointer
# ____________________________________________________________
@unwrap_spec(w_ctptr=ctypeobj.W_CType)
def new_array_type(space, w_ctptr, w_length):
+ if space.is_w(w_length, space.w_None):
+ length = -1
+ else:
+ length = space.getindex_w(w_length, space.w_OverflowError)
+ if length < 0:
+ raise OperationError(space.w_ValueError,
+ space.wrap("negative array length"))
+ return _new_array_type(space, w_ctptr, length)
+
+def _new_array_type(space, w_ctptr, length):
+ unique_cache = space.fromcache(UniqueCache)
+ unique_key = (w_ctptr, length)
+ try:
+ return unique_cache.arrays[unique_key]
+ except KeyError:
+ pass
+ #
if not isinstance(w_ctptr, ctypeptr.W_CTypePointer):
raise OperationError(space.w_TypeError,
space.wrap("first arg must be a pointer ctype"))
@@ -137,15 +190,10 @@
if ctitem.size < 0:
raise oefmt(space.w_ValueError, "array item of unknown size: '%s'",
ctitem.name)
- if space.is_w(w_length, space.w_None):
- length = -1
+ if length < 0:
arraysize = -1
extra = '[]'
else:
- length = space.getindex_w(w_length, space.w_OverflowError)
- if length < 0:
- raise OperationError(space.w_ValueError,
- space.wrap("negative array length"))
try:
arraysize = ovfcheck(length * ctitem.size)
except OverflowError:
@@ -154,6 +202,7 @@
extra = '[%d]' % length
#
ctype = ctypearray.W_CTypeArray(space, w_ctptr, length, arraysize, extra)
+ unique_cache.arrays[unique_key] = ctype
return ctype
# ____________________________________________________________
@@ -441,8 +490,10 @@
# ____________________________________________________________
def new_void_type(space):
- ctype = ctypevoid.W_CTypeVoid(space)
- return ctype
+ unique_cache = space.fromcache(UniqueCache)
+ if unique_cache.ctvoid is None:
+ unique_cache.ctvoid = ctypevoid.W_CTypeVoid(space)
+ return unique_cache.ctvoid
# ____________________________________________________________
@@ -484,7 +535,6 @@
@unwrap_spec(w_fresult=ctypeobj.W_CType, ellipsis=int)
def new_function_type(space, w_fargs, w_fresult, ellipsis=0):
- from pypy.module._cffi_backend import ctypefunc
fargs = []
for w_farg in space.fixedview(w_fargs):
if not isinstance(w_farg, ctypeobj.W_CType):
@@ -493,6 +543,17 @@
if isinstance(w_farg, ctypearray.W_CTypeArray):
w_farg = w_farg.ctptr
fargs.append(w_farg)
+ return _new_function_type(space, fargs, w_fresult, bool(ellipsis))
+
+def _new_function_type(space, fargs, w_fresult, ellipsis=False):
+ from pypy.module._cffi_backend import ctypefunc
+ #
+ unique_cache = space.fromcache(UniqueCache)
+ unique_key = (fargs, w_fresult, ellipsis)
+ try:
+ return self.functions[unique_key]
+ except KeyError:
+ pass
#
if ((w_fresult.size < 0 and
not isinstance(w_fresult, ctypevoid.W_CTypeVoid))
@@ -506,4 +567,5 @@
"invalid result type: '%s'", w_fresult.name)
#
fct = ctypefunc.W_CTypeFunc(space, fargs, w_fresult, ellipsis)
+ self.functions[unique_key] = fct
return fct
More information about the pypy-commit
mailing list