summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2020-04-07 23:42:27 (GMT)
committerGitHub <noreply@github.com>2020-04-07 23:42:27 (GMT)
commit45ec5b99aefa54552947049086e87ec01bc2fc9a (patch)
tree991c703174190872d806ae18387e69d62ff69c76 /Objects
parentef5c615f5ae72c4f6979159c94da46afefbfab9a (diff)
downloadcpython-45ec5b99aefa54552947049086e87ec01bc2fc9a.zip
cpython-45ec5b99aefa54552947049086e87ec01bc2fc9a.tar.gz
cpython-45ec5b99aefa54552947049086e87ec01bc2fc9a.tar.bz2
bpo-40170: PyType_HasFeature() now always calls PyType_GetFlags() (GH-19378)
PyType_HasFeature() now always calls PyType_GetFlags() to hide implementation details. Previously, it accessed directly the PyTypeObject.tp_flags member when the limited C API was not used. Add fast inlined version _PyType_HasFeature() and _PyType_IS_GC() for object.c and typeobject.c.
Diffstat (limited to 'Objects')
-rw-r--r--Objects/object.c10
-rw-r--r--Objects/typeobject.c47
2 files changed, 32 insertions, 25 deletions
diff --git a/Objects/object.c b/Objects/object.c
index 069afc0..ef4ba99 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -188,11 +188,11 @@ PyObject_CallFinalizer(PyObject *self)
if (tp->tp_finalize == NULL)
return;
/* tp_finalize should only be called once. */
- if (PyType_IS_GC(tp) && _PyGC_FINALIZED(self))
+ if (_PyType_IS_GC(tp) && _PyGC_FINALIZED(self))
return;
tp->tp_finalize(self);
- if (PyType_IS_GC(tp)) {
+ if (_PyType_IS_GC(tp)) {
_PyGC_SET_FINALIZED(self);
}
}
@@ -229,7 +229,7 @@ PyObject_CallFinalizerFromDealloc(PyObject *self)
Py_SET_REFCNT(self, refcnt);
_PyObject_ASSERT(self,
- (!PyType_IS_GC(Py_TYPE(self))
+ (!_PyType_IS_GC(Py_TYPE(self))
|| _PyObject_GC_IS_TRACKED(self)));
/* If Py_REF_DEBUG macro is defined, _Py_NewReference() increased
_Py_RefTotal, so we need to undo that. */
@@ -1104,7 +1104,7 @@ _PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method)
descr = _PyType_Lookup(tp, name);
if (descr != NULL) {
Py_INCREF(descr);
- if (PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)) {
+ if (_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR)) {
meth_found = 1;
} else {
f = Py_TYPE(descr)->tp_descr_get;
@@ -2177,7 +2177,7 @@ _PyObject_AssertFailed(PyObject *obj, const char *expr, const char *msg,
to crash than dumping the traceback. */
void *ptr;
PyTypeObject *type = Py_TYPE(obj);
- if (PyType_IS_GC(type)) {
+ if (_PyType_IS_GC(type)) {
ptr = (void *)((char *)obj - sizeof(PyGC_Head));
}
else {
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index bdd16af..ca26d96 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -269,7 +269,7 @@ PyType_Modified(PyTypeObject *type)
PyObject *raw, *ref;
Py_ssize_t i;
- if (!PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG))
+ if (!_PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG))
return;
raw = type->tp_subclasses;
@@ -307,7 +307,7 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) {
PyObject *mro_meth = NULL;
PyObject *type_mro_meth = NULL;
- if (!PyType_HasFeature(type, Py_TPFLAGS_HAVE_VERSION_TAG))
+ if (!_PyType_HasFeature(type, Py_TPFLAGS_HAVE_VERSION_TAG))
return;
if (custom) {
@@ -332,7 +332,7 @@ type_mro_modified(PyTypeObject *type, PyObject *bases) {
assert(PyType_Check(b));
cls = (PyTypeObject *)b;
- if (!PyType_HasFeature(cls, Py_TPFLAGS_HAVE_VERSION_TAG) ||
+ if (!_PyType_HasFeature(cls, Py_TPFLAGS_HAVE_VERSION_TAG) ||
!PyType_IsSubtype(type, cls)) {
goto clear;
}
@@ -356,11 +356,11 @@ assign_version_tag(PyTypeObject *type)
Py_ssize_t i, n;
PyObject *bases;
- if (PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG))
+ if (_PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG))
return 1;
- if (!PyType_HasFeature(type, Py_TPFLAGS_HAVE_VERSION_TAG))
+ if (!_PyType_HasFeature(type, Py_TPFLAGS_HAVE_VERSION_TAG))
return 0;
- if (!PyType_HasFeature(type, Py_TPFLAGS_READY))
+ if (!_PyType_HasFeature(type, Py_TPFLAGS_READY))
return 0;
type->tp_version_tag = next_version_tag++;
@@ -1028,23 +1028,29 @@ PyType_GenericAlloc(PyTypeObject *type, Py_ssize_t nitems)
const size_t size = _PyObject_VAR_SIZE(type, nitems+1);
/* note that we need to add one, for the sentinel */
- if (PyType_IS_GC(type))
+ if (_PyType_IS_GC(type)) {
obj = _PyObject_GC_Malloc(size);
- else
+ }
+ else {
obj = (PyObject *)PyObject_MALLOC(size);
+ }
- if (obj == NULL)
+ if (obj == NULL) {
return PyErr_NoMemory();
+ }
memset(obj, '\0', size);
- if (type->tp_itemsize == 0)
+ if (type->tp_itemsize == 0) {
(void)PyObject_INIT(obj, type);
- else
+ }
+ else {
(void) PyObject_INIT_VAR((PyVarObject *)obj, type, nitems);
+ }
- if (PyType_IS_GC(type))
+ if (_PyType_IS_GC(type)) {
_PyObject_GC_TRACK(obj);
+ }
return obj;
}
@@ -1178,7 +1184,7 @@ subtype_dealloc(PyObject *self)
/* Test whether the type has GC exactly once */
- if (!PyType_IS_GC(type)) {
+ if (!_PyType_IS_GC(type)) {
/* A non GC dynamic type allows certain simplifications:
there's no need to call clear_slots(), or DECREF the dict,
or clear weakrefs. */
@@ -1304,8 +1310,9 @@ subtype_dealloc(PyObject *self)
/* Call the base tp_dealloc(); first retrack self if
* basedealloc knows about gc.
*/
- if (PyType_IS_GC(base))
+ if (_PyType_IS_GC(base)) {
_PyObject_GC_TRACK(self);
+ }
assert(basedealloc);
basedealloc(self);
@@ -1435,7 +1442,7 @@ lookup_maybe_method(PyObject *self, _Py_Identifier *attrid, int *unbound)
return NULL;
}
- if (PyType_HasFeature(Py_TYPE(res), Py_TPFLAGS_METHOD_DESCRIPTOR)) {
+ if (_PyType_HasFeature(Py_TYPE(res), Py_TPFLAGS_METHOD_DESCRIPTOR)) {
/* Avoid temporary PyMethodObject */
*unbound = 1;
Py_INCREF(res);
@@ -2026,7 +2033,7 @@ best_base(PyObject *bases)
if (PyType_Ready(base_i) < 0)
return NULL;
}
- if (!PyType_HasFeature(base_i, Py_TPFLAGS_BASETYPE)) {
+ if (!_PyType_HasFeature(base_i, Py_TPFLAGS_BASETYPE)) {
PyErr_Format(PyExc_TypeError,
"type '%.100s' is not an acceptable base type",
base_i->tp_name);
@@ -2933,7 +2940,7 @@ PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases)
if (base == NULL) {
goto fail;
}
- if (!PyType_HasFeature(base, Py_TPFLAGS_BASETYPE)) {
+ if (!_PyType_HasFeature(base, Py_TPFLAGS_BASETYPE)) {
PyErr_Format(PyExc_TypeError,
"type '%.100s' is not an acceptable base type",
base->tp_name);
@@ -3051,7 +3058,7 @@ PyType_FromSpec(PyType_Spec *spec)
void *
PyType_GetSlot(PyTypeObject *type, int slot)
{
- if (!PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE) || slot < 0) {
+ if (!_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE) || slot < 0) {
PyErr_BadInternalCall();
return NULL;
}
@@ -3134,7 +3141,7 @@ _PyType_Lookup(PyTypeObject *type, PyObject *name)
unsigned int h;
if (MCACHE_CACHEABLE_NAME(name) &&
- PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG)) {
+ _PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG)) {
/* fast path */
h = MCACHE_HASH_METHOD(type, name);
if (method_cache[h].version == type->tp_version_tag &&
@@ -5404,7 +5411,7 @@ PyType_Ready(PyTypeObject *type)
}
/* Sanity check for tp_free. */
- if (PyType_IS_GC(type) && (type->tp_flags & Py_TPFLAGS_BASETYPE) &&
+ if (_PyType_IS_GC(type) && (type->tp_flags & Py_TPFLAGS_BASETYPE) &&
(type->tp_free == NULL || type->tp_free == PyObject_Del)) {
/* This base class needs to call tp_free, but doesn't have
* one, or its tp_free is for non-gc'ed objects.