summaryrefslogtreecommitdiffstats
path: root/Python/generated_cases.c.h
diff options
context:
space:
mode:
authorSam Gross <colesbury@gmail.com>2025-04-21 19:54:25 (GMT)
committerGitHub <noreply@github.com>2025-04-21 19:54:25 (GMT)
commitda53660f35db2dfb1e6181e603468dfe5758f3b8 (patch)
treecf641cfff0634552f7d84ae9b246fa17d5e04166 /Python/generated_cases.c.h
parent8dfa840773d1d6bae1bf6e0dfa07618ea10c9d71 (diff)
downloadcpython-da53660f35db2dfb1e6181e603468dfe5758f3b8.zip
cpython-da53660f35db2dfb1e6181e603468dfe5758f3b8.tar.gz
cpython-da53660f35db2dfb1e6181e603468dfe5758f3b8.tar.bz2
gh-131586: Avoid refcount contention in context managers (gh-131851)
This avoid reference count contention in the free threading build when calling special methods like `__enter__` and `__exit__`.
Diffstat (limited to 'Python/generated_cases.c.h')
-rw-r--r--Python/generated_cases.c.h66
1 files changed, 33 insertions, 33 deletions
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 911f5ae..18785c7 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -9342,41 +9342,41 @@
frame->instr_ptr = next_instr;
next_instr += 1;
INSTRUCTION_STATS(LOAD_SPECIAL);
- _PyStackRef owner;
- _PyStackRef attr;
- _PyStackRef self_or_null;
- owner = stack_pointer[-1];
- assert(oparg <= SPECIAL_MAX);
- PyObject *owner_o = PyStackRef_AsPyObjectSteal(owner);
- PyObject *name = _Py_SpecialMethods[oparg].name;
- PyObject *self_or_null_o;
- stack_pointer += -1;
- assert(WITHIN_STACK_BOUNDS());
- _PyFrame_SetStackPointer(frame, stack_pointer);
- PyObject *attr_o = _PyObject_LookupSpecialMethod(owner_o, name, &self_or_null_o);
- stack_pointer = _PyFrame_GetStackPointer(frame);
- if (attr_o == NULL) {
- if (!_PyErr_Occurred(tstate)) {
- _PyFrame_SetStackPointer(frame, stack_pointer);
- const char *errfmt = _PyEval_SpecialMethodCanSuggest(owner_o, oparg)
- ? _Py_SpecialMethods[oparg].error_suggestion
- : _Py_SpecialMethods[oparg].error;
- stack_pointer = _PyFrame_GetStackPointer(frame);
- assert(!_PyErr_Occurred(tstate));
- assert(errfmt != NULL);
- _PyFrame_SetStackPointer(frame, stack_pointer);
- _PyErr_Format(tstate, PyExc_TypeError, errfmt, owner_o);
- stack_pointer = _PyFrame_GetStackPointer(frame);
+ _PyStackRef self;
+ _PyStackRef *method_and_self;
+ // _INSERT_NULL
+ {
+ self = stack_pointer[-1];
+ method_and_self = &stack_pointer[-1];
+ method_and_self[1] = self;
+ method_and_self[0] = PyStackRef_NULL;
+ }
+ // _LOAD_SPECIAL
+ {
+ method_and_self = &stack_pointer[-1];
+ PyObject *name = _Py_SpecialMethods[oparg].name;
+ stack_pointer += 1;
+ assert(WITHIN_STACK_BOUNDS());
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ int err = _PyObject_LookupSpecialMethod(name, method_and_self);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ if (err <= 0) {
+ if (err == 0) {
+ PyObject *owner = PyStackRef_AsPyObjectBorrow(method_and_self[1]);
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ const char *errfmt = _PyEval_SpecialMethodCanSuggest(owner, oparg)
+ ? _Py_SpecialMethods[oparg].error_suggestion
+ : _Py_SpecialMethods[oparg].error;
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ assert(!_PyErr_Occurred(tstate));
+ assert(errfmt != NULL);
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ _PyErr_Format(tstate, PyExc_TypeError, errfmt, owner);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ }
+ JUMP_TO_LABEL(error);
}
- JUMP_TO_LABEL(error);
}
- attr = PyStackRef_FromPyObjectSteal(attr_o);
- self_or_null = self_or_null_o == NULL ?
- PyStackRef_NULL : PyStackRef_FromPyObjectSteal(self_or_null_o);
- stack_pointer[0] = attr;
- stack_pointer[1] = self_or_null;
- stack_pointer += 2;
- assert(WITHIN_STACK_BOUNDS());
DISPATCH();
}