[pypy-commit] cffi cffi-1.0: Move the guarantee of uniqueness of types to the core _cffi_backend.c.
arigo
noreply at buildbot.pypy.org
Mon Apr 27 16:18:18 CEST 2015
Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-1.0
Changeset: r1855:04e073297436
Date: 2015-04-27 15:33 +0200
http://bitbucket.org/cffi/cffi/changeset/04e073297436/
Log: Move the guarantee of uniqueness of types to the core
_cffi_backend.c. Gets rid of USES_LOCAL which is not really
compatible with ffi.include().
diff --git a/_cffi1/ffi_obj.c b/_cffi1/ffi_obj.c
--- a/_cffi1/ffi_obj.c
+++ b/_cffi1/ffi_obj.c
@@ -400,7 +400,6 @@
}
z = new_pointer_type(ct);
- z = get_unique_type(self->types_builder, z);
if (z == NULL)
return NULL;
diff --git a/_cffi1/realize_c_type.c b/_cffi1/realize_c_type.c
--- a/_cffi1/realize_c_type.c
+++ b/_cffi1/realize_c_type.c
@@ -7,7 +7,6 @@
static PyObject *all_primitives[_CFFI__NUM_PRIM];
-static PyObject *global_types_dict;
static CTypeDescrObject *g_ct_voidp, *g_ct_chararray;
static PyObject *build_primitive_type(int num); /* forward */
@@ -16,14 +15,6 @@
(all_primitives[num] != NULL ? all_primitives[num] \
: build_primitive_type(num))
-static int _add_to_global_types_dict(PyObject *ct)
-{
- if (ct == NULL)
- return -1;
- return PyDict_SetItemString(global_types_dict,
- ((CTypeDescrObject *)ct)->ct_name, ct);
-}
-
static int init_global_types_dict(PyObject *ffi_type_dict)
{
int err;
@@ -32,29 +23,25 @@
MemoryErrors during importing an extension module are kind
of bad anyway */
- global_types_dict = PyDict_New();
- if (global_types_dict == NULL)
- return -1;
-
ct_void = get_primitive_type(_CFFI_PRIM_VOID); // 'void'
- if (_add_to_global_types_dict(ct_void) < 0)
+ if (ct_void == NULL)
return -1;
ct2 = new_pointer_type((CTypeDescrObject *)ct_void); // 'void *'
- if (_add_to_global_types_dict(ct2) < 0)
+ if (ct2 == NULL)
return -1;
g_ct_voidp = (CTypeDescrObject *)ct2;
ct_char = get_primitive_type(_CFFI_PRIM_CHAR); // 'char'
- if (_add_to_global_types_dict(ct_char) < 0)
+ if (ct_char == NULL)
return -1;
ct2 = new_pointer_type((CTypeDescrObject *)ct_char); // 'char *'
- if (_add_to_global_types_dict(ct2) < 0)
+ if (ct2 == NULL)
return -1;
ct2 = new_array_type((CTypeDescrObject *)ct2, -1); // 'char[]'
- if (_add_to_global_types_dict(ct2) < 0)
+ if (ct2 == NULL)
return -1;
g_ct_chararray = (CTypeDescrObject *)ct2;
@@ -117,66 +104,6 @@
return builder;
}
-static PyObject *get_unique_type(builder_c_t *builder, PyObject *x)
-{
- /* Replace the CTypeDescrObject 'x' with a standardized one.
- This either just returns x, or x is decrefed and a new reference
- to the standard equivalent is returned.
-
- In this function, 'x' always contains a reference that must be
- decrefed, and 'y' never does.
- */
- CTypeDescrObject *ct = (CTypeDescrObject *)x;
- if (ct == NULL)
- return NULL;
-
- /* XXX maybe change the type of ct_name to be a real 'PyObject *'? */
- PyObject *name = PyString_FromString(ct->ct_name);
- if (name == NULL)
- goto no_memory;
-
- PyObject *y = PyDict_GetItem(builder->types_dict, name);
- if (y != NULL) {
- /* Already found the same ct_name in the dict. Return the old one. */
- Py_INCREF(y);
- Py_DECREF(x);
- x = y;
- goto done;
- }
-
- if (!(ct->ct_flags & CT_USES_LOCAL)) {
- /* The type is not "local", i.e. does not make use of any struct,
- union or enum. This means it should be shared across independent
- ffi instances. Look it up and possibly add it to the global
- types dict.
- */
- y = PyDict_GetItem(global_types_dict, name);
- if (y != NULL) {
- Py_INCREF(y);
- Py_DECREF(x);
- x = y;
- }
- else {
- /* Not found in the global dictionary. Put it there. */
- if (PyDict_SetItem(global_types_dict, name, x) < 0)
- goto no_memory;
- }
- }
-
- /* Set x in the local dict. */
- if (PyDict_SetItem(builder->types_dict, name, x) < 0)
- goto no_memory;
-
- done:
- Py_DECREF(name);
- return x;
-
- no_memory:
- Py_XDECREF(name);
- Py_DECREF(x);
- return NULL;
-}
-
static PyObject *build_primitive_type(int num)
{
/* XXX too many translations between here and new_primitive_type() */
@@ -365,7 +292,6 @@
return NULL;
if (CTypeDescr_Check(y)) {
x = new_pointer_type((CTypeDescrObject *)y);
- x = get_unique_type(builder, x);
}
else {
assert(PyTuple_Check(y)); /* from _CFFI_OP_FUNCTION */
@@ -383,12 +309,10 @@
if (y == NULL)
return NULL;
z = new_pointer_type((CTypeDescrObject *)y);
- z = get_unique_type(builder, z);
Py_DECREF(y);
if (z == NULL)
return NULL;
x = new_array_type((CTypeDescrObject *)z, length);
- x = get_unique_type(builder, x);
Py_DECREF(z);
break;
@@ -573,7 +497,6 @@
z = new_function_type(fargs, (CTypeDescrObject *)y, ellipsis,
FFI_DEFAULT_ABI);
- z = get_unique_type(builder, z);
Py_DECREF(fargs);
Py_DECREF(y);
if (z == NULL)
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -132,7 +132,6 @@
#define CT_WITH_VAR_ARRAY 1048576
#define CT_IS_UNSIZED_CHAR_A 2097152
#define CT_LAZY_FIELD_LIST 4194304
-#define CT_USES_LOCAL 8388608
#define CT_PRIMITIVE_ANY (CT_PRIMITIVE_SIGNED | \
CT_PRIMITIVE_UNSIGNED | \
CT_PRIMITIVE_CHAR | \
@@ -3381,6 +3380,57 @@
/************************************************************/
+static PyObject *unique_cache;
+
+static PyObject *get_unique_type(CTypeDescrObject *x,
+ const void *unique_key[], long keylength)
+{
+ /* Replace the CTypeDescrObject 'x' with a standardized one.
+ This either just returns x, or x is decrefed and a new reference
+ to the already-existing equivalent is returned.
+
+ In this function, 'x' always contains a reference that must be
+ either decrefed or returned.
+
+ Keys:
+ void ["void"]
+ primitive [&static_struct]
+ pointer [ctype]
+ array [ctype, length]
+ funcptr [ctresult, ellipsis+abi, num_args, ctargs...]
+ */
+ long i;
+ PyObject *key, *y;
+ const void **pkey;
+ int err;
+
+ key = PyString_FromStringAndSize(NULL, keylength * sizeof(void *));
+ if (key == NULL)
+ goto error;
+
+ pkey = (const void **)PyString_AS_STRING(key);
+ for (i = 0; i < keylength; i++)
+ pkey[i] = unique_key[i];
+
+ y = PyDict_GetItem(unique_cache, key);
+ if (y != NULL) {
+ Py_DECREF(key);
+ Py_INCREF(y);
+ Py_DECREF(x);
+ return y;
+ }
+ err = PyDict_SetItem(unique_cache, key, (PyObject *)x);
+ Py_DECREF(key);
+ if (err < 0)
+ goto error;
+
+ return (PyObject *)x;
+
+ error:
+ Py_DECREF(x);
+ return NULL;
+}
+
static PyObject *new_primitive_type(const char *name)
{
#define ENUM_PRIMITIVE_TYPES \
@@ -3461,6 +3511,7 @@
{ NULL }
};
const struct descr_s *ptypes;
+ const void *unique_key[1];
int name_size;
ffi_type *ffitype;
@@ -3526,7 +3577,8 @@
td->ct_flags |= CT_PRIMITIVE_FITS_LONG;
}
td->ct_name_position = strlen(td->ct_name);
- return (PyObject *)td;
+ unique_key[0] = ptypes;
+ return get_unique_type(td, unique_key, 1);
bad_ffi_type:
PyErr_Format(PyExc_NotImplementedError,
@@ -3548,6 +3600,7 @@
{
CTypeDescrObject *td;
const char *extra;
+ const void *unique_key[1];
if (ctitem->ct_flags & CT_ARRAY)
extra = "(*)"; /* obscure case: see test_array_add */
@@ -3559,7 +3612,7 @@
td->ct_size = sizeof(void *);
td->ct_length = -1;
- td->ct_flags = CT_POINTER | (ctitem->ct_flags & CT_USES_LOCAL);
+ td->ct_flags = CT_POINTER;
if (ctitem->ct_flags & (CT_STRUCT|CT_UNION))
td->ct_flags |= CT_IS_PTR_TO_OWNED;
if (ctitem->ct_flags & CT_VOID)
@@ -3568,7 +3621,8 @@
((ctitem->ct_flags & CT_PRIMITIVE_CHAR) &&
ctitem->ct_size == sizeof(char)))
td->ct_flags |= CT_CAST_ANYTHING; /* 'void *' or 'char *' only */
- return (PyObject *)td;
+ unique_key[0] = ctitem;
+ return get_unique_type(td, unique_key, 1);
}
static PyObject *b_new_pointer_type(PyObject *self, PyObject *args)
@@ -3611,6 +3665,7 @@
char extra_text[32];
Py_ssize_t arraysize;
int flags = CT_ARRAY;
+ const void *unique_key[2];
if (!(ctptr->ct_flags & CT_POINTER)) {
PyErr_SetString(PyExc_TypeError, "first arg must be a pointer ctype");
@@ -3648,13 +3703,16 @@
td->ct_stuff = (PyObject *)ctptr;
td->ct_size = arraysize;
td->ct_length = length;
- td->ct_flags = flags | (ctptr->ct_flags & CT_USES_LOCAL);
- return (PyObject *)td;
+ td->ct_flags = flags;
+ unique_key[0] = ctptr;
+ unique_key[1] = (void *)length;
+ return get_unique_type(td, unique_key, 2);
}
static PyObject *new_void_type(void)
{
int name_size = strlen("void") + 1;
+ const void *unique_key[1];
CTypeDescrObject *td = ctypedescr_new(name_size);
if (td == NULL)
return NULL;
@@ -3663,7 +3721,8 @@
td->ct_size = -1;
td->ct_flags = CT_VOID | CT_IS_OPAQUE;
td->ct_name_position = strlen("void");
- return (PyObject *)td;
+ unique_key[0] = "void";
+ return get_unique_type(td, unique_key, 1);
}
static PyObject *b_new_void_type(PyObject *self, PyObject *args)
@@ -3680,7 +3739,7 @@
td->ct_size = -1;
td->ct_length = -1;
- td->ct_flags = flag | CT_IS_OPAQUE | CT_USES_LOCAL;
+ td->ct_flags = flag | CT_IS_OPAQUE;
td->ct_extra = NULL;
memcpy(td->ct_name, name, namelen + 1);
td->ct_name_position = namelen;
@@ -4406,8 +4465,6 @@
int ellipsis)
{
CTypeDescrObject *fct;
- Py_ssize_t i, nargs;
- int all_flags;
fb->nb_bytes = 0;
fb->bufferp = NULL;
@@ -4429,16 +4486,9 @@
goto error;
assert(fb->bufferp == fct->ct_name + fb->nb_bytes);
- all_flags = fresult->ct_flags;
- nargs = PyTuple_GET_SIZE(fargs);
- for (i = 0; i < nargs; i++) {
- CTypeDescrObject *farg = (CTypeDescrObject *)PyTuple_GET_ITEM(fargs, i);
- all_flags |= farg->ct_flags;
- }
-
fct->ct_extra = NULL;
fct->ct_size = sizeof(void(*)(void));
- fct->ct_flags = CT_FUNCTIONPTR | (all_flags & CT_USES_LOCAL);
+ fct->ct_flags = CT_FUNCTIONPTR;
return fct;
error:
@@ -4496,6 +4546,7 @@
CTypeDescrObject *fct;
struct funcbuilder_s funcbuilder;
Py_ssize_t i;
+ const void **unique_key;
if ((fresult->ct_size < 0 && !(fresult->ct_flags & CT_VOID)) ||
(fresult->ct_flags & CT_ARRAY)) {
@@ -4551,7 +4602,15 @@
Py_INCREF(o);
PyTuple_SET_ITEM(fct->ct_stuff, 2 + i, o);
}
- return (PyObject *)fct;
+
+ /* [ctresult, ellipsis+abi, num_args, ctargs...] */
+ unique_key = alloca((3 + funcbuilder.nargs) * sizeof(void *));
+ unique_key[0] = fresult;
+ unique_key[1] = (const void *)(Py_ssize_t)((fabi << 1) | !!ellipsis);
+ unique_key[2] = (const void *)(Py_ssize_t)(funcbuilder.nargs);
+ for (i=0; i<funcbuilder.nargs; i++)
+ unique_key[3 + i] = PyTuple_GET_ITEM(fct->ct_stuff, 2 + i);
+ return get_unique_type(fct, unique_key, 3 + funcbuilder.nargs);
error:
Py_DECREF(fct);
@@ -4890,7 +4949,7 @@
td->ct_size = basetd->ct_size;
td->ct_length = basetd->ct_length; /* alignment */
td->ct_extra = basetd->ct_extra; /* ffi type */
- td->ct_flags = basetd->ct_flags | CT_IS_ENUM | CT_USES_LOCAL;
+ td->ct_flags = basetd->ct_flags | CT_IS_ENUM;
td->ct_name_position = name_size - 1;
return (PyObject *)td;
@@ -5914,6 +5973,11 @@
if (m == NULL)
INITERROR;
+
+ unique_cache = PyDict_New();
+ if (unique_cache == NULL)
+ INITERROR;
+
if (PyType_Ready(&dl_type) < 0)
INITERROR;
if (PyType_Ready(&CTypeDescr_Type) < 0)
More information about the pypy-commit
mailing list