Skip to content

Commit 212bc3c

Browse files
fix scaling of enums
1 parent 36f15ba commit 212bc3c

2 files changed

Lines changed: 35 additions & 6 deletions

File tree

Python/specialize.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,15 +1201,23 @@ specialize_class_load_attr(PyObject *owner, _Py_CODEUNIT *instr,
12011201
}
12021202
}
12031203
switch (kind) {
1204-
case METHOD:
1205-
case NON_DESCRIPTOR:
1206-
#ifdef Py_GIL_DISABLED
1207-
if (!_PyObject_HasDeferredRefcount(descr)) {
1208-
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_DESCR_NOT_DEFERRED);
1204+
case MUTABLE:
1205+
// special case for enums which has Py_TYPE(descr) == cls
1206+
// so guarding on type_version is sufficient
1207+
if (Py_TYPE(descr) != cls) {
1208+
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_MUTABLE_CLASS);
12091209
Py_XDECREF(descr);
12101210
return -1;
12111211
}
1212-
#endif
1212+
if (Py_TYPE(descr)->tp_descr_get || Py_TYPE(descr)->tp_descr_set) {
1213+
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_MUTABLE_CLASS);
1214+
Py_XDECREF(descr);
1215+
return -1;
1216+
}
1217+
_Py_FALLTHROUGH;
1218+
case METHOD:
1219+
case NON_DESCRIPTOR:
1220+
PyUnstable_Object_EnableDeferredRefcount(descr);
12131221
write_u32(cache->type_version, tp_version);
12141222
write_ptr(cache->descr, descr);
12151223
if (metaclass_check) {

Tools/ftscalingbench/ftscalingbench.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,27 @@ def setattr_non_interned():
295295
setattr(obj, f"{prefix}_c", None)
296296

297297

298+
from enum import Enum
299+
class MyEnum(Enum):
300+
X = 1
301+
Y = 2
302+
Z = 3
303+
304+
@register_benchmark
305+
def enum_attr():
306+
for _ in range(1000 * WORK_SCALE):
307+
MyEnum.X
308+
MyEnum.Y
309+
MyEnum.Z
310+
311+
@register_benchmark
312+
def enum_value():
313+
for _ in range(1000 * WORK_SCALE):
314+
MyEnum.X.value
315+
MyEnum.Y.value
316+
MyEnum.Z.value
317+
318+
298319
def bench_one_thread(func):
299320
t0 = time.perf_counter_ns()
300321
func()

0 commit comments

Comments
 (0)