summaryrefslogtreecommitdiffstats
path: root/Python/generated_cases.c.h
diff options
context:
space:
mode:
authorSam Gross <colesbury@gmail.com>2024-09-24 20:08:18 (GMT)
committerGitHub <noreply@github.com>2024-09-24 20:08:18 (GMT)
commitf4997bb3ac961d6aaf07ce650cd074e28ce6ccd0 (patch)
tree6c82b0fadd282e74c8f81de4a3966666fd210196 /Python/generated_cases.c.h
parentd3c76dff444046504754a437dceebc9a9c87ef18 (diff)
downloadcpython-f4997bb3ac961d6aaf07ce650cd074e28ce6ccd0.zip
cpython-f4997bb3ac961d6aaf07ce650cd074e28ce6ccd0.tar.gz
cpython-f4997bb3ac961d6aaf07ce650cd074e28ce6ccd0.tar.bz2
gh-123923: Defer refcounting for `f_funcobj` in `_PyInterpreterFrame` (#124026)
Use a `_PyStackRef` and defer the reference to `f_funcobj` when possible. This avoids some reference count contention in the common case of executing the same code object from multiple threads concurrently in the free-threaded build.
Diffstat (limited to 'Python/generated_cases.c.h')
-rw-r--r--Python/generated_cases.c.h52
1 files changed, 23 insertions, 29 deletions
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 6d902e2..58792a2 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -506,7 +506,6 @@
assert(code->co_argcount == 2);
DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), BINARY_SUBSCR);
STAT_INC(BINARY_SUBSCR, hit);
- Py_INCREF(getitem);
}
// _BINARY_SUBSCR_INIT_CALL
sub = stack_pointer[-1];
@@ -514,7 +513,7 @@
PyTypeObject *tp = Py_TYPE(PyStackRef_AsPyObjectBorrow(container));
PyHeapTypeObject *ht = (PyHeapTypeObject *)tp;
PyObject *getitem = ht->_spec_cache.getitem;
- new_frame = _PyFrame_PushUnchecked(tstate, (PyFunctionObject *)getitem, 2, frame);
+ new_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(getitem), 2, frame);
stack_pointer += -2;
assert(WITHIN_STACK_BOUNDS());
new_frame->localsplus[0] = container;
@@ -892,7 +891,7 @@
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
_PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit(
- tstate, (PyFunctionObject *)PyStackRef_AsPyObjectSteal(callable), locals,
+ tstate, callable, locals,
args, total_args, NULL, frame
);
// Manipulate stack directly since we leave using DISPATCH_INLINED().
@@ -1021,10 +1020,9 @@
assert(_PyCode_CODE(_PyFrame_GetCode(shim))[0].op.code == EXIT_INIT_CHECK);
/* Push self onto stack of shim */
shim->localsplus[0] = PyStackRef_DUP(self);
- PyFunctionObject *init_func = (PyFunctionObject *)PyStackRef_AsPyObjectSteal(init);
args[-1] = self;
init_frame = _PyEvalFramePushAndInit(
- tstate, init_func, NULL, args-1, oparg+1, NULL, shim);
+ tstate, init, NULL, args-1, oparg+1, NULL, shim);
stack_pointer += -2 - oparg;
assert(WITHIN_STACK_BOUNDS());
if (init_frame == NULL) {
@@ -1119,11 +1117,9 @@
// _INIT_CALL_PY_EXACT_ARGS
args = &stack_pointer[-oparg];
{
- PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
int has_self = !PyStackRef_IsNull(self_or_null[0]);
STAT_INC(CALL, hit);
- PyFunctionObject *func = (PyFunctionObject *)callable_o;
- new_frame = _PyFrame_PushUnchecked(tstate, func, oparg + has_self, frame);
+ new_frame = _PyFrame_PushUnchecked(tstate, callable, oparg + has_self, frame);
_PyStackRef *first_non_self_local = new_frame->localsplus + has_self;
new_frame->localsplus[0] = self_or_null[0];
for (int i = 0; i < oparg; i++) {
@@ -1216,7 +1212,7 @@
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
new_frame = _PyEvalFramePushAndInit(
- tstate, (PyFunctionObject *)PyStackRef_AsPyObjectSteal(callable), locals,
+ tstate, callable, locals,
args, total_args, NULL, frame
);
// The frame has stolen all the arguments from the stack,
@@ -1616,8 +1612,8 @@
Py_ssize_t nargs = PyTuple_GET_SIZE(callargs);
int code_flags = ((PyCodeObject *)PyFunction_GET_CODE(func))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(func));
- _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit_Ex(tstate,
- (PyFunctionObject *)PyStackRef_AsPyObjectSteal(func_st), locals,
+ _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit_Ex(
+ tstate, func_st, locals,
nargs, callargs, kwargs, frame);
// Need to manually shrink the stack since we exit with DISPATCH_INLINED.
STACK_SHRINK(oparg + 3);
@@ -1802,7 +1798,7 @@
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
_PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit(
- tstate, (PyFunctionObject *)PyStackRef_AsPyObjectSteal(callable), locals,
+ tstate, callable, locals,
args, positional_args, kwnames_o, frame
);
PyStackRef_CLOSE(kwnames);
@@ -1936,7 +1932,7 @@
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
new_frame = _PyEvalFramePushAndInit(
- tstate, (PyFunctionObject *)PyStackRef_AsPyObjectSteal(callable), locals,
+ tstate, callable, locals,
args, positional_args, kwnames_o, frame
);
PyStackRef_CLOSE(kwnames);
@@ -2104,7 +2100,7 @@
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
new_frame = _PyEvalFramePushAndInit(
- tstate, (PyFunctionObject *)PyStackRef_AsPyObjectSteal(callable), locals,
+ tstate, callable, locals,
args, positional_args, kwnames_o, frame
);
PyStackRef_CLOSE(kwnames);
@@ -2649,11 +2645,9 @@
// _INIT_CALL_PY_EXACT_ARGS
args = &stack_pointer[-oparg];
{
- PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
int has_self = !PyStackRef_IsNull(self_or_null[0]);
STAT_INC(CALL, hit);
- PyFunctionObject *func = (PyFunctionObject *)callable_o;
- new_frame = _PyFrame_PushUnchecked(tstate, func, oparg + has_self, frame);
+ new_frame = _PyFrame_PushUnchecked(tstate, callable, oparg + has_self, frame);
_PyStackRef *first_non_self_local = new_frame->localsplus + has_self;
new_frame->localsplus[0] = self_or_null[0];
for (int i = 0; i < oparg; i++) {
@@ -2726,7 +2720,7 @@
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
new_frame = _PyEvalFramePushAndInit(
- tstate, (PyFunctionObject *)PyStackRef_AsPyObjectSteal(callable), locals,
+ tstate, callable, locals,
args, total_args, NULL, frame
);
// The frame has stolen all the arguments from the stack,
@@ -3274,8 +3268,9 @@
INSTRUCTION_STATS(COPY_FREE_VARS);
/* Copy closure variables to free variables */
PyCodeObject *co = _PyFrame_GetCode(frame);
- assert(PyFunction_Check(frame->f_funcobj));
- PyObject *closure = ((PyFunctionObject *)frame->f_funcobj)->func_closure;
+ assert(PyStackRef_FunctionCheck(frame->f_funcobj));
+ PyFunctionObject *func = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(frame->f_funcobj);
+ PyObject *closure = func->func_closure;
assert(oparg == co->co_nfreevars);
int offset = co->co_nlocalsplus - oparg;
for (int i = 0; i < oparg; ++i) {
@@ -4102,7 +4097,7 @@
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
_PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit(
- tstate, (PyFunctionObject *)PyStackRef_AsPyObjectSteal(callable), locals,
+ tstate, callable, locals,
args, total_args, NULL, frame
);
// Manipulate stack directly since we leave using DISPATCH_INLINED().
@@ -4997,8 +4992,8 @@
DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), LOAD_ATTR);
STAT_INC(LOAD_ATTR, hit);
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
- Py_INCREF(f);
- _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, f, 2, frame);
+ _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(
+ tstate, PyStackRef_FromPyObjectNew(f), 2, frame);
// Manipulate stack directly because we exit with DISPATCH_INLINED().
STACK_SHRINK(1);
new_frame->localsplus[0] = owner;
@@ -5328,8 +5323,7 @@
DEOPT_IF(code->co_argcount != 1, LOAD_ATTR);
DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), LOAD_ATTR);
STAT_INC(LOAD_ATTR, hit);
- Py_INCREF(fget);
- new_frame = _PyFrame_PushUnchecked(tstate, f, 1, frame);
+ new_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(fget), 1, frame);
new_frame->localsplus[0] = owner;
}
// _SAVE_RETURN_OFFSET
@@ -6504,8 +6498,8 @@
next_instr += 1;
INSTRUCTION_STATS(RETURN_GENERATOR);
_PyStackRef res;
- assert(PyFunction_Check(frame->f_funcobj));
- PyFunctionObject *func = (PyFunctionObject *)frame->f_funcobj;
+ assert(PyStackRef_FunctionCheck(frame->f_funcobj));
+ PyFunctionObject *func = (PyFunctionObject *)PyStackRef_AsPyObjectBorrow(frame->f_funcobj);
PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func);
if (gen == NULL) {
goto error;
@@ -7718,8 +7712,8 @@
Py_ssize_t nargs = PyTuple_GET_SIZE(callargs);
int code_flags = ((PyCodeObject *)PyFunction_GET_CODE(func))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(func));
- _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit_Ex(tstate,
- (PyFunctionObject *)PyStackRef_AsPyObjectSteal(func_st), locals,
+ _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit_Ex(
+ tstate, func_st, locals,
nargs, callargs, kwargs, frame);
// Need to manually shrink the stack since we exit with DISPATCH_INLINED.
STACK_SHRINK(oparg + 3);