Skip to content

Commit 3529f0f

Browse files
Only store builtins state on the interpreter state.
1 parent df204e8 commit 3529f0f

File tree

2 files changed

+28
-114
lines changed

2 files changed

+28
-114
lines changed

Include/internal/pycore_typeobject.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,13 @@ struct type_cache {
4545

4646
typedef struct {
4747
PyTypeObject *type;
48+
PyObject *subclasses;
4849
} static_builtin_state;
4950

5051
struct types_state {
5152
struct type_cache type_cache;
5253
size_t num_builtins_initialized;
5354
static_builtin_state builtins[_Py_MAX_STATIC_BUILTIN_TYPES];
54-
PyObject *subclasses;
5555
};
5656

5757

Objects/typeobject.c

Lines changed: 27 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ static_builtin_state_clear(PyTypeObject *self)
138138

139139
static_builtin_state *state = static_builtin_state_get(interp, self);
140140
state->type = NULL;
141+
/* state->subclasses is left NULL until init_subclasses() sets it. */
141142
static_builtin_index_clear(self);
142143

143144
assert(interp->types.num_builtins_initialized > 0);
@@ -149,49 +150,6 @@ static_builtin_state_clear(PyTypeObject *self)
149150
/* end static builtin helpers */
150151

151152

152-
static Py_hash_t slot_tp_hash(PyObject *self);
153-
static inline PyObject * lookup___hash__(PyObject *self, int *unbound);
154-
155-
static int
156-
is_hashable(PyObject *obj)
157-
{
158-
PyTypeObject *cls = Py_TYPE(obj);
159-
if (cls->tp_hash != NULL &&
160-
cls->tp_hash != PyObject_HashNotImplemented)
161-
{
162-
if (cls->tp_hash != slot_tp_hash) {
163-
return 1;
164-
}
165-
int unbound;
166-
if (lookup___hash__((PyObject *)cls, &unbound) != NULL) {
167-
return 1;
168-
}
169-
if (PyErr_Occurred()) {
170-
return -1;
171-
}
172-
}
173-
return 0;
174-
}
175-
176-
static inline Py_hash_t
177-
get_hash_with_fallback(PyObject *obj)
178-
{
179-
Py_hash_t hash = PyObject_Hash(obj);
180-
if (hash < 0) {
181-
if (!PyErr_ExceptionMatches(PyExc_TypeError) ||
182-
is_hashable((PyObject *)obj))
183-
{
184-
PyErr_WarnEx(PyExc_RuntimeWarning, "failed to hash object", 1);
185-
}
186-
// Fall back to object.__hash__().
187-
PyErr_Clear();
188-
hash = _Py_HashPointer(obj);
189-
assert(!PyErr_Occurred());
190-
}
191-
return hash;
192-
}
193-
194-
195153
/*
196154
* finds the beginning of the docstring's introspection signature.
197155
* if present, returns a pointer pointing to the first '('.
@@ -4464,28 +4422,22 @@ type_dealloc(PyTypeObject *type)
44644422
static PyObject *
44654423
lookup_subclasses(PyTypeObject *self)
44664424
{
4467-
// XXX Drop tp_subclasses?
4468-
// Heap types are guaranteed to be per-interpreter.
4469-
if (self->tp_flags & Py_TPFLAGS_HEAPTYPE) {
4470-
return self->tp_subclasses;
4471-
}
4472-
// For static types we store them per-interpreter.
4473-
PyInterpreterState *interp = _PyInterpreterState_GET();
4474-
if (interp->types.subclasses == NULL) {
4475-
return NULL;
4425+
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
4426+
static_builtin_state *state = _PyStaticType_GetState(self);
4427+
assert(state != NULL);
4428+
return state->subclasses;
44764429
}
4477-
/* We must handle the rare case where the metaclass
4478-
of the given type makes it unhashable. */
4479-
Py_hash_t hash = get_hash_with_fallback((PyObject *)self);
4480-
return _PyDict_GetItem_KnownHash(interp->types.subclasses,
4481-
(PyObject *)self, hash);
4430+
return self->tp_subclasses;
44824431
}
44834432

44844433
int
44854434
_PyType_HasSubclasses(PyTypeObject *self)
44864435
{
4487-
PyObject *subclasses = lookup_subclasses(self);
4488-
if (subclasses == NULL) {
4436+
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN &&
4437+
_PyStaticType_GetState(self) == NULL) {
4438+
return 0;
4439+
}
4440+
if (lookup_subclasses(self) == NULL) {
44894441
return PyErr_Occurred() ? -1 : 0;
44904442
}
44914443
return 1;
@@ -6883,30 +6835,16 @@ _PyStaticType_InitBuiltin(PyTypeObject *self)
68836835
static PyObject *
68846836
init_subclasses(PyTypeObject *self)
68856837
{
6886-
// Heap types are guaranteed to be per-interpreter.
6887-
if (self->tp_flags & Py_TPFLAGS_HEAPTYPE) {
6888-
self->tp_subclasses = PyDict_New();
6889-
return self->tp_subclasses;
6890-
}
68916838
PyObject *subclasses = PyDict_New();
68926839
if (subclasses == NULL) {
68936840
return NULL;
68946841
}
6895-
PyInterpreterState *interp = _PyInterpreterState_GET();
6896-
if (interp->types.subclasses == NULL) {
6897-
interp->types.subclasses = PyDict_New();
6898-
if (interp->types.subclasses == NULL) {
6899-
Py_DECREF(subclasses);
6900-
return NULL;
6901-
}
6842+
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
6843+
static_builtin_state *state = _PyStaticType_GetState(self);
6844+
state->subclasses = subclasses;
69026845
}
6903-
/* We must handle the rare case where the metaclass
6904-
of the given type makes it unhashable. */
6905-
Py_hash_t hash = get_hash_with_fallback((PyObject *)self);
6906-
int res = _PyDict_SetItem_KnownHash(interp->types.subclasses,
6907-
(PyObject *)self, subclasses, hash);
6908-
Py_DECREF(subclasses);
6909-
return res == 0 ? subclasses : NULL;
6846+
self->tp_subclasses = subclasses;
6847+
return subclasses;
69106848
}
69116849

69126850
static void
@@ -6915,27 +6853,12 @@ clear_subclasses(PyTypeObject *self)
69156853
/* Delete the dictionary to save memory. _PyStaticType_Dealloc()
69166854
callers also test if tp_subclasses is NULL to check if a static type
69176855
has no subclass. */
6918-
// Heap types are guaranteed to be per-interpreter.
6919-
if (self->tp_flags & Py_TPFLAGS_HEAPTYPE) {
6920-
Py_CLEAR(self->tp_subclasses);
6921-
return;
6922-
}
6923-
PyInterpreterState *interp = _PyInterpreterState_GET();
6924-
if (interp->types.subclasses == NULL) {
6925-
return;
6926-
}
6927-
/* We must handle the rare case where the metaclass
6928-
of the given type makes it unhashable. */
6929-
Py_hash_t hash = get_hash_with_fallback((PyObject *)self);
6930-
int res = _PyDict_DelItem_KnownHash(interp->types.subclasses,
6931-
(PyObject *)self, hash);
6932-
if (res != 0) {
6933-
PyErr_Clear();
6856+
if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
6857+
static_builtin_state *state = _PyStaticType_GetState(self);
6858+
Py_CLEAR(state->subclasses);
69346859
return;
69356860
}
6936-
if (PyDict_GET_SIZE(interp->types.subclasses) == 0) {
6937-
Py_CLEAR(interp->types.subclasses);
6938-
}
6861+
Py_CLEAR(self->tp_subclasses);
69396862
}
69406863

69416864
static int
@@ -8022,30 +7945,21 @@ slot_tp_repr(PyObject *self)
80227945

80237946
SLOT0(slot_tp_str, __str__)
80247947

8025-
8026-
static inline PyObject *
8027-
lookup___hash__(PyObject *self, int *unbound)
8028-
{
8029-
PyObject *func = lookup_maybe_method(self, &_Py_ID(__hash__), unbound);
8030-
if (func == Py_None) {
8031-
Py_DECREF(func);
8032-
func = NULL;
8033-
}
8034-
return func;
8035-
}
8036-
80377948
static Py_hash_t
80387949
slot_tp_hash(PyObject *self)
80397950
{
80407951
PyObject *func, *res;
80417952
Py_ssize_t h;
80427953
int unbound;
80437954

8044-
func = lookup___hash__(self, &unbound);
7955+
func = lookup_maybe_method(self, &_Py_ID(__hash__), &unbound);
7956+
7957+
if (func == Py_None) {
7958+
Py_DECREF(func);
7959+
func = NULL;
7960+
}
7961+
80457962
if (func == NULL) {
8046-
if (PyErr_Occurred()) {
8047-
return -1;
8048-
}
80497963
return PyObject_HashNotImplemented(self);
80507964
}
80517965

0 commit comments

Comments
 (0)