aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Objects
diff options
context:
space:
mode:
Diffstat (limited to 'Objects')
-rw-r--r--Objects/descrobject.c5
-rw-r--r--Objects/namespaceobject.c8
-rw-r--r--Objects/object.c38
-rw-r--r--Objects/typeobject.c61
4 files changed, 83 insertions, 29 deletions
diff --git a/Objects/descrobject.c b/Objects/descrobject.c
index 10c465b95ac..d3d17e92b6d 100644
--- a/Objects/descrobject.c
+++ b/Objects/descrobject.c
@@ -1233,7 +1233,10 @@ static PyObject *
mappingproxy_richcompare(PyObject *self, PyObject *w, int op)
{
mappingproxyobject *v = (mappingproxyobject *)self;
- return PyObject_RichCompare(v->mapping, w, op);
+ if (op == Py_EQ || op == Py_NE) {
+ return PyObject_RichCompare(v->mapping, w, op);
+ }
+ Py_RETURN_NOTIMPLEMENTED;
}
static int
diff --git a/Objects/namespaceobject.c b/Objects/namespaceobject.c
index 0fc2bcea4cb..201cb8a7df8 100644
--- a/Objects/namespaceobject.c
+++ b/Objects/namespaceobject.c
@@ -194,10 +194,14 @@ namespace_clear(PyObject *op)
static PyObject *
namespace_richcompare(PyObject *self, PyObject *other, int op)
{
- if (PyObject_TypeCheck(self, &_PyNamespace_Type) &&
- PyObject_TypeCheck(other, &_PyNamespace_Type))
+ if (
+ (op == Py_EQ || op == Py_NE) &&
+ PyObject_TypeCheck(self, &_PyNamespace_Type) &&
+ PyObject_TypeCheck(other, &_PyNamespace_Type)
+ ) {
return PyObject_RichCompare(((_PyNamespaceObject *)self)->ns_dict,
((_PyNamespaceObject *)other)->ns_dict, op);
+ }
Py_RETURN_NOTIMPLEMENTED;
}
diff --git a/Objects/object.c b/Objects/object.c
index 1223983753a..3ed7d55593d 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -1213,16 +1213,27 @@ PyObject_HasAttrString(PyObject *obj, const char *name)
int
PyObject_SetAttrString(PyObject *v, const char *name, PyObject *w)
{
- PyObject *s;
- int res;
+ PyThreadState *tstate = _PyThreadState_GET();
+ if (w == NULL && _PyErr_Occurred(tstate)) {
+ PyObject *exc = _PyErr_GetRaisedException(tstate);
+ _PyErr_SetString(tstate, PyExc_SystemError,
+ "PyObject_SetAttrString() must not be called with NULL value "
+ "and an exception set");
+ _PyErr_ChainExceptions1Tstate(tstate, exc);
+ return -1;
+ }
- if (Py_TYPE(v)->tp_setattr != NULL)
+ if (Py_TYPE(v)->tp_setattr != NULL) {
return (*Py_TYPE(v)->tp_setattr)(v, (char*)name, w);
- s = PyUnicode_InternFromString(name);
- if (s == NULL)
+ }
+
+ PyObject *s = PyUnicode_InternFromString(name);
+ if (s == NULL) {
return -1;
- res = PyObject_SetAttr(v, s, w);
- Py_XDECREF(s);
+ }
+
+ int res = PyObject_SetAttr(v, s, w);
+ Py_DECREF(s);
return res;
}
@@ -1440,6 +1451,16 @@ PyObject_HasAttr(PyObject *obj, PyObject *name)
int
PyObject_SetAttr(PyObject *v, PyObject *name, PyObject *value)
{
+ PyThreadState *tstate = _PyThreadState_GET();
+ if (value == NULL && _PyErr_Occurred(tstate)) {
+ PyObject *exc = _PyErr_GetRaisedException(tstate);
+ _PyErr_SetString(tstate, PyExc_SystemError,
+ "PyObject_SetAttr() must not be called with NULL value "
+ "and an exception set");
+ _PyErr_ChainExceptions1Tstate(tstate, exc);
+ return -1;
+ }
+
PyTypeObject *tp = Py_TYPE(v);
int err;
@@ -1451,8 +1472,7 @@ PyObject_SetAttr(PyObject *v, PyObject *name, PyObject *value)
}
Py_INCREF(name);
- PyInterpreterState *interp = _PyInterpreterState_GET();
- _PyUnicode_InternMortal(interp, &name);
+ _PyUnicode_InternMortal(tstate->interp, &name);
if (tp->tp_setattro != NULL) {
err = (*tp->tp_setattro)(v, name, value);
Py_DECREF(name);
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 6e7471cb594..e84278d13c3 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -54,7 +54,6 @@ class object "PyObject *" "&PyBaseObject_Type"
PyUnicode_CheckExact(name) && \
(PyUnicode_GET_LENGTH(name) <= MCACHE_MAX_ATTR_SIZE)
-#define NEXT_GLOBAL_VERSION_TAG _PyRuntime.types.next_version_tag
#define NEXT_VERSION_TAG(interp) \
(interp)->types.next_version_tag
@@ -266,8 +265,8 @@ static_ext_type_lookup(PyInterpreterState *interp, size_t index,
assert(index < _Py_MAX_MANAGED_STATIC_EXT_TYPES);
size_t full_index = index + _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES;
- int64_t interp_count =
- _PyRuntime.types.managed_static.types[full_index].interp_count;
+ int64_t interp_count = _Py_atomic_load_int64(
+ &_PyRuntime.types.managed_static.types[full_index].interp_count);
assert((interp_count == 0) ==
(_PyRuntime.types.managed_static.types[full_index].type == NULL));
*p_interp_count = interp_count;
@@ -344,7 +343,7 @@ managed_static_type_state_init(PyInterpreterState *interp, PyTypeObject *self,
: index + _Py_MAX_MANAGED_STATIC_BUILTIN_TYPES;
assert((initial == 1) ==
- (_PyRuntime.types.managed_static.types[full_index].interp_count == 0));
+ (_Py_atomic_load_int64(&_PyRuntime.types.managed_static.types[full_index].interp_count) == 0));
(void)_Py_atomic_add_int64(
&_PyRuntime.types.managed_static.types[full_index].interp_count, 1);
@@ -393,7 +392,7 @@ managed_static_type_state_clear(PyInterpreterState *interp, PyTypeObject *self,
: &(interp->types.for_extensions.initialized[index]);
assert(state != NULL);
- assert(_PyRuntime.types.managed_static.types[full_index].interp_count > 0);
+ assert(_Py_atomic_load_int64(&_PyRuntime.types.managed_static.types[full_index].interp_count) > 0);
assert(_PyRuntime.types.managed_static.types[full_index].type == state->type);
assert(state->type != NULL);
@@ -403,7 +402,7 @@ managed_static_type_state_clear(PyInterpreterState *interp, PyTypeObject *self,
(void)_Py_atomic_add_int64(
&_PyRuntime.types.managed_static.types[full_index].interp_count, -1);
if (final) {
- assert(!_PyRuntime.types.managed_static.types[full_index].interp_count);
+ assert(!_Py_atomic_load_int64(&_PyRuntime.types.managed_static.types[full_index].interp_count));
_PyRuntime.types.managed_static.types[full_index].type = NULL;
managed_static_type_index_clear(self);
@@ -1359,6 +1358,19 @@ _PyType_LookupByVersion(unsigned int version)
#error "_Py_ATTR_CACHE_UNUSED must be bigger than max"
#endif
+static inline unsigned int
+next_global_version_tag(void)
+{
+ unsigned int old;
+ do {
+ old = _Py_atomic_load_uint_relaxed(&_PyRuntime.types.next_version_tag);
+ if (old >= _Py_MAX_GLOBAL_TYPE_VERSION_TAG) {
+ return 0;
+ }
+ } while (!_Py_atomic_compare_exchange_uint(&_PyRuntime.types.next_version_tag, &old, old + 1));
+ return old + 1;
+}
+
static int
assign_version_tag(PyInterpreterState *interp, PyTypeObject *type)
{
@@ -1389,11 +1401,12 @@ assign_version_tag(PyInterpreterState *interp, PyTypeObject *type)
}
if (type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) {
/* static types */
- if (NEXT_GLOBAL_VERSION_TAG > _Py_MAX_GLOBAL_TYPE_VERSION_TAG) {
+ unsigned int next_version_tag = next_global_version_tag();
+ if (next_version_tag == 0) {
/* We have run out of version numbers */
return 0;
}
- set_version_unlocked(type, NEXT_GLOBAL_VERSION_TAG++);
+ set_version_unlocked(type, next_version_tag);
assert (type->tp_version_tag <= _Py_MAX_GLOBAL_TYPE_VERSION_TAG);
}
else {
@@ -9007,7 +9020,11 @@ type_ready_set_new(PyTypeObject *type, int initial)
&& base == &PyBaseObject_Type
&& !(type->tp_flags & Py_TPFLAGS_HEAPTYPE))
{
- type_add_flags(type, Py_TPFLAGS_DISALLOW_INSTANTIATION);
+ if (initial) {
+ type_add_flags(type, Py_TPFLAGS_DISALLOW_INSTANTIATION);
+ } else {
+ assert(type->tp_flags & Py_TPFLAGS_DISALLOW_INSTANTIATION);
+ }
}
if (!(type->tp_flags & Py_TPFLAGS_DISALLOW_INSTANTIATION)) {
@@ -9021,13 +9038,17 @@ type_ready_set_new(PyTypeObject *type, int initial)
}
}
else {
- // tp_new is NULL: inherit tp_new from base
- type->tp_new = base->tp_new;
+ if (initial) {
+ // tp_new is NULL: inherit tp_new from base
+ type->tp_new = base->tp_new;
+ }
}
}
else {
// Py_TPFLAGS_DISALLOW_INSTANTIATION sets tp_new to NULL
- type->tp_new = NULL;
+ if (initial) {
+ type->tp_new = NULL;
+ }
}
return 0;
}
@@ -9160,7 +9181,12 @@ type_ready(PyTypeObject *type, int initial)
}
/* All done -- set the ready flag */
- type_add_flags(type, Py_TPFLAGS_READY);
+ if (initial) {
+ type_add_flags(type, Py_TPFLAGS_READY);
+ } else {
+ assert(type->tp_flags & Py_TPFLAGS_READY);
+ }
+
stop_readying(type);
assert(_PyType_CheckConsistency(type));
@@ -9209,15 +9235,16 @@ init_static_type(PyInterpreterState *interp, PyTypeObject *self,
assert(!(self->tp_flags & Py_TPFLAGS_MANAGED_DICT));
assert(!(self->tp_flags & Py_TPFLAGS_MANAGED_WEAKREF));
- if ((self->tp_flags & Py_TPFLAGS_READY) == 0) {
- assert(initial);
+ if (initial) {
+ assert((self->tp_flags & Py_TPFLAGS_READY) == 0);
type_add_flags(self, _Py_TPFLAGS_STATIC_BUILTIN);
type_add_flags(self, Py_TPFLAGS_IMMUTABLETYPE);
- assert(NEXT_GLOBAL_VERSION_TAG <= _Py_MAX_GLOBAL_TYPE_VERSION_TAG);
if (self->tp_version_tag == 0) {
- _PyType_SetVersion(self, NEXT_GLOBAL_VERSION_TAG++);
+ unsigned int next_version_tag = next_global_version_tag();
+ assert(next_version_tag != 0);
+ _PyType_SetVersion(self, next_version_tag);
}
}
else {