mirror of
https://github.com/python/cpython.git
synced 2025-11-24 20:30:18 +00:00
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__`.
This commit is contained in:
parent
8dfa840773
commit
da53660f35
11 changed files with 247 additions and 207 deletions
|
|
@ -3417,28 +3417,33 @@ dummy_func(
|
|||
_FOR_ITER_GEN_FRAME +
|
||||
_PUSH_FRAME;
|
||||
|
||||
inst(LOAD_SPECIAL, (owner -- attr, self_or_null)) {
|
||||
assert(oparg <= SPECIAL_MAX);
|
||||
PyObject *owner_o = PyStackRef_AsPyObjectSteal(owner);
|
||||
op(_INSERT_NULL, (self -- method_and_self[2])) {
|
||||
method_and_self[1] = self;
|
||||
method_and_self[0] = PyStackRef_NULL;
|
||||
DEAD(self);
|
||||
}
|
||||
|
||||
op(_LOAD_SPECIAL, (method_and_self[2] -- method_and_self[2])) {
|
||||
PyObject *name = _Py_SpecialMethods[oparg].name;
|
||||
PyObject *self_or_null_o;
|
||||
PyObject *attr_o = _PyObject_LookupSpecialMethod(owner_o, name, &self_or_null_o);
|
||||
if (attr_o == NULL) {
|
||||
if (!_PyErr_Occurred(tstate)) {
|
||||
const char *errfmt = _PyEval_SpecialMethodCanSuggest(owner_o, oparg)
|
||||
int err = _PyObject_LookupSpecialMethod(name, method_and_self);
|
||||
if (err <= 0) {
|
||||
if (err == 0) {
|
||||
PyObject *owner = PyStackRef_AsPyObjectBorrow(method_and_self[1]);
|
||||
const char *errfmt = _PyEval_SpecialMethodCanSuggest(owner, oparg)
|
||||
? _Py_SpecialMethods[oparg].error_suggestion
|
||||
: _Py_SpecialMethods[oparg].error;
|
||||
assert(!_PyErr_Occurred(tstate));
|
||||
assert(errfmt != NULL);
|
||||
_PyErr_Format(tstate, PyExc_TypeError, errfmt, owner_o);
|
||||
_PyErr_Format(tstate, PyExc_TypeError, errfmt, owner);
|
||||
}
|
||||
ERROR_IF(true, error);
|
||||
ERROR_NO_POP();
|
||||
}
|
||||
attr = PyStackRef_FromPyObjectSteal(attr_o);
|
||||
self_or_null = self_or_null_o == NULL ?
|
||||
PyStackRef_NULL : PyStackRef_FromPyObjectSteal(self_or_null_o);
|
||||
}
|
||||
|
||||
macro(LOAD_SPECIAL) =
|
||||
_INSERT_NULL +
|
||||
_LOAD_SPECIAL;
|
||||
|
||||
inst(WITH_EXCEPT_START, (exit_func, exit_self, lasti, unused, val -- exit_func, exit_self, lasti, unused, val, res)) {
|
||||
/* At the top of the stack are 4 values:
|
||||
- val: TOP = exc_info()
|
||||
|
|
|
|||
45
Python/executor_cases.c.h
generated
45
Python/executor_cases.c.h
generated
|
|
@ -4407,43 +4407,42 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _LOAD_SPECIAL: {
|
||||
_PyStackRef owner;
|
||||
_PyStackRef attr;
|
||||
_PyStackRef self_or_null;
|
||||
oparg = CURRENT_OPARG();
|
||||
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;
|
||||
case _INSERT_NULL: {
|
||||
_PyStackRef self;
|
||||
_PyStackRef *method_and_self;
|
||||
self = stack_pointer[-1];
|
||||
method_and_self = &stack_pointer[-1];
|
||||
method_and_self[1] = self;
|
||||
method_and_self[0] = PyStackRef_NULL;
|
||||
stack_pointer += 1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
break;
|
||||
}
|
||||
|
||||
case _LOAD_SPECIAL: {
|
||||
_PyStackRef *method_and_self;
|
||||
oparg = CURRENT_OPARG();
|
||||
method_and_self = &stack_pointer[-2];
|
||||
PyObject *name = _Py_SpecialMethods[oparg].name;
|
||||
_PyFrame_SetStackPointer(frame, stack_pointer);
|
||||
PyObject *attr_o = _PyObject_LookupSpecialMethod(owner_o, name, &self_or_null_o);
|
||||
int err = _PyObject_LookupSpecialMethod(name, method_and_self);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
if (attr_o == NULL) {
|
||||
if (!_PyErr_Occurred(tstate)) {
|
||||
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_o, oparg)
|
||||
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_o);
|
||||
_PyErr_Format(tstate, PyExc_TypeError, errfmt, owner);
|
||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||
}
|
||||
JUMP_TO_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());
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
68
Python/generated_cases.c.h
generated
68
Python/generated_cases.c.h
generated
|
|
@ -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);
|
||||
}
|
||||
JUMP_TO_LABEL(error);
|
||||
_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);
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -897,9 +897,14 @@ dummy_func(void) {
|
|||
}
|
||||
}
|
||||
|
||||
op(_LOAD_SPECIAL, (owner -- attr, self_or_null)) {
|
||||
attr = sym_new_not_null(ctx);
|
||||
self_or_null = sym_new_unknown(ctx);
|
||||
op(_INSERT_NULL, (self -- method_and_self[2])) {
|
||||
method_and_self[0] = sym_new_null(ctx);
|
||||
method_and_self[1] = self;
|
||||
}
|
||||
|
||||
op(_LOAD_SPECIAL, (method_and_self[2] -- method_and_self[2])) {
|
||||
method_and_self[0] = sym_new_not_null(ctx);
|
||||
method_and_self[1] = sym_new_unknown(ctx);
|
||||
}
|
||||
|
||||
op(_JUMP_TO_TOP, (--)) {
|
||||
|
|
|
|||
22
Python/optimizer_cases.c.h
generated
22
Python/optimizer_cases.c.h
generated
|
|
@ -1553,18 +1553,26 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _LOAD_SPECIAL: {
|
||||
JitOptSymbol *attr;
|
||||
JitOptSymbol *self_or_null;
|
||||
attr = sym_new_not_null(ctx);
|
||||
self_or_null = sym_new_unknown(ctx);
|
||||
stack_pointer[-1] = attr;
|
||||
stack_pointer[0] = self_or_null;
|
||||
case _INSERT_NULL: {
|
||||
JitOptSymbol *self;
|
||||
JitOptSymbol **method_and_self;
|
||||
self = stack_pointer[-1];
|
||||
method_and_self = &stack_pointer[-1];
|
||||
method_and_self[0] = sym_new_null(ctx);
|
||||
method_and_self[1] = self;
|
||||
stack_pointer += 1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
break;
|
||||
}
|
||||
|
||||
case _LOAD_SPECIAL: {
|
||||
JitOptSymbol **method_and_self;
|
||||
method_and_self = &stack_pointer[-2];
|
||||
method_and_self[0] = sym_new_not_null(ctx);
|
||||
method_and_self[1] = sym_new_unknown(ctx);
|
||||
break;
|
||||
}
|
||||
|
||||
case _WITH_EXCEPT_START: {
|
||||
JitOptSymbol *res;
|
||||
res = sym_new_not_null(ctx);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue