Skip to content

Commit 8cf19e8

Browse files
Use type_slots_ptrs cache
1 parent 8d1f5be commit 8cf19e8

File tree

1 file changed

+34
-33
lines changed

1 file changed

+34
-33
lines changed

Objects/typeobject.c

+34-33
Original file line numberDiff line numberDiff line change
@@ -11005,22 +11005,15 @@ slotptr(PyTypeObject *type, int ioffset)
1100511005
return (void **)ptr;
1100611006
}
1100711007

11008-
/* Return a slot pointer for a given name, but ONLY if the attribute has
11009-
exactly one slot function. The name must be an interned string. */
11010-
static void **
11011-
resolve_slotdups(PyTypeObject *type, PyObject *name)
11008+
static int
11009+
fill_type_slots_cache_from_slotdefs_cache(PyInterpreterState *interp,
11010+
PyObject *name)
1101211011
{
11013-
PyInterpreterState *interp = _PyInterpreterState_GET();
11014-
11015-
/* XXX Maybe this could be optimized more -- but is it worth it? */
11016-
void **res, **ptr;
11017-
res = NULL;
11012+
#define ptrs _Py_INTERP_CACHED_OBJECT(interp, type_slots_ptrs)
1101811013

11014+
int rc = 0;
1101911015
PyObject *cache = Py_XNewRef(interp->cached_objects.slotdefs_cache);
1102011016
if (cache) {
11021-
int rc = 0;
11022-
// Py_BEGIN_CRITICAL_SECTION(cache);
11023-
1102411017
PyObject* bytes=NULL;
1102511018
rc = PyDict_GetItemRef(cache, name, &bytes);
1102611019
if (rc > 0) {
@@ -11033,53 +11026,61 @@ resolve_slotdups(PyTypeObject *type, PyObject *name)
1103311026
assert(n >= 0);
1103411027
assert(n < MAX_EQUIV);
1103511028

11036-
uint8_t i;
11037-
for(i = 0; i < n; i++) {
11029+
pytype_slotdef **pp = ptrs;
11030+
for(uint8_t i = 0; i < n; i++) {
1103811031
uint8_t idx = data[i + 1];
1103911032
assert (idx < Py_ARRAY_LENGTH(slotdefs));
1104011033

11041-
pytype_slotdef *x = &slotdefs[idx];
11042-
ptr = slotptr(type, x->offset);
11043-
if (ptr == NULL || *ptr == NULL) {
11044-
continue;
11045-
}
11046-
if (res != NULL) {
11047-
res = NULL;
11048-
break;
11049-
}
11050-
res = ptr;
11034+
*pp++ = &slotdefs[idx];
1105111035
}
11036+
*pp = NULL;
11037+
1105211038
Py_DECREF(bytes);
1105311039
} else if (rc < 0) {
1105411040
PyErr_Clear();
1105511041
}
1105611042

1105711043
Py_DECREF(cache);
11058-
// Py_END_CRITICAL_SECTION();
11059-
if (rc > 0) {
11060-
return res;
11061-
}
1106211044
}
1106311045

11046+
return rc;
11047+
11048+
#undef ptrs
11049+
}
11050+
11051+
/* Return a slot pointer for a given name, but ONLY if the attribute has
11052+
exactly one slot function. The name must be an interned string. */
11053+
static void **
11054+
resolve_slotdups(PyTypeObject *type, PyObject *name)
11055+
{
11056+
/* XXX Maybe this could be optimized more -- but is it worth it? */
11057+
1106411058
/* pname and ptrs act as a little cache */
11059+
PyInterpreterState *interp = _PyInterpreterState_GET();
1106511060
#define pname _Py_INTERP_CACHED_OBJECT(interp, type_slots_pname)
1106611061
#define ptrs _Py_INTERP_CACHED_OBJECT(interp, type_slots_ptrs)
1106711062
pytype_slotdef *p, **pp;
11063+
void **res, **ptr;
1106811064

1106911065
if (pname != name) {
1107011066
/* Collect all slotdefs that match name into ptrs. */
1107111067
pname = name;
11072-
pp = ptrs;
11073-
for (p = slotdefs; p->name_strobj; p++) {
11074-
if (p->name_strobj == name)
11075-
*pp++ = p;
11068+
11069+
int rc = fill_type_slots_cache_from_slotdefs_cache(interp, name);
11070+
if (rc <= 0) {
11071+
pp = ptrs;
11072+
for (p = slotdefs; p->name_strobj; p++) {
11073+
if (p->name_strobj == name)
11074+
*pp++ = p;
11075+
}
11076+
*pp = NULL;
1107611077
}
11077-
*pp = NULL;
1107811078
}
1107911079

1108011080
/* Look in all slots of the type matching the name. If exactly one of these
1108111081
has a filled-in slot, return a pointer to that slot.
1108211082
Otherwise, return NULL. */
11083+
res = NULL;
1108311084
for (pp = ptrs; *pp; pp++) {
1108411085
ptr = slotptr(type, (*pp)->offset);
1108511086
if (ptr == NULL || *ptr == NULL)

0 commit comments

Comments
 (0)