Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 44 additions & 17 deletions Objects/typeobject.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -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

Expand DownExpand Up@@ -157,8 +156,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;
Expand DownExpand Up@@ -235,7 +234,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);

Expand DownExpand Up@@ -284,7 +283,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);
Expand All@@ -294,7 +293,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);
Expand DownExpand Up@@ -1258,6 +1257,19 @@ _PyType_GetVersionForCurrentState(PyTypeObject *tp)
#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)
{
Expand DownExpand Up@@ -1288,11 +1300,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 {
Expand DownExpand Up@@ -8704,7 +8717,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)) {
Expand All@@ -8718,13 +8735,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;
}
Expand DownExpand Up@@ -8857,7 +8878,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));
Expand DownExpand Up@@ -8906,15 +8932,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 {
Expand Down
Loading