Commit 12628a6b authored by scoder's avatar scoder Committed by GitHub

Use PyType_GetSlot() and friends in more places to reduce the special cases...

Use PyType_GetSlot() and friends in more places to reduce the special cases for type-specs / Limited-API (GH-4506)
parent f372c5ab
......@@ -1519,16 +1519,10 @@ 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
tp_new = "__Pyx_PyType_GetSlot(%s, tp_new, newfunc)" % 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")
......@@ -1694,9 +1688,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln(
"if (unlikely("
"(PY_VERSION_HEX >= 0x03080000 || __Pyx_PyType_HasFeature(Py_TYPE(o), Py_TPFLAGS_HAVE_FINALIZE))"
" && Py_TYPE(o)->tp_finalize) && %s) {" % finalised_check)
" && __Pyx_PyObject_GetSlot(o, tp_finalize, destructor)) && %s) {" % finalised_check)
code.putln("if (Py_TYPE(o)->tp_dealloc == %s) {" % slot_func_cname)
code.putln("if (__Pyx_PyObject_GetSlot(o, tp_dealloc, destructor) == %s) {" % slot_func_cname)
# if instance was resurrected by finaliser, return
code.putln("if (PyObject_CallFinalizerFromDealloc(o)) return;")
code.putln("}")
......@@ -1750,14 +1744,14 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
if tp_dealloc is not None:
code.putln("%s(o);" % tp_dealloc)
elif base_type.is_builtin_type:
code.putln("%s->tp_dealloc(o);" % base_type.typeptr_cname)
code.putln("__Pyx_PyType_GetSlot(%s, tp_dealloc, destructor)(o);" % base_type.typeptr_cname)
else:
# This is an externally defined type. Calling through the
# cimported base type pointer directly interacts badly with
# the module cleanup, which may already have cleared it.
# In that case, fall back to traversing the type hierarchy.
base_cname = base_type.typeptr_cname
code.putln("if (likely(%s)) %s->tp_dealloc(o); "
code.putln("if (likely(%s)) __Pyx_PyType_GetSlot(%s, tp_dealloc, destructor)(o); "
"else __Pyx_call_next_tp_dealloc(o, %s);" % (
base_cname, base_cname, slot_func_cname))
code.globalstate.use_utility_code(
......@@ -2275,7 +2269,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
"right, left" if reverse else "left, right",
extra_arg)
else:
return '%s_maybe_call_slot(%s->tp_base, left, right %s)' % (
return '%s_maybe_call_slot(__Pyx_PyType_GetSlot(%s, tp_base, PyTypeObject*), left, right %s)' % (
func_name,
scope.parent_type.typeptr_cname,
extra_arg)
......
......@@ -5273,13 +5273,14 @@ class CClassDefNode(ClassDefNode):
first_base = "((PyTypeObject*)PyTuple_GET_ITEM(%s, 0))" % bases
# Let Python do the base types compatibility checking.
trial_type = code.funcstate.allocate_temp(PyrexTypes.py_object_type, manage_ref=True)
code.putln("%s = PyType_Type.tp_new(&PyType_Type, %s, NULL);" % (
code.putln("%s = __Pyx_PyType_GetSlot(&PyType_Type, tp_new, newfunc)(&PyType_Type, %s, NULL);" % (
trial_type, self.type_init_args.result()))
code.putln(code.error_goto_if_null(trial_type, self.pos))
code.put_gotref(trial_type, py_object_type)
code.putln("if (((PyTypeObject*) %s)->tp_base != %s) {" % (
code.putln("if (__Pyx_PyType_GetSlot((PyTypeObject*) %s, tp_base, PyTypeObject*) != %s) {" % (
trial_type, first_base))
code.putln("__Pyx_TypeName base_name = __Pyx_PyType_GetName(((PyTypeObject*) %s)->tp_base);" % trial_type)
trial_type_base = "__Pyx_PyType_GetSlot((PyTypeObject*) %s, tp_base, PyTypeObject*)" % trial_type
code.putln("__Pyx_TypeName base_name = __Pyx_PyType_GetName(%s);" % trial_type_base)
code.putln("__Pyx_TypeName type_name = __Pyx_PyType_GetName(%s);" % first_base)
code.putln("PyErr_Format(PyExc_TypeError, "
"\"best base '\" __Pyx_FMT_TYPENAME \"' must be equal to first base '\" __Pyx_FMT_TYPENAME \"'\",")
......
......@@ -178,7 +178,8 @@ static int __Pyx_PyType_Ready(PyTypeObject *t) {
#else
int r;
if (t->tp_bases && unlikely(__Pyx_validate_bases_tuple(t->tp_name, t->tp_dictoffset, t->tp_bases) == -1))
PyObject *bases = __Pyx_PyType_GetSlot(t, tp_bases, PyObject*);
if (bases && unlikely(__Pyx_validate_bases_tuple(t->tp_name, t->tp_dictoffset, bases) == -1))
return -1;
#if PY_VERSION_HEX >= 0x03050000 && !defined(PYSTON_MAJOR_VERSION)
......@@ -308,7 +309,7 @@ static int __Pyx_PyType_Ready(PyTypeObject *t) {
} while (0);
#define __Pyx_TRASHCAN_BEGIN(op, dealloc) __Pyx_TRASHCAN_BEGIN_CONDITION(op, \
Py_TYPE(op)->tp_dealloc == (destructor)(dealloc))
__Pyx_PyObject_GetSlot(op, tp_dealloc, destructor) == (destructor)(dealloc))
#else
// The trashcan is a no-op on other Python implementations
......@@ -325,13 +326,14 @@ static void __Pyx_call_next_tp_dealloc(PyObject* obj, destructor current_tp_deal
static void __Pyx_call_next_tp_dealloc(PyObject* obj, destructor current_tp_dealloc) {
PyTypeObject* type = Py_TYPE(obj);
destructor tp_dealloc = NULL;
/* try to find the first parent type that has a different tp_dealloc() function */
while (type && type->tp_dealloc != current_tp_dealloc)
type = type->tp_base;
while (type && type->tp_dealloc == current_tp_dealloc)
type = type->tp_base;
while (type && __Pyx_PyType_GetSlot(type, tp_dealloc, destructor) != current_tp_dealloc)
type = __Pyx_PyType_GetSlot(type, tp_base, PyTypeObject*);
while (type && (tp_dealloc = __Pyx_PyType_GetSlot(type, tp_dealloc, destructor)) == current_tp_dealloc)
type = __Pyx_PyType_GetSlot(type, tp_base, PyTypeObject*);
if (type)
type->tp_dealloc(obj);
tp_dealloc(obj);
}
/////////////// CallNextTpTraverse.proto ///////////////
......@@ -342,32 +344,34 @@ static int __Pyx_call_next_tp_traverse(PyObject* obj, visitproc v, void *a, trav
static int __Pyx_call_next_tp_traverse(PyObject* obj, visitproc v, void *a, traverseproc current_tp_traverse) {
PyTypeObject* type = Py_TYPE(obj);
traverseproc tp_traverse = NULL;
/* try to find the first parent type that has a different tp_traverse() function */
while (type && type->tp_traverse != current_tp_traverse)
type = type->tp_base;
while (type && type->tp_traverse == current_tp_traverse)
type = type->tp_base;
if (type && type->tp_traverse)
return type->tp_traverse(obj, v, a);
while (type && __Pyx_PyType_GetSlot(type, tp_traverse, traverseproc) != current_tp_traverse)
type = __Pyx_PyType_GetSlot(type, tp_base, PyTypeObject*);
while (type && (tp_traverse = __Pyx_PyType_GetSlot(type, tp_traverse, traverseproc)) == current_tp_traverse)
type = __Pyx_PyType_GetSlot(type, tp_base, PyTypeObject*);
if (type && tp_traverse)
return tp_traverse(obj, v, a);
// FIXME: really ignore?
return 0;
}
/////////////// CallNextTpClear.proto ///////////////
static void __Pyx_call_next_tp_clear(PyObject* obj, inquiry current_tp_dealloc);
static void __Pyx_call_next_tp_clear(PyObject* obj, inquiry current_tp_clear);
/////////////// CallNextTpClear ///////////////
static void __Pyx_call_next_tp_clear(PyObject* obj, inquiry current_tp_clear) {
PyTypeObject* type = Py_TYPE(obj);
inquiry tp_clear = NULL;
/* try to find the first parent type that has a different tp_clear() function */
while (type && type->tp_clear != current_tp_clear)
type = type->tp_base;
while (type && type->tp_clear == current_tp_clear)
type = type->tp_base;
if (type && type->tp_clear)
type->tp_clear(obj);
while (type && __Pyx_PyType_GetSlot(type, tp_clear, inquiry) != current_tp_clear)
type = __Pyx_PyType_GetSlot(type, tp_base, PyTypeObject*);
while (type && (tp_clear = __Pyx_PyType_GetSlot(type, tp_clear, inquiry)) == current_tp_clear)
type = __Pyx_PyType_GetSlot(type, tp_base, PyTypeObject*);
if (type && tp_clear)
tp_clear(obj);
}
/////////////// SetupReduce.proto ///////////////
......
......@@ -724,6 +724,13 @@ static CYTHON_INLINE void *__Pyx_PyModule_GetState(PyObject *op)
}
#endif
#define __Pyx_PyObject_GetSlot(obj, name, func_ctype) __Pyx_PyType_GetSlot(Py_TYPE(obj), name, func_ctype)
#if CYTHON_COMPILING_IN_LIMITED_API
#define __Pyx_PyType_GetSlot(type, name, func_ctype) ((func_ctype) PyType_GetSlot((type), Py_##name))
#else
#define __Pyx_PyType_GetSlot(type, name, func_ctype) ((type)->name)
#endif
// TSS (Thread Specific Storage) API
#if PY_VERSION_HEX < 0x030700A2 && !defined(PyThread_tss_create) && !defined(Py_tss_NEEDS_INIT)
#include "pythread.h"
......@@ -1136,7 +1143,7 @@ static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObj
#if CYTHON_COMPILING_IN_CPYTHON
static int __Pyx_InBases(PyTypeObject *a, PyTypeObject *b) {
while (a) {
a = a->tp_base;
a = __Pyx_PyType_GetSlot(a, tp_base, PyTypeObject*);
if (a == b)
return 1;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment