You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
_Py_CallBuiltinClass_StackRefSteal does not declare PY_VECTORCALL_ARGUMENTS_OFFSET #143361
The call to tp_vectorcall does not declare PY_VECTORCALL_ARGUMENTS_OFFSET despite STACKREFS_TO_PYOBJECTS (via _PyObjectArray_FromStackRefArray) always allocating an args_o that has an extra scratch space at position -1.
Strictly speaking, this isn't incorrect. But it can force the caller to make a redundant copy of the arguments, which is inefficient. Best practice to allocate the extra entry and then communicate its presence to the vector-callee.
This inefficiency is not restricted to Python-internal types. It also affects custom heap types that are themselves vector-callable. In this case, Python's adaptive optimizing interpreter replaces CALL_NON_PY_GENERAL with CALL_BUILTIN_CLASS that then goes through this code path.
I don't think 3.14 is affected by this right? It should be only the main branch?
Yeah this function doesn't exist at all in 3.14 or earlier. Only in the main branch. I expect the change would be pretty trivial, changing the flags passed to vectorcall.
Sorry for the double comment, but was intrigued and taking a look at this with some findings. I was able to verify a fix with LLDB.
Before fix: LLDB shows nargsf = 1.
With fix: Adding total_args | PY_VECTORCALL_ARGUMENTS_OFFSET results in nargsf = 0x8000000000000001, which shows available offset to the callee and avoids redundant allocation/copy.
Also did a quick perf test with the fix locally with time taken for 5M allocations at 1.6193s pre-fix, and 1.5560s post-fix, about a 3.9% speedup, which seems pretty strong.
I have a patch ready for this and would be happy to submit a PR if this is a direction the core contribs want to take.
I realized I should not have looked at the master branch. That same inefficiency is also present in the latest CPython 3.14. In this case, it is in bytecodes.c
Sure enough @wjakob, not the same function name but identical logic. @Fidget-Spinner would you recommend I add a patch for bytecodes.c to my PR, or create a second PR with the additional bytecodes fix?
@a12k we can only backport if it was a prior bug/regression. Eg if in 3.13 we set the flag and in 3.14 we didnt, then backport is fine. Otherwise we cant backport perf fixes to maintenance branches, or I would be backporting the JIT 😀
Activity
Fidget-Spinner commentedon Jan 2, 2026
I don't think 3.14 is affected by this right? It should be only the main branch?
a12k commentedon Jan 2, 2026
Yeah this function doesn't exist at all in 3.14 or earlier. Only in the main branch. I expect the change would be pretty trivial, changing the flags passed to vectorcall.
a12k commentedon Jan 2, 2026
Sorry for the double comment, but was intrigued and taking a look at this with some findings. I was able to verify a fix with LLDB.
Before fix: LLDB shows nargsf = 1.
With fix: Adding
total_args | PY_VECTORCALL_ARGUMENTS_OFFSETresults in nargsf = 0x8000000000000001, which shows available offset to the callee and avoids redundant allocation/copy.Also did a quick perf test with the fix locally with time taken for 5M allocations at 1.6193s pre-fix, and 1.5560s post-fix, about a 3.9% speedup, which seems pretty strong.
I have a patch ready for this and would be happy to submit a PR if this is a direction the core contribs want to take.
Fidget-Spinner commentedon Jan 2, 2026
Yes please go ahead, I will merge this.
a12k commentedon Jan 2, 2026
@Fidget-Spinner made the change in a PR above!
wjakob commentedon Jan 2, 2026
@Fidget-Spinner @a12k
I realized I should not have looked at the master branch. That same inefficiency is also present in the latest CPython 3.14. In this case, it is in
bytecodes.ca12k commentedon Jan 2, 2026
Sure enough @wjakob, not the same function name but identical logic. @Fidget-Spinner would you recommend I add a patch for bytecodes.c to my PR, or create a second PR with the additional bytecodes fix?
Fidget-Spinner commentedon Jan 2, 2026
@a12k we can only backport if it was a prior bug/regression. Eg if in 3.13 we set the flag and in 3.14 we didnt, then backport is fine. Otherwise we cant backport perf fixes to maintenance branches, or I would be backporting the JIT 😀
gh-143361: Pass PY_VECTORCALL_ARGUMENTS_OFFSET in _Py_CallBuiltinClas…
Fidget-Spinner commentedon Jan 2, 2026
Does anyone know if we need to backport (ie, this was a regression compared to 3.13?) If not, I'm closing this issue as done.
chris-eibl commentedon Jan 3, 2026
_CALL_BUILTIN_CLASSon latest 3.13cpython/Python/bytecodes.c
Line 3484 in 16d2e97
doesn't use
PY_VECTORCALL_ARGUMENTS_OFFSET, so unfortunately we cannot backport.pythongh-143361: Pass PY_VECTORCALL_ARGUMENTS_OFFSET in _Py_CallBuilt…
Type freezing via ``nb::class_<..>::freeze()``