mirror of
https://github.com/python/cpython.git
synced 2026-10-28 10:25:05 +08:00
gh-155141: Improve stack-use estimation for keyword calls (#155785)
This commit is contained in:
1 parent
50ed1ec6ca
commit
e13ecaeca2
3 files changed
+32
-2
No files matched your search
@@ -63,6 +63,30 @@ class TestSpecifics(unittest.TestCase):
|
||||
self.assertRaises(SyntaxError, exec, 'def f(a = 0, a = 1): pass')
|
||||
self.assertRaises(SyntaxError, exec, 'def f(a): global a; a = 1')
|
||||
|
||||
def test_call_opcode_stack_use_limit(self):
|
||||
def get_call_opcode(positional_count, keyword_count):
|
||||
args = ["0"] * positional_count
|
||||
args.extend(f"a{i}=0" for i in range(keyword_count))
|
||||
code = compile(f"f({', '.join(args)})", "<test>", "exec")
|
||||
return next(
|
||||
instr.opname for instr in dis.get_instructions(code)
|
||||
if instr.opname.startswith("CALL")
|
||||
)
|
||||
|
||||
for positional_count, keyword_count, expected_opcode in [
|
||||
(0, 16, "CALL_KW"),
|
||||
(15, 14, "CALL_KW"),
|
||||
(15, 15, "CALL_FUNCTION_EX"),
|
||||
]:
|
||||
with self.subTest(
|
||||
positional_count=positional_count,
|
||||
keyword_count=keyword_count,
|
||||
):
|
||||
self.assertEqual(
|
||||
get_call_opcode(positional_count, keyword_count),
|
||||
expected_opcode,
|
||||
)
|
||||
|
||||
def test_syntax_error(self):
|
||||
self.assertRaises(SyntaxError, compile, "1+*3", "filename", "exec")
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
Compile pure-keyword calls with 16 to 29 keyword arguments using the faster
|
||||
``CALL_KW`` instruction. This includes common cases such as dataclass
|
||||
constructors with many fields.
|
||||
+5
-2
@@ -87,6 +87,9 @@ typedef _PyCompile_FBlockInfo fblockinfo;
|
||||
|
||||
#define LOC(x) SRC_LOCATION_FROM_AST(x)
|
||||
|
||||
#define CALL_STACK_USE(nargs, nkwds) \
|
||||
((nargs) + (nkwds) + ((nkwds) != 0))
|
||||
|
||||
#define NEW_JUMP_TARGET_LABEL(C, NAME) \
|
||||
jump_target_label NAME = _PyInstructionSequence_NewLabel(INSTR_SEQUENCE(C)); \
|
||||
if (!IS_JUMP_TARGET_LABEL(NAME)) { \
|
||||
@@ -4147,7 +4150,7 @@ maybe_optimize_method_call(compiler *c, expr_ty e)
|
||||
/* Check that there aren't too many arguments */
|
||||
argsl = asdl_seq_LEN(args);
|
||||
kwdsl = asdl_seq_LEN(kwds);
|
||||
if (argsl + kwdsl + (kwdsl != 0) >= _PY_STACK_USE_GUIDELINE) {
|
||||
if (CALL_STACK_USE(argsl, kwdsl) >= _PY_STACK_USE_GUIDELINE) {
|
||||
return 0;
|
||||
}
|
||||
/* Check that there are no *varargs types of arguments. */
|
||||
@@ -4440,7 +4443,7 @@ codegen_call_helper_impl(compiler *c, location loc,
|
||||
nelts = asdl_seq_LEN(args);
|
||||
nkwelts = asdl_seq_LEN(keywords);
|
||||
|
||||
if (nelts + nkwelts*2 > _PY_STACK_USE_GUIDELINE) {
|
||||
if (CALL_STACK_USE(nelts, nkwelts) > _PY_STACK_USE_GUIDELINE) {
|
||||
goto ex_call;
|
||||
}
|
||||
for (i = 0; i < nelts; i++) {
|
||||
|
||||
Reference in new issue
Block a user