Unverified Commit a87f498d authored by Eddie Elizondo's avatar Eddie Elizondo Committed by GitHub

Expand LIMITED_API support (GH-3311)

* Add more limited api support
* Fix Fused Functions
* Fixed profile
* Use PyModule_GetDict
* Simplify __Pyx_Globals
* Address issues in CommonStructures
* ifdef guard CyFunction and FusedFunction
parent 1431cc4e
......@@ -1078,14 +1078,14 @@ class GlobalState(object):
'h_code',
'filename_table',
'utility_code_proto_before_types',
'module_state',
'module_state_clear',
'module_state_traverse',
'module_state_defines',
'numeric_typedefs', # Let these detailed individual parts stay!,
'complex_type_declarations', # as the proper solution is to make a full DAG...
'type_declarations', # More coarse-grained blocks would simply hide
'utility_code_proto', # the ugliness, not fix it
'module_state',
'module_state_clear',
'module_state_traverse',
'module_state_defines',
'module_declarations',
'typeinfo',
'before_global_var',
......
......@@ -1203,6 +1203,18 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
module_state_traverse.putln(
"Py_VISIT(traverse_module_state->%s);" %
entry.type.typeptr_cname)
if entry.type.typeobj_cname is not None:
module_state.putln("PyObject *%s;" % entry.type.typeobj_cname)
module_state_defines.putln("#define %s %s->%s" % (
entry.type.typeobj_cname,
Naming.modulestateglobal_cname,
entry.type.typeobj_cname))
module_state_clear.putln(
"Py_CLEAR(clear_module_state->%s);" % (
entry.type.typeobj_cname))
module_state_traverse.putln(
"Py_VISIT(traverse_module_state->%s);" % (
entry.type.typeobj_cname))
code.putln("#endif")
def generate_cvariable_declarations(self, env, code, definition):
......@@ -1365,12 +1377,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
freecount_name = scope.mangle_internal(Naming.freecount_name)
decls = code.globalstate['decls']
if cinit_func_entry is None:
decls.putln("#if !CYTHON_COMPILING_IN_LIMITED_API")
decls.putln("static PyObject *%s(PyTypeObject *t, PyObject *a, PyObject *k); /*proto*/" %
slot_func)
if cinit_func_entry is None:
decls.putln("#endif")
code.putln("")
if freelist_size:
code.putln("static %s[%d];" % (
......@@ -1378,8 +1386,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
freelist_size))
code.putln("static int %s = 0;" % freecount_name)
code.putln("")
if cinit_func_entry is None:
code.putln("#if !CYTHON_COMPILING_IN_LIMITED_API")
code.putln(
"static PyObject *%s(PyTypeObject *t, %sPyObject *a, %sPyObject *k) {" % (
slot_func, unused_marker, unused_marker))
......@@ -1390,10 +1396,16 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
if need_self_cast:
code.putln("%s;" % scope.parent_type.declaration_code("p"))
if base_type:
code.putln("#if CYTHON_COMPILING_IN_LIMITED_API")
code.putln("newfunc new_func = (newfunc)PyType_GetSlot(%s, Py_tp_new);" %
base_type.typeptr_cname)
code.putln("PyObject *o = new_func(t, a, k);")
code.putln("#else")
tp_new = TypeSlots.get_base_slot_function(scope, tp_slot)
if tp_new is None:
tp_new = "%s->tp_new" % base_type.typeptr_cname
code.putln("PyObject *o = %s(t, a, k);" % tp_new)
code.putln("#endif")
else:
code.putln("PyObject *o;")
code.putln("#if CYTHON_COMPILING_IN_LIMITED_API")
......@@ -1425,10 +1437,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("} else {")
code.putln("o = (PyObject *) PyBaseObject_Type.tp_new(t, %s, 0);" % Naming.empty_tuple)
code.putln("}")
code.putln("#endif")
code.putln("if (unlikely(!o)) return 0;")
if freelist_size and not base_type:
code.putln('}')
if not base_type:
code.putln("#endif")
if need_self_cast:
code.putln("p = %s;" % type.cast_code("o"))
#if need_self_cast:
......@@ -1488,8 +1501,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("return NULL;")
code.putln(
"}")
if cinit_func_entry is None:
code.putln("#endif")
def generate_dealloc_function(self, scope, code):
tp_slot = TypeSlots.ConstructorSlot("tp_dealloc", '__dealloc__')
......@@ -2234,8 +2245,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
for slot in TypeSlots.slot_table:
if slot.slot_name == "tp_flags":
continue
if slot.slot_name == "tp_new" and scope.lookup_here("__cinit__") is None:
continue
if slot.slot_name == "tp_dealloc" and scope.lookup_here("__dealloc__") is None:
continue
if slot.slot_name == "tp_getattro":
......@@ -2452,26 +2461,18 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln('int %s;' % Naming.lineno_cname)
code.putln('int %s;' % Naming.clineno_cname)
code.putln('const char *%s;' % Naming.filename_cname)
code.putln('#ifdef __Pyx_CyFunction_USED')
code.putln('PyObject *%s;' % Naming.cyfunction_type_cname)
code.putln('#endif')
code.putln('#ifdef __Pyx_FusedFunction_USED')
code.putln('PyObject *%s;' % Naming.fusedfunction_type_cname)
code.putln('#endif')
def generate_module_state_end(self, env, modules, globalstate):
module_state = globalstate['module_state']
module_state_defines = globalstate['module_state_defines']
module_state_clear = globalstate['module_state_clear']
module_state_traverse = globalstate['module_state_traverse']
for module in modules:
definition = module is env
for entry in env.c_class_entries:
if definition or entry.defined_in_pxd:
module_state.putln("PyObject *%s;" % entry.type.typeobj_cname)
module_state_defines.putln("#define %s %s->%s" % (
entry.type.typeobj_cname,
Naming.modulestateglobal_cname,
entry.type.typeobj_cname))
module_state_clear.putln("Py_CLEAR(clear_module_state->%s);" %
entry.type.typeobj_cname)
module_state_traverse.putln(
"Py_VISIT(traverse_module_state->%s);" %
entry.type.typeobj_cname)
module_state.putln('} %s;' % Naming.modulestate_cname)
module_state.putln('')
module_state.putln('#ifdef __cplusplus')
......@@ -2542,6 +2543,18 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
Naming.filename_cname,
Naming.modulestateglobal_cname,
Naming.filename_cname))
code.putln('#ifdef __Pyx_CyFunction_USED')
code.putln('#define %s %s->%s' % (
Naming.cyfunction_type_cname,
Naming.modulestateglobal_cname,
Naming.cyfunction_type_cname))
code.putln('#endif')
code.putln('#ifdef __Pyx_FusedFunction_USED')
code.putln('#define %s %s->%s' %
(Naming.fusedfunction_type_cname,
Naming.modulestateglobal_cname,
Naming.fusedfunction_type_cname))
code.putln('#endif')
def generate_module_state_clear(self, env, code):
code.putln("#if CYTHON_COMPILING_IN_LIMITED_API")
......@@ -2560,6 +2573,14 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
Naming.empty_bytes)
code.putln('Py_CLEAR(clear_module_state->%s);' %
Naming.empty_unicode)
code.putln('#ifdef __Pyx_CyFunction_USED')
code.putln('Py_CLEAR(clear_module_state->%s);' %
Naming.cyfunction_type_cname)
code.putln('#endif')
code.putln('#ifdef __Pyx_FusedFunction_USED')
code.putln('Py_CLEAR(clear_module_state->%s);' %
Naming.fusedfunction_type_cname)
code.putln('#endif')
def generate_module_state_traverse(self, env, code):
code.putln("#if CYTHON_COMPILING_IN_LIMITED_API")
......@@ -2578,6 +2599,14 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
Naming.empty_bytes)
code.putln('Py_VISIT(traverse_module_state->%s);' %
Naming.empty_unicode)
code.putln('#ifdef __Pyx_CyFunction_USED')
code.putln('Py_VISIT(traverse_module_state->%s);' %
Naming.cyfunction_type_cname)
code.putln('#endif')
code.putln('#ifdef __Pyx_FusedFunction_USED')
code.putln('Py_VISIT(traverse_module_state->%s);' %
Naming.fusedfunction_type_cname)
code.putln('#endif')
def generate_module_init_func(self, imported_modules, env, code):
subfunction = self.mod_init_subfunction(self.scope, code)
......@@ -3371,7 +3400,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
if type.vtabptr_cname:
code.globalstate.use_utility_code(
UtilityCode.load_cached('GetVTable', 'ImportExport.c'))
code.putln("%s = (struct %s*)__Pyx_GetVtable(%s->tp_dict); %s" % (
code.putln("%s = (struct %s*)__Pyx_GetVtable(%s); %s" % (
type.vtabptr_cname,
type.vtabstruct_cname,
type.typeptr_cname,
......
......@@ -134,6 +134,8 @@ tp_dict_version_temp = pyrex_prefix + "tp_dict_version"
obj_dict_version_temp = pyrex_prefix + "obj_dict_version"
type_dict_guard_temp = pyrex_prefix + "type_dict_guard"
cython_runtime_cname = pyrex_prefix + "cython_runtime"
cyfunction_type_cname = pyrex_prefix + "CyFunctionType"
fusedfunction_type_cname = pyrex_prefix + "FusedFunctionType"
global_code_object_cache_find = pyrex_prefix + 'find_code_object'
global_code_object_cache_insert = pyrex_prefix + 'insert_code_object'
......
......@@ -5078,11 +5078,29 @@ class CClassDefNode(ClassDefNode):
return
if entry.visibility != 'extern':
code.putln("#if CYTHON_COMPILING_IN_LIMITED_API")
code.putln(
"%s = PyType_FromSpec(&%s_spec); %s" % (
typeobj_cname,
typeobj_cname,
code.error_goto_if_null(typeobj_cname, entry.pos)))
tuple_temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True)
base_type = scope.parent_type.base_type
if base_type:
code.putln(
"%s = PyTuple_Pack(1, (PyObject *)%s); %s" % (
tuple_temp,
base_type.typeptr_cname,
code.error_goto_if_null(tuple_temp, entry.pos)))
code.put_gotref(tuple_temp)
code.putln(
"%s = PyType_FromSpecWithBases(&%s_spec, %s); %s" % (
typeobj_cname,
typeobj_cname,
tuple_temp,
code.error_goto_if_null(typeobj_cname, entry.pos)))
code.put_xdecref_clear(tuple_temp, type=py_object_type)
code.funcstate.release_temp(tuple_temp)
else:
code.putln(
"%s = PyType_FromSpec(&%s_spec); %s" % (
typeobj_cname,
typeobj_cname,
code.error_goto_if_null(typeobj_cname, entry.pos)))
code.putln("#else")
for slot in TypeSlots.slot_table:
slot.generate_dynamic_init_code(scope, code)
......@@ -5227,7 +5245,11 @@ class CClassDefNode(ClassDefNode):
# Generate code to initialise the typeptr of an extension
# type defined in this module to point to its type object.
if type.typeobj_cname:
code.putln("#if !CYTHON_COMPILING_IN_LIMITED_API")
code.putln("#if CYTHON_COMPILING_IN_LIMITED_API")
code.putln(
"%s = (PyTypeObject *)%s;" % (
type.typeptr_cname, type.typeobj_cname))
code.putln("#else")
code.putln(
"%s = &%s;" % (
type.typeptr_cname, type.typeobj_cname))
......
......@@ -20,47 +20,15 @@ static PyObject* __Pyx_Globals(void); /*proto*/
// access requires a rewrite as a dedicated class.
static PyObject* __Pyx_Globals(void) {
Py_ssize_t i;
PyObject *names;
PyObject *globals = $moddict_cname;
Py_INCREF(globals);
names = PyObject_Dir($module_cname);
if (!names)
goto bad;
for (i = PyList_GET_SIZE(names)-1; i >= 0; i--) {
#if CYTHON_COMPILING_IN_PYPY
PyObject* name = PySequence_ITEM(names, i);
if (!name)
goto bad;
PyObject *globals;
#if CYTHON_COMPILING_IN_LIMITED_API
globals = PyModule_GetDict($module_cname);
if (unlikely(!globals)) return NULL;
#else
PyObject* name = PyList_GET_ITEM(names, i);
#endif
if (!PyDict_Contains(globals, name)) {
PyObject* value = __Pyx_GetAttr($module_cname, name);
if (!value) {
#if CYTHON_COMPILING_IN_PYPY
Py_DECREF(name);
#endif
goto bad;
}
if (PyDict_SetItem(globals, name, value) < 0) {
#if CYTHON_COMPILING_IN_PYPY
Py_DECREF(name);
#endif
Py_DECREF(value);
goto bad;
}
}
#if CYTHON_COMPILING_IN_PYPY
Py_DECREF(name);
globals = $moddict_cname;
#endif
}
Py_DECREF(names);
Py_INCREF(globals);
return globals;
bad:
Py_XDECREF(names);
Py_XDECREF(globals);
return NULL;
}
//////////////////// PyExecGlobals.proto ////////////////////
......
/////////////// FetchCommonType.proto ///////////////
static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type);
#if CYTHON_COMPILING_IN_LIMITED_API
static PyObject* __Pyx_FetchCommonTypeFromSpec(PyType_Spec *spec, PyObject *bases);
#endif
/////////////// FetchCommonType ///////////////
static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type) {
PyObject* fake_module;
PyTypeObject* cached_type = NULL;
static PyObject *__Pyx_FetchSharedCythonABIModule(void) {
PyObject *abi_module = PyImport_AddModule((char*) "_cython_" CYTHON_ABI);
if (!abi_module) return NULL;
Py_INCREF(abi_module);
return abi_module;
}
fake_module = PyImport_AddModule((char*) "_cython_" CYTHON_ABI);
if (!fake_module) return NULL;
Py_INCREF(fake_module);
static int __Pyx_VerifyCachedType(PyObject *cached_type,
const char *name,
Py_ssize_t basicsize,
Py_ssize_t expected_basicsize) {
if (!PyType_Check(cached_type)) {
PyErr_Format(PyExc_TypeError,
"Shared Cython type %.200s is not a type object", name);
return -1;
}
if (basicsize != expected_basicsize) {
PyErr_Format(PyExc_TypeError,
"Shared Cython type %.200s has the wrong size, try recompiling",
name);
return -1;
}
return 0;
}
static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type) {
PyObject* abi_module;
PyTypeObject *cached_type = NULL;
cached_type = (PyTypeObject*) PyObject_GetAttrString(fake_module, type->tp_name);
abi_module = __Pyx_FetchSharedCythonABIModule();
if (!abi_module) return NULL;
cached_type = (PyTypeObject*) PyObject_GetAttrString(abi_module, type->tp_name);
if (cached_type) {
if (!PyType_Check((PyObject*)cached_type)) {
PyErr_Format(PyExc_TypeError,
"Shared Cython type %.200s is not a type object",
type->tp_name);
if (__Pyx_VerifyCachedType(
(PyObject *)cached_type,
type->tp_name,
cached_type->tp_basicsize,
type->tp_basicsize) < 0) {
goto bad;
}
if (cached_type->tp_basicsize != type->tp_basicsize) {
PyErr_Format(PyExc_TypeError,
"Shared Cython type %.200s has the wrong size, try recompiling",
type->tp_name);
goto done;
}
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) goto bad;
PyErr_Clear();
if (PyType_Ready(type) < 0) goto bad;
if (PyObject_SetAttrString(abi_module, type->tp_name, (PyObject *)type) < 0)
goto bad;
Py_INCREF(type);
cached_type = type;
done:
Py_DECREF(abi_module);
// NOTE: always returns owned reference, or NULL on error
return cached_type;
bad:
Py_XDECREF(cached_type);
cached_type = NULL;
goto done;
}
#if CYTHON_COMPILING_IN_LIMITED_API
static PyObject *__Pyx_FetchCommonTypeFromSpec(PyType_Spec *spec, PyObject *bases) {
PyObject *abi_module, *py_basicsize, *type, *cached_type = NULL;
Py_ssize_t basicsize;
abi_module = __Pyx_FetchSharedCythonABIModule();
if (!abi_module) return NULL;
cached_type = PyObject_GetAttrString(abi_module, spec->name);
if (cached_type) {
py_basicsize = PyObject_GetAttrString(cached_type, "__basicsize__");
if (!py_basicsize) goto bad;
basicsize = PyLong_AsSsize_t(py_basicsize);
Py_DECREF(py_basicsize);
py_basicsize = 0;
if (basicsize == (Py_ssize_t)-1 && PyErr_Occurred()) goto bad;
if (__Pyx_VerifyCachedType(
cached_type,
spec->name,
basicsize,
spec->basicsize) < 0) {
goto bad;
}
} else {
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) goto bad;
PyErr_Clear();
if (PyType_Ready(type) < 0) goto bad;
if (PyObject_SetAttrString(fake_module, type->tp_name, (PyObject*) type) < 0)
goto bad;
Py_INCREF(type);
cached_type = type;
goto done;
}
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) goto bad;
PyErr_Clear();
type = PyType_FromSpecWithBases(spec, bases);
if (unlikely(!type)) goto bad;
if (PyObject_SetAttrString(abi_module, spec->name, type) < 0) goto bad;
cached_type = type;
done:
Py_DECREF(fake_module);
Py_DECREF(abi_module);
// NOTE: always returns owned reference, or NULL on error
return cached_type;
......@@ -46,6 +111,7 @@ bad:
cached_type = NULL;
goto done;
}
#endif
/////////////// FetchCommonPointer.proto ///////////////
......@@ -56,27 +122,27 @@ static void* __Pyx_FetchCommonPointer(void* pointer, const char* name);
static void* __Pyx_FetchCommonPointer(void* pointer, const char* name) {
PyObject* fake_module = NULL;
PyObject* abi_module = NULL;
PyObject* capsule = NULL;
void* value = NULL;
fake_module = PyImport_AddModule((char*) "_cython_" CYTHON_ABI);
if (!fake_module) return NULL;
Py_INCREF(fake_module);
abi_module = PyImport_AddModule((char*) "_cython_" CYTHON_ABI);
if (!abi_module) return NULL;
Py_INCREF(abi_module);
capsule = PyObject_GetAttrString(fake_module, name);
capsule = PyObject_GetAttrString(abi_module, name);
if (!capsule) {
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) goto bad;
PyErr_Clear();
capsule = PyCapsule_New(pointer, name, NULL);
if (!capsule) goto bad;
if (PyObject_SetAttrString(fake_module, name, capsule) < 0)
if (PyObject_SetAttrString(abi_module, name, capsule) < 0)
goto bad;
}
value = PyCapsule_GetPointer(capsule, name);
bad:
Py_XDECREF(capsule);
Py_DECREF(fake_module);
Py_DECREF(abi_module);
return value;
}
......@@ -48,12 +48,14 @@ typedef struct {
PyObject *func_annotations; /* function annotations dict */
} __pyx_CyFunctionObject;
#if !CYTHON_COMPILING_IN_LIMITED_API
static PyTypeObject *__pyx_CyFunctionType = 0;
#endif
#define __Pyx_CyFunction_Check(obj) (__Pyx_TypeCheck(obj, __pyx_CyFunctionType))
#define __Pyx_CyFunction_NewEx(ml, flags, qualname, closure, module, globals, code) \
__Pyx_CyFunction_New(__pyx_CyFunctionType, ml, flags, qualname, closure, module, globals, code)
__Pyx_CyFunction_New((PyTypeObject *)__pyx_CyFunctionType, ml, flags, qualname, closure, module, globals, code)
static PyObject *__Pyx_CyFunction_New(PyTypeObject *type, PyMethodDef *ml,
int flags, PyObject* qualname,
......@@ -435,6 +437,14 @@ static PyGetSetDef __pyx_CyFunction_getsets[] = {
static PyMemberDef __pyx_CyFunction_members[] = {
{(char *) "__module__", T_OBJECT, offsetof(PyCFunctionObject, m_module), PY_WRITE_RESTRICTED, 0},
#if CYTHON_COMPILING_IN_LIMITED_API
{(char *) "__dictoffset__", T_PYSSIZET, offsetof(__pyx_CyFunctionObject, func_dict), READONLY, 0},
#if PY_VERSION_HEX < 0x030500A0
{(char *) "__weaklistoffset__", T_PYSSIZET, offsetof(__pyx_CyFunctionObject, func_weakreflist), READONLY, 0},
#else
{(char *) "__weaklistoffset__", T_PYSSIZET, offsetof(PyCFunctionObject, m_weakreflist), READONLY, 0},
#endif
#endif
{0, 0, 0, 0, 0}
};
......@@ -812,6 +822,29 @@ static PyObject * __Pyx_CyFunction_Vectorcall_FASTCALL_KEYWORDS(PyObject *func,
}
#endif
#if CYTHON_COMPILING_IN_LIMITED_API
static PyType_Slot __pyx_CyFunctionType_slots[] = {
{Py_tp_dealloc, (void *)__Pyx_CyFunction_dealloc},
{Py_tp_repr, (void *)__Pyx_CyFunction_repr},
{Py_tp_call, (void *)__Pyx_CyFunction_CallAsMethod},
{Py_tp_traverse, (void *)__Pyx_CyFunction_traverse},
{Py_tp_clear, (void *)__Pyx_CyFunction_clear},
{Py_tp_methods, (void *)__pyx_CyFunction_methods},
{Py_tp_members, (void *)__pyx_CyFunction_members},
{Py_tp_getset, (void *)__pyx_CyFunction_getsets},
{Py_tp_descr_get, (void *)__Pyx_PyMethod_New},
{0, 0},
};
static PyType_Spec __pyx_CyFunctionType_spec = {
"cython_function_or_method",
sizeof(__pyx_CyFunctionObject),
0,
// TODO: Support _Py_TPFLAGS_HAVE_VECTORCALL and _Py_TPFLAGS_HAVE_VECTORCALL
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
__pyx_CyFunctionType_slots
};
#else
static PyTypeObject __pyx_CyFunctionType_type = {
PyVarObject_HEAD_INIT(0, 0)
"cython_function_or_method", /*tp_name*/
......@@ -890,10 +923,15 @@ static PyTypeObject __pyx_CyFunctionType_type = {
0, /*tp_print*/
#endif
};
#endif /* CYTHON_COMPILING_IN_LIMITED_API */
static int __pyx_CyFunction_init(void) {
#if CYTHON_COMPILING_IN_LIMITED_API
__pyx_CyFunctionType = __Pyx_FetchCommonTypeFromSpec(&__pyx_CyFunctionType_spec, NULL);
#else
__pyx_CyFunctionType = __Pyx_FetchCommonType(&__pyx_CyFunctionType_type);
#endif
if (unlikely(__pyx_CyFunctionType == NULL)) {
return -1;
}
......@@ -965,7 +1003,7 @@ typedef struct {
} __pyx_FusedFunctionObject;
#define __pyx_FusedFunction_NewEx(ml, flags, qualname, closure, module, globals, code) \
__pyx_FusedFunction_New(__pyx_FusedFunctionType, ml, flags, qualname, closure, module, globals, code)
__pyx_FusedFunction_New((PyTypeObject *)__pyx_FusedFunctionType, ml, flags, qualname, closure, module, globals, code)
static PyObject *__pyx_FusedFunction_New(PyTypeObject *type,
PyMethodDef *ml, int flags,
PyObject *qualname, PyObject *closure,
......@@ -973,7 +1011,9 @@ static PyObject *__pyx_FusedFunction_New(PyTypeObject *type,
PyObject *code);
static int __pyx_FusedFunction_clear(__pyx_FusedFunctionObject *self);
#if !CYTHON_COMPILING_IN_LIMITED_API
static PyTypeObject *__pyx_FusedFunctionType = NULL;
#endif
static int __pyx_FusedFunction_init(void);
#define __Pyx_FusedFunction_USED
......@@ -1305,6 +1345,27 @@ static PyMappingMethods __pyx_FusedFunction_mapping_methods = {
0,
};
#if CYTHON_COMPILING_IN_LIMITED_API
static PyType_Slot __pyx_FusedFunctionType_slots[] = {
{Py_tp_dealloc, (void *)__pyx_FusedFunction_dealloc},
{Py_tp_call, (void *)__pyx_FusedFunction_call},
{Py_tp_traverse, (void *)__pyx_FusedFunction_traverse},
{Py_tp_clear, (void *)__pyx_FusedFunction_clear},
{Py_tp_members, (void *)__pyx_FusedFunction_members},
{Py_tp_getset, (void *)__pyx_CyFunction_getsets},
{Py_tp_descr_get, (void *)__pyx_FusedFunction_descr_get},
{Py_mp_ass_subscript, (void *)__pyx_FusedFunction_getitem},
{0, 0},
};
static PyType_Spec __pyx_FusedFunctionType_spec = {
"fused_cython_function",
sizeof(__pyx_FusedFunctionObject),
0,
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /*tp_flags*/
__pyx_FusedFunctionType_slots
};
#else
static PyTypeObject __pyx_FusedFunctionType_type = {
PyVarObject_HEAD_INIT(0, 0)
"fused_cython_function", /*tp_name*/
......@@ -1369,9 +1430,19 @@ static PyTypeObject __pyx_FusedFunctionType_type = {
0, /*tp_print*/
#endif
};
#endif
static int __pyx_FusedFunction_init(void) {
#if CYTHON_COMPILING_IN_LIMITED_API
PyObject *bases = PyTuple_Pack(1, __pyx_CyFunctionType);
if (unlikely(!bases)) {
return -1;
}
__pyx_FusedFunctionType = __Pyx_FetchCommonTypeFromSpec(&__pyx_FusedFunctionType_spec, bases);
Py_DECREF(bases);
#else
__pyx_FusedFunctionType = __Pyx_FetchCommonType(&__pyx_FusedFunctionType_type);
#endif
if (__pyx_FusedFunctionType == NULL) {
return -1;
}
......
......@@ -475,7 +475,7 @@ static PyTypeObject *__Pyx_ImportType(PyObject *module, const char *module_name,
PyObject *result = 0;
char warning[200];
Py_ssize_t basicsize;
#ifdef Py_LIMITED_API
#if CYTHON_COMPILING_IN_LIMITED_API
PyObject *py_basicsize;
#endif
......@@ -488,7 +488,7 @@ static PyTypeObject *__Pyx_ImportType(PyObject *module, const char *module_name,
module_name, class_name);
goto bad;
}
#ifndef Py_LIMITED_API
#if !CYTHON_COMPILING_IN_LIMITED_API
basicsize = ((PyTypeObject *)result)->tp_basicsize;
#else
py_basicsize = PyObject_GetAttrString(result, "__basicsize__");
......@@ -720,13 +720,17 @@ bad:
/////////////// GetVTable.proto ///////////////
static void* __Pyx_GetVtable(PyObject *dict); /*proto*/
static void* __Pyx_GetVtable(PyTypeObject *type); /*proto*/
/////////////// GetVTable ///////////////
static void* __Pyx_GetVtable(PyObject *dict) {
static void* __Pyx_GetVtable(PyTypeObject *type) {
void* ptr;
PyObject *ob = PyObject_GetItem(dict, PYIDENT("__pyx_vtable__"));
#if CYTHON_COMPILING_IN_LIMITED_API
PyObject *ob = PyObject_GetAttr((PyObject *)type, PYIDENT("__pyx_vtable__"));
#else
PyObject *ob = PyObject_GetItem(type->tp_dict, PYIDENT("__pyx_vtable__"));
#endif
if (!ob)
goto bad;
ptr = PyCapsule_GetPointer(ob, 0);
......@@ -769,13 +773,13 @@ static int __Pyx_MergeVtables(PyTypeObject *type) {
// instance struct is so extended. (It would be good to also do this
// check when a multiple-base class is created in pure Python as well.)
for (i = 1; i < PyTuple_GET_SIZE(bases); i++) {
void* base_vtable = __Pyx_GetVtable(((PyTypeObject*)PyTuple_GET_ITEM(bases, i))->tp_dict);
void* base_vtable = __Pyx_GetVtable(((PyTypeObject*)PyTuple_GET_ITEM(bases, i)));
if (base_vtable != NULL) {
int j;
PyTypeObject* base = type->tp_base;
for (j = 0; j < base_depth; j++) {
if (base_vtables[j] == unknown) {
base_vtables[j] = __Pyx_GetVtable(base->tp_dict);
base_vtables[j] = __Pyx_GetVtable(base);
base_vtables[j + 1] = unknown;
}
if (base_vtables[j] == base_vtable) {
......
......@@ -1293,7 +1293,7 @@ static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name)
if (unlikely(!$module_cname)) {
return NULL;
}
result = PyObject_GetItem($module_cname, name);
result = PyObject_GetAttr($module_cname, name);
if (likely(result)) {
return result;
}
......
......@@ -6,7 +6,7 @@
// but maybe some other profilers don't.
#ifndef CYTHON_PROFILE
#if CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_PYSTON
#if CYTHON_COMPILING_IN_LIMITED_API || CYTHON_COMPILING_IN_PYPY || CYTHON_COMPILING_IN_PYSTON
#define CYTHON_PROFILE 0
#else
#define CYTHON_PROFILE 1
......
......@@ -2372,6 +2372,7 @@ def runtests(options, cmd_args, coverage=None):
if options.limited_api:
CFLAGS.append("-DCYTHON_LIMITED_API=1")
CFLAGS.append('-Wno-unused-function')
if xml_output_dir and options.fork:
......
# This file contains tests corresponding to unresolved bugs using CPython's
# Limited API which will be skipped in the normal testing run.
calc_pi_2
calc_pi_3
calc_pi_4
clone
convolve2
cpdef_sin
dict_animal
integrate
landscaping
mymodule
not_none
overhead