Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
optimize _CALL_BUILTIN_FAST_WITH_KEYWORDS
  • Loading branch information
Sacul0457 committed Apr 11, 2026
commit 60aaed74368f7735c989d6f650416ec4fce08419
2 changes: 1 addition & 1 deletion Include/internal/pycore_ceval.h
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ _Py_BuiltinCallFast_StackRef(
int total_args);

PyAPI_FUNC(PyObject *)
_Py_BuiltinCallFastWithKeywords_StackRefSteal(
_Py_BuiltinCallFastWithKeywords_StackRef(
_PyStackRef callable,
_PyStackRef *arguments,
int total_args);
Expand Down
4 changes: 2 additions & 2 deletions Include/internal/pycore_opcode_metadata.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Include/internal/pycore_uop_ids.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions Include/internal/pycore_uop_metadata.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions Lib/test/test_capi/test_opt.py
Original file line number Diff line number Diff line change
Expand Up @@ -2746,7 +2746,12 @@ def test_call_builtin_fast_with_keywords(self):
def testfunc(n):
x = 0
for _ in range(n):
# _CALL_BUILTIN_FAST_WITH_KEYWORDS: 1 _POP_TOP_NOP, 1 POP_TOP
# _LIST_EXTEND: 1 _POP_TOP_NOP,
y = sorted([3, 1, 2])

# _BINARY_OP_SUBSCR_LIST_INT: 2 _POP_TOP_NOP
# _BINARY_OP_ADD_INT: 1 _POP_TOP_NOP
x += y[0]
return x

Expand All @@ -2756,6 +2761,8 @@ def testfunc(n):
uops = get_opnames(ex)
self.assertIn("_CALL_BUILTIN_FAST_WITH_KEYWORDS", uops)
self.assertNotIn("_GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS", uops)
self.assertGreaterEqual(count_ops(ex, "_POP_TOP_NOP"), 5)
self.assertGreaterEqual(count_ops(ex, "_POP_TOP"), 3)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this, we probably will have more in the future when we optimize more ops.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh alr, gimme a sec

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed :)


def test_call_method_descriptor_o(self):
def testfunc(n):
Expand Down
30 changes: 23 additions & 7 deletions Modules/_testinternalcapi/test_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 10 additions & 7 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -4689,7 +4689,7 @@ dummy_func(
EXIT_IF(PyCFunction_GET_FLAGS(callable_o) != (METH_FASTCALL | METH_KEYWORDS));
}

op(_CALL_BUILTIN_FAST_WITH_KEYWORDS, (callable, self_or_null, args[oparg] -- res)) {
op(_CALL_BUILTIN_FAST_WITH_KEYWORDS, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) {
/* Builtin METH_FASTCALL | METH_KEYWORDS functions */
int total_args = oparg;
_PyStackRef *arguments = args;
Expand All @@ -4698,12 +4698,13 @@ dummy_func(
total_args++;
}
STAT_INC(CALL, hit);
PyObject *res_o = _Py_BuiltinCallFastWithKeywords_StackRefSteal(callable, arguments, total_args);
DEAD(args);
DEAD(self_or_null);
DEAD(callable);
ERROR_IF(res_o == NULL);
res = PyStackRef_FromPyObjectSteal(res_o);
PyObject *res_o = _Py_BuiltinCallFastWithKeywords_StackRef(callable, arguments, total_args);
if (res_o == NULL) {
ERROR_NO_POP();
}
_PyStackRef temp = callable;
callable = PyStackRef_FromPyObjectSteal(res_o);
PyStackRef_CLOSE(temp);
}

macro(CALL_BUILTIN_FAST_WITH_KEYWORDS) =
Expand All @@ -4712,6 +4713,8 @@ dummy_func(
unused/2 +
_GUARD_CALLABLE_BUILTIN_FAST_WITH_KEYWORDS +
_CALL_BUILTIN_FAST_WITH_KEYWORDS +
_POP_TOP_OPARG +
POP_TOP +
_CHECK_PERIODIC_AT_END;

macro(CALL_LEN) =
Expand Down
14 changes: 2 additions & 12 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -832,32 +832,22 @@ _Py_BuiltinCallFast_StackRef(
}

PyObject *
_Py_BuiltinCallFastWithKeywords_StackRefSteal(
_Py_BuiltinCallFastWithKeywords_StackRef(
_PyStackRef callable,
_PyStackRef *arguments,
int total_args)
{
PyObject *res;
STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o);
if (CONVERSION_FAILED(args_o)) {
res = NULL;
goto cleanup;
return NULL;
}
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
PyCFunctionFastWithKeywords cfunc =
_PyCFunctionFastWithKeywords_CAST(PyCFunction_GET_FUNCTION(callable_o));
res = cfunc(PyCFunction_GET_SELF(callable_o), args_o, total_args, NULL);
STACKREFS_TO_PYOBJECTS_CLEANUP(args_o);
assert((res != NULL) ^ (PyErr_Occurred() != NULL));
cleanup:
// arguments is a pointer into the GC visible stack,
// so we must NULL out values as we clear them.
for (int i = total_args-1; i >= 0; i--) {
_PyStackRef tmp = arguments[i];
arguments[i] = PyStackRef_NULL;
PyStackRef_CLOSE(tmp);
}
PyStackRef_CLOSE(callable);
return res;
}

Expand Down
20 changes: 10 additions & 10 deletions Python/executor_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 23 additions & 7 deletions Python/generated_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Python/optimizer_bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -1325,6 +1325,10 @@ dummy_func(void) {
}
}

op(_CALL_BUILTIN_FAST_WITH_KEYWORDS, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) {
callable = sym_new_not_null(ctx);
}

op(_CALL_BUILTIN_O, (callable, self_or_null, args[oparg] -- res, c, s)) {
res = sym_new_not_null(ctx);
c = callable;
Expand Down
10 changes: 4 additions & 6 deletions Python/optimizer_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.