summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2024-05-04 11:11:11 (GMT)
committerGitHub <noreply@github.com>2024-05-04 11:11:11 (GMT)
commit1ab6356ebec25f216a0eddbd81225abcb93f2d55 (patch)
tree86b24ff50b131570819da11ae13ddc9a76a9c6d1
parent00da0afa0d98ce1fae67f7258c7f3db2b81a07e7 (diff)
downloadcpython-1ab6356ebec25f216a0eddbd81225abcb93f2d55.zip
cpython-1ab6356ebec25f216a0eddbd81225abcb93f2d55.tar.gz
cpython-1ab6356ebec25f216a0eddbd81225abcb93f2d55.tar.bz2
GH-118095: Use broader specializations of CALL in tier 1, for better tier 2 support of calls. (GH-118322)
* Add CALL_PY_GENERAL, CALL_BOUND_METHOD_GENERAL and call CALL_NON_PY_GENERAL specializations. * Remove CALL_PY_WITH_DEFAULTS specialization * Use CALL_NON_PY_GENERAL in more cases when otherwise failing to specialize
-rw-r--r--Include/internal/pycore_frame.h5
-rw-r--r--Include/internal/pycore_opcode_metadata.h31
-rw-r--r--Include/internal/pycore_uop_ids.h261
-rw-r--r--Include/internal/pycore_uop_metadata.h26
-rw-r--r--Include/opcode_ids.h116
-rw-r--r--Lib/_opcode_metadata.py120
-rw-r--r--Lib/test/test_call.py13
-rw-r--r--Lib/test/test_dis.py2
-rw-r--r--Lib/test/test_dynamic.py3
-rw-r--r--Lib/test/test_glob.py3
-rw-r--r--Python/bytecodes.c141
-rw-r--r--Python/ceval.c8
-rw-r--r--Python/executor_cases.c.h149
-rw-r--r--Python/generated_cases.c.h235
-rw-r--r--Python/opcode_targets.h6
-rw-r--r--Python/optimizer.c1
-rw-r--r--Python/optimizer_bytecodes.c11
-rw-r--r--Python/optimizer_cases.c.h56
-rw-r--r--Python/specialize.c124
19 files changed, 863 insertions, 448 deletions
diff --git a/Include/internal/pycore_frame.h b/Include/internal/pycore_frame.h
index 37ae5ae..e13fdd9 100644
--- a/Include/internal/pycore_frame.h
+++ b/Include/internal/pycore_frame.h
@@ -318,6 +318,11 @@ PyGenObject *_PyFrame_GetGenerator(_PyInterpreterFrame *frame)
return (PyGenObject *)(((char *)frame) - offset_in_gen);
}
+PyAPI_FUNC(_PyInterpreterFrame *)
+_PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func,
+ PyObject *locals, PyObject* const* args,
+ size_t argcount, PyObject *kwnames);
+
#ifdef __cplusplus
}
#endif
diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h
index d10224c..2a237bc 100644
--- a/Include/internal/pycore_opcode_metadata.h
+++ b/Include/internal/pycore_opcode_metadata.h
@@ -95,6 +95,8 @@ int _PyOpcode_num_popped(int opcode, int oparg) {
return 2 + oparg;
case CALL_BOUND_METHOD_EXACT_ARGS:
return 2 + oparg;
+ case CALL_BOUND_METHOD_GENERAL:
+ return 2 + oparg;
case CALL_BUILTIN_CLASS:
return 2 + oparg;
case CALL_BUILTIN_FAST:
@@ -125,9 +127,11 @@ int _PyOpcode_num_popped(int opcode, int oparg) {
return 2 + oparg;
case CALL_METHOD_DESCRIPTOR_O:
return 2 + oparg;
+ case CALL_NON_PY_GENERAL:
+ return 2 + oparg;
case CALL_PY_EXACT_ARGS:
return 2 + oparg;
- case CALL_PY_WITH_DEFAULTS:
+ case CALL_PY_GENERAL:
return 2 + oparg;
case CALL_STR_1:
return 3;
@@ -524,6 +528,8 @@ int _PyOpcode_num_pushed(int opcode, int oparg) {
return 1;
case CALL_BOUND_METHOD_EXACT_ARGS:
return 0;
+ case CALL_BOUND_METHOD_GENERAL:
+ return 0;
case CALL_BUILTIN_CLASS:
return 1;
case CALL_BUILTIN_FAST:
@@ -554,10 +560,12 @@ int _PyOpcode_num_pushed(int opcode, int oparg) {
return 1;
case CALL_METHOD_DESCRIPTOR_O:
return 1;
+ case CALL_NON_PY_GENERAL:
+ return 1;
case CALL_PY_EXACT_ARGS:
return 0;
- case CALL_PY_WITH_DEFAULTS:
- return 1;
+ case CALL_PY_GENERAL:
+ return 0;
case CALL_STR_1:
return 1;
case CALL_TUPLE_1:
@@ -985,6 +993,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[268] = {
[CALL] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
[CALL_ALLOC_AND_ENTER_INIT] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
[CALL_BOUND_METHOD_EXACT_ARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG },
+ [CALL_BOUND_METHOD_GENERAL] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
[CALL_BUILTIN_CLASS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[CALL_BUILTIN_FAST] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[CALL_BUILTIN_FAST_WITH_KEYWORDS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
@@ -1000,8 +1009,9 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[268] = {
[CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[CALL_METHOD_DESCRIPTOR_NOARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[CALL_METHOD_DESCRIPTOR_O] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
+ [CALL_NON_PY_GENERAL] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[CALL_PY_EXACT_ARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG },
- [CALL_PY_WITH_DEFAULTS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
+ [CALL_PY_GENERAL] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
[CALL_STR_1] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[CALL_TUPLE_1] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[CALL_TYPE_1] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
@@ -1211,6 +1221,7 @@ _PyOpcode_macro_expansion[256] = {
[BUILD_STRING] = { .nuops = 1, .uops = { { _BUILD_STRING, 0, 0 } } },
[BUILD_TUPLE] = { .nuops = 1, .uops = { { _BUILD_TUPLE, 0, 0 } } },
[CALL_BOUND_METHOD_EXACT_ARGS] = { .nuops = 8, .uops = { { _CHECK_PEP_523, 0, 0 }, { _CHECK_CALL_BOUND_METHOD_EXACT_ARGS, 0, 0 }, { _INIT_CALL_BOUND_METHOD_EXACT_ARGS, 0, 0 }, { _CHECK_FUNCTION_EXACT_ARGS, 2, 1 }, { _CHECK_STACK_SPACE, 0, 0 }, { _INIT_CALL_PY_EXACT_ARGS, 0, 0 }, { _SAVE_RETURN_OFFSET, 7, 3 }, { _PUSH_FRAME, 0, 0 } } },
+ [CALL_BOUND_METHOD_GENERAL] = { .nuops = 6, .uops = { { _CHECK_PEP_523, 0, 0 }, { _CHECK_METHOD_VERSION, 2, 1 }, { _EXPAND_METHOD, 0, 0 }, { _PY_FRAME_GENERAL, 0, 0 }, { _SAVE_RETURN_OFFSET, 7, 3 }, { _PUSH_FRAME, 0, 0 } } },
[CALL_BUILTIN_CLASS] = { .nuops = 2, .uops = { { _CALL_BUILTIN_CLASS, 0, 0 }, { _CHECK_PERIODIC, 0, 0 } } },
[CALL_BUILTIN_FAST] = { .nuops = 2, .uops = { { _CALL_BUILTIN_FAST, 0, 0 }, { _CHECK_PERIODIC, 0, 0 } } },
[CALL_BUILTIN_FAST_WITH_KEYWORDS] = { .nuops = 2, .uops = { { _CALL_BUILTIN_FAST_WITH_KEYWORDS, 0, 0 }, { _CHECK_PERIODIC, 0, 0 } } },
@@ -1223,7 +1234,9 @@ _PyOpcode_macro_expansion[256] = {
[CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { .nuops = 2, .uops = { { _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, 0, 0 }, { _CHECK_PERIODIC, 0, 0 } } },
[CALL_METHOD_DESCRIPTOR_NOARGS] = { .nuops = 2, .uops = { { _CALL_METHOD_DESCRIPTOR_NOARGS, 0, 0 }, { _CHECK_PERIODIC, 0, 0 } } },
[CALL_METHOD_DESCRIPTOR_O] = { .nuops = 2, .uops = { { _CALL_METHOD_DESCRIPTOR_O, 0, 0 }, { _CHECK_PERIODIC, 0, 0 } } },
+ [CALL_NON_PY_GENERAL] = { .nuops = 3, .uops = { { _CHECK_IS_NOT_PY_CALLABLE, 0, 0 }, { _CALL_NON_PY_GENERAL, 0, 0 }, { _CHECK_PERIODIC, 0, 0 } } },
[CALL_PY_EXACT_ARGS] = { .nuops = 6, .uops = { { _CHECK_PEP_523, 0, 0 }, { _CHECK_FUNCTION_EXACT_ARGS, 2, 1 }, { _CHECK_STACK_SPACE, 0, 0 }, { _INIT_CALL_PY_EXACT_ARGS, 0, 0 }, { _SAVE_RETURN_OFFSET, 7, 3 }, { _PUSH_FRAME, 0, 0 } } },
+ [CALL_PY_GENERAL] = { .nuops = 5, .uops = { { _CHECK_PEP_523, 0, 0 }, { _CHECK_FUNCTION_VERSION, 2, 1 }, { _PY_FRAME_GENERAL, 0, 0 }, { _SAVE_RETURN_OFFSET, 7, 3 }, { _PUSH_FRAME, 0, 0 } } },
[CALL_STR_1] = { .nuops = 2, .uops = { { _CALL_STR_1, 0, 0 }, { _CHECK_PERIODIC, 0, 0 } } },
[CALL_TUPLE_1] = { .nuops = 2, .uops = { { _CALL_TUPLE_1, 0, 0 }, { _CHECK_PERIODIC, 0, 0 } } },
[CALL_TYPE_1] = { .nuops = 1, .uops = { { _CALL_TYPE_1, 0, 0 } } },
@@ -1383,6 +1396,7 @@ const char *_PyOpcode_OpName[268] = {
[CALL] = "CALL",
[CALL_ALLOC_AND_ENTER_INIT] = "CALL_ALLOC_AND_ENTER_INIT",
[CALL_BOUND_METHOD_EXACT_ARGS] = "CALL_BOUND_METHOD_EXACT_ARGS",
+ [CALL_BOUND_METHOD_GENERAL] = "CALL_BOUND_METHOD_GENERAL",
[CALL_BUILTIN_CLASS] = "CALL_BUILTIN_CLASS",
[CALL_BUILTIN_FAST] = "CALL_BUILTIN_FAST",
[CALL_BUILTIN_FAST_WITH_KEYWORDS] = "CALL_BUILTIN_FAST_WITH_KEYWORDS",
@@ -1398,8 +1412,9 @@ const char *_PyOpcode_OpName[268] = {
[CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = "CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS",
[CALL_METHOD_DESCRIPTOR_NOARGS] = "CALL_METHOD_DESCRIPTOR_NOARGS",
[CALL_METHOD_DESCRIPTOR_O] = "CALL_METHOD_DESCRIPTOR_O",
+ [CALL_NON_PY_GENERAL] = "CALL_NON_PY_GENERAL",
[CALL_PY_EXACT_ARGS] = "CALL_PY_EXACT_ARGS",
- [CALL_PY_WITH_DEFAULTS] = "CALL_PY_WITH_DEFAULTS",
+ [CALL_PY_GENERAL] = "CALL_PY_GENERAL",
[CALL_STR_1] = "CALL_STR_1",
[CALL_TUPLE_1] = "CALL_TUPLE_1",
[CALL_TYPE_1] = "CALL_TYPE_1",
@@ -1636,6 +1651,7 @@ const uint8_t _PyOpcode_Deopt[256] = {
[CALL] = CALL,
[CALL_ALLOC_AND_ENTER_INIT] = CALL,
[CALL_BOUND_METHOD_EXACT_ARGS] = CALL,
+ [CALL_BOUND_METHOD_GENERAL] = CALL,
[CALL_BUILTIN_CLASS] = CALL,
[CALL_BUILTIN_FAST] = CALL,
[CALL_BUILTIN_FAST_WITH_KEYWORDS] = CALL,
@@ -1651,8 +1667,9 @@ const uint8_t _PyOpcode_Deopt[256] = {
[CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = CALL,
[CALL_METHOD_DESCRIPTOR_NOARGS] = CALL,
[CALL_METHOD_DESCRIPTOR_O] = CALL,
+ [CALL_NON_PY_GENERAL] = CALL,
[CALL_PY_EXACT_ARGS] = CALL,
- [CALL_PY_WITH_DEFAULTS] = CALL,
+ [CALL_PY_GENERAL] = CALL,
[CALL_STR_1] = CALL,
[CALL_TUPLE_1] = CALL,
[CALL_TYPE_1] = CALL,
@@ -1852,8 +1869,6 @@ const uint8_t _PyOpcode_Deopt[256] = {
case 146: \
case 147: \
case 148: \
- case 221: \
- case 222: \
case 223: \
case 224: \
case 225: \
diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h
index 988464b..1e6ef8e 100644
--- a/Include/internal/pycore_uop_ids.h
+++ b/Include/internal/pycore_uop_ids.h
@@ -51,32 +51,35 @@ extern "C" {
#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 317
#define _CALL_METHOD_DESCRIPTOR_NOARGS 318
#define _CALL_METHOD_DESCRIPTOR_O 319
-#define _CALL_PY_WITH_DEFAULTS CALL_PY_WITH_DEFAULTS
-#define _CALL_STR_1 320
-#define _CALL_TUPLE_1 321
+#define _CALL_NON_PY_GENERAL 320
+#define _CALL_STR_1 321
+#define _CALL_TUPLE_1 322
#define _CALL_TYPE_1 CALL_TYPE_1
-#define _CHECK_ATTR_CLASS 322
-#define _CHECK_ATTR_METHOD_LAZY_DICT 323
-#define _CHECK_ATTR_MODULE 324
-#define _CHECK_ATTR_WITH_HINT 325
-#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 326
+#define _CHECK_ATTR_CLASS 323
+#define _CHECK_ATTR_METHOD_LAZY_DICT 324
+#define _CHECK_ATTR_MODULE 325
+#define _CHECK_ATTR_WITH_HINT 326
+#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 327
#define _CHECK_EG_MATCH CHECK_EG_MATCH
#define _CHECK_EXC_MATCH CHECK_EXC_MATCH
-#define _CHECK_FUNCTION 327
-#define _CHECK_FUNCTION_EXACT_ARGS 328
-#define _CHECK_MANAGED_OBJECT_HAS_VALUES 329
-#define _CHECK_PEP_523 330
-#define _CHECK_PERIODIC 331
-#define _CHECK_STACK_SPACE 332
-#define _CHECK_STACK_SPACE_OPERAND 333
-#define _CHECK_VALIDITY 334
-#define _CHECK_VALIDITY_AND_SET_IP 335
-#define _COLD_EXIT 336
-#define _COMPARE_OP 337
-#define _COMPARE_OP_FLOAT 338
-#define _COMPARE_OP_INT 339
-#define _COMPARE_OP_STR 340
-#define _CONTAINS_OP 341
+#define _CHECK_FUNCTION 328
+#define _CHECK_FUNCTION_EXACT_ARGS 329
+#define _CHECK_FUNCTION_VERSION 330
+#define _CHECK_IS_NOT_PY_CALLABLE 331
+#define _CHECK_MANAGED_OBJECT_HAS_VALUES 332
+#define _CHECK_METHOD_VERSION 333
+#define _CHECK_PEP_523 334
+#define _CHECK_PERIODIC 335
+#define _CHECK_STACK_SPACE 336
+#define _CHECK_STACK_SPACE_OPERAND 337
+#define _CHECK_VALIDITY 338
+#define _CHECK_VALIDITY_AND_SET_IP 339
+#define _COLD_EXIT 340
+#define _COMPARE_OP 341
+#define _COMPARE_OP_FLOAT 342
+#define _COMPARE_OP_INT 343
+#define _COMPARE_OP_STR 344
+#define _CONTAINS_OP 345
#define _CONTAINS_OP_DICT CONTAINS_OP_DICT
#define _CONTAINS_OP_SET CONTAINS_OP_SET
#define _CONVERT_VALUE CONVERT_VALUE
@@ -88,52 +91,53 @@ extern "C" {
#define _DELETE_GLOBAL DELETE_GLOBAL
#define _DELETE_NAME DELETE_NAME
#define _DELETE_SUBSCR DELETE_SUBSCR
-#define _DEOPT 342
+#define _DEOPT 346
#define _DICT_MERGE DICT_MERGE
#define _DICT_UPDATE DICT_UPDATE
-#define _DYNAMIC_EXIT 343
+#define _DYNAMIC_EXIT 347
#define _END_SEND END_SEND
-#define _ERROR_POP_N 344
+#define _ERROR_POP_N 348
#define _EXIT_INIT_CHECK EXIT_INIT_CHECK
-#define _FATAL_ERROR 345
+#define _EXPAND_METHOD 349
+#define _FATAL_ERROR 350
#define _FORMAT_SIMPLE FORMAT_SIMPLE
#define _FORMAT_WITH_SPEC FORMAT_WITH_SPEC
-#define _FOR_ITER 346
-#define _FOR_ITER_GEN_FRAME 347
-#define _FOR_ITER_TIER_TWO 348
+#define _FOR_ITER 351
+#define _FOR_ITER_GEN_FRAME 352
+#define _FOR_ITER_TIER_TWO 353
#define _GET_AITER GET_AITER
#define _GET_ANEXT GET_ANEXT
#define _GET_AWAITABLE GET_AWAITABLE
#define _GET_ITER GET_ITER
#define _GET_LEN GET_LEN
#define _GET_YIELD_FROM_ITER GET_YIELD_FROM_ITER
-#define _GUARD_BOTH_FLOAT 349
-#define _GUARD_BOTH_INT 350
-#define _GUARD_BOTH_UNICODE 351
-#define _GUARD_BUILTINS_VERSION 352
-#define _GUARD_DORV_NO_DICT 353
-#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 354
-#define _GUARD_GLOBALS_VERSION 355
-#define _GUARD_IS_FALSE_POP 356
-#define _GUARD_IS_NONE_POP 357
-#define _GUARD_IS_NOT_NONE_POP 358
-#define _GUARD_IS_TRUE_POP 359
-#define _GUARD_KEYS_VERSION 360
-#define _GUARD_NOS_FLOAT 361
-#define _GUARD_NOS_INT 362
-#define _GUARD_NOT_EXHAUSTED_LIST 363
-#define _GUARD_NOT_EXHAUSTED_RANGE 364
-#define _GUARD_NOT_EXHAUSTED_TUPLE 365
-#define _GUARD_TOS_FLOAT 366
-#define _GUARD_TOS_INT 367
-#define _GUARD_TYPE_VERSION 368
-#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 369
-#define _INIT_CALL_PY_EXACT_ARGS 370
-#define _INIT_CALL_PY_EXACT_ARGS_0 371
-#define _INIT_CALL_PY_EXACT_ARGS_1 372
-#define _INIT_CALL_PY_EXACT_ARGS_2 373
-#define _INIT_CALL_PY_EXACT_ARGS_3 374
-#define _INIT_CALL_PY_EXACT_ARGS_4 375
+#define _GUARD_BOTH_FLOAT 354
+#define _GUARD_BOTH_INT 355
+#define _GUARD_BOTH_UNICODE 356
+#define _GUARD_BUILTINS_VERSION 357
+#define _GUARD_DORV_NO_DICT 358
+#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 359
+#define _GUARD_GLOBALS_VERSION 360
+#define _GUARD_IS_FALSE_POP 361
+#define _GUARD_IS_NONE_POP 362
+#define _GUARD_IS_NOT_NONE_POP 363
+#define _GUARD_IS_TRUE_POP 364
+#define _GUARD_KEYS_VERSION 365
+#define _GUARD_NOS_FLOAT 366
+#define _GUARD_NOS_INT 367
+#define _GUARD_NOT_EXHAUSTED_LIST 368
+#define _GUARD_NOT_EXHAUSTED_RANGE 369
+#define _GUARD_NOT_EXHAUSTED_TUPLE 370
+#define _GUARD_TOS_FLOAT 371
+#define _GUARD_TOS_INT 372
+#define _GUARD_TYPE_VERSION 373
+#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 374
+#define _INIT_CALL_PY_EXACT_ARGS 375
+#define _INIT_CALL_PY_EXACT_ARGS_0 376
+#define _INIT_CALL_PY_EXACT_ARGS_1 377
+#define _INIT_CALL_PY_EXACT_ARGS_2 378
+#define _INIT_CALL_PY_EXACT_ARGS_3 379
+#define _INIT_CALL_PY_EXACT_ARGS_4 380
#define _INSTRUMENTED_CALL INSTRUMENTED_CALL
#define _INSTRUMENTED_CALL_FUNCTION_EX INSTRUMENTED_CALL_FUNCTION_EX
#define _INSTRUMENTED_CALL_KW INSTRUMENTED_CALL_KW
@@ -150,65 +154,65 @@ extern "C" {
#define _INSTRUMENTED_RETURN_CONST INSTRUMENTED_RETURN_CONST
#define _INSTRUMENTED_RETURN_VALUE INSTRUMENTED_RETURN_VALUE
#define _INSTRUMENTED_YIELD_VALUE INSTRUMENTED_YIELD_VALUE
-#define _INTERNAL_INCREMENT_OPT_COUNTER 376
-#define _IS_NONE 377
+#define _INTERNAL_INCREMENT_OPT_COUNTER 381
+#define _IS_NONE 382
#define _IS_OP IS_OP
-#define _ITER_CHECK_LIST 378
-#define _ITER_CHECK_RANGE 379
-#define _ITER_CHECK_TUPLE 380
-#define _ITER_JUMP_LIST 381
-#define _ITER_JUMP_RANGE 382
-#define _ITER_JUMP_TUPLE 383
-#define _ITER_NEXT_LIST 384
-#define _ITER_NEXT_RANGE 385
-#define _ITER_NEXT_TUPLE 386
-#define _JUMP_TO_TOP 387
+#define _ITER_CHECK_LIST 383
+#define _ITER_CHECK_RANGE 384
+#define _ITER_CHECK_TUPLE 385
+#define _ITER_JUMP_LIST 386
+#define _ITER_JUMP_RANGE 387
+#define _ITER_JUMP_TUPLE 388
+#define _ITER_NEXT_LIST 389
+#define _ITER_NEXT_RANGE 390
+#define _ITER_NEXT_TUPLE 391
+#define _JUMP_TO_TOP 392
#define _LIST_APPEND LIST_APPEND
#define _LIST_EXTEND LIST_EXTEND
#define _LOAD_ASSERTION_ERROR LOAD_ASSERTION_ERROR
-#define _LOAD_ATTR 388
-#define _LOAD_ATTR_CLASS 389
-#define _LOAD_ATTR_CLASS_0 390
-#define _LOAD_ATTR_CLASS_1 391
+#define _LOAD_ATTR 393
+#define _LOAD_ATTR_CLASS 394
+#define _LOAD_ATTR_CLASS_0 395
+#define _LOAD_ATTR_CLASS_1 396
#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN
-#define _LOAD_ATTR_INSTANCE_VALUE 392
-#define _LOAD_ATTR_INSTANCE_VALUE_0 393
-#define _LOAD_ATTR_INSTANCE_VALUE_1 394
-#define _LOAD_ATTR_METHOD_LAZY_DICT 395
-#define _LOAD_ATTR_METHOD_NO_DICT 396
-#define _LOAD_ATTR_METHOD_WITH_VALUES 397
-#define _LOAD_ATTR_MODULE 398
-#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 399
-#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 400
+#define _LOAD_ATTR_INSTANCE_VALUE 397
+#define _LOAD_ATTR_INSTANCE_VALUE_0 398
+#define _LOAD_ATTR_INSTANCE_VALUE_1 399
+#define _LOAD_ATTR_METHOD_LAZY_DICT 400
+#define _LOAD_ATTR_METHOD_NO_DICT 401
+#define _LOAD_ATTR_METHOD_WITH_VALUES 402
+#define _LOAD_ATTR_MODULE 403
+#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 404
+#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 405
#define _LOAD_ATTR_PROPERTY LOAD_ATTR_PROPERTY
-#define _LOAD_ATTR_SLOT 401
-#define _LOAD_ATTR_SLOT_0 402
-#define _LOAD_ATTR_SLOT_1 403
-#define _LOAD_ATTR_WITH_HINT 404
+#define _LOAD_ATTR_SLOT 406
+#define _LOAD_ATTR_SLOT_0 407
+#define _LOAD_ATTR_SLOT_1 408
+#define _LOAD_ATTR_WITH_HINT 409
#define _LOAD_BUILD_CLASS LOAD_BUILD_CLASS
#define _LOAD_CONST LOAD_CONST
-#define _LOAD_CONST_INLINE 405
-#define _LOAD_CONST_INLINE_BORROW 406
-#define _LOAD_CONST_INLINE_BORROW_WITH_NULL 407
-#define _LOAD_CONST_INLINE_WITH_NULL 408
+#define _LOAD_CONST_INLINE 410
+#define _LOAD_CONST_INLINE_BORROW 411
+#define _LOAD_CONST_INLINE_BORROW_WITH_NULL 412
+#define _LOAD_CONST_INLINE_WITH_NULL 413
#define _LOAD_DEREF LOAD_DEREF
-#define _LOAD_FAST 409
-#define _LOAD_FAST_0 410
-#define _LOAD_FAST_1 411
-#define _LOAD_FAST_2 412
-#define _LOAD_FAST_3 413
-#define _LOAD_FAST_4 414
-#define _LOAD_FAST_5 415
-#define _LOAD_FAST_6 416
-#define _LOAD_FAST_7 417
+#define _LOAD_FAST 414
+#define _LOAD_FAST_0 415
+#define _LOAD_FAST_1 416
+#define _LOAD_FAST_2 417
+#define _LOAD_FAST_3 418
+#define _LOAD_FAST_4 419
+#define _LOAD_FAST_5 420
+#define _LOAD_FAST_6 421
+#define _LOAD_FAST_7 422
#define _LOAD_FAST_AND_CLEAR LOAD_FAST_AND_CLEAR
#define _LOAD_FAST_CHECK LOAD_FAST_CHECK
#define _LOAD_FAST_LOAD_FAST LOAD_FAST_LOAD_FAST
#define _LOAD_FROM_DICT_OR_DEREF LOAD_FROM_DICT_OR_DEREF
#define _LOAD_FROM_DICT_OR_GLOBALS LOAD_FROM_DICT_OR_GLOBALS
-#define _LOAD_GLOBAL 418
-#define _LOAD_GLOBAL_BUILTINS 419
-#define _LOAD_GLOBAL_MODULE 420
+#define _LOAD_GLOBAL 423
+#define _LOAD_GLOBAL_BUILTINS 424
+#define _LOAD_GLOBAL_MODULE 425
#define _LOAD_LOCALS LOAD_LOCALS
#define _LOAD_NAME LOAD_NAME
#define _LOAD_SUPER_ATTR_ATTR LOAD_SUPER_ATTR_ATTR
@@ -222,50 +226,51 @@ extern "C" {
#define _MATCH_SEQUENCE MATCH_SEQUENCE
#define _NOP NOP
#define _POP_EXCEPT POP_EXCEPT
-#define _POP_FRAME 421
-#define _POP_JUMP_IF_FALSE 422
-#define _POP_JUMP_IF_TRUE 423
+#define _POP_FRAME 426
+#define _POP_JUMP_IF_FALSE 427
+#define _POP_JUMP_IF_TRUE 428
#define _POP_TOP POP_TOP
-#define _POP_TOP_LOAD_CONST_INLINE_BORROW 424
+#define _POP_TOP_LOAD_CONST_INLINE_BORROW 429
#define _PUSH_EXC_INFO PUSH_EXC_INFO
-#define _PUSH_FRAME 425
+#define _PUSH_FRAME 430
#define _PUSH_NULL PUSH_NULL
-#define _REPLACE_WITH_TRUE 426
+#define _PY_FRAME_GENERAL 431
+#define _REPLACE_WITH_TRUE 432
#define _RESUME_CHECK RESUME_CHECK
#define _RETURN_GENERATOR RETURN_GENERATOR
-#define _SAVE_RETURN_OFFSET 427
-#define _SEND 428
+#define _SAVE_RETURN_OFFSET 433
+#define _SEND 434
#define _SEND_GEN SEND_GEN
#define _SETUP_ANNOTATIONS SETUP_ANNOTATIONS
#define _SET_ADD SET_ADD
#define _SET_FUNCTION_ATTRIBUTE SET_FUNCTION_ATTRIBUTE
#define _SET_UPDATE SET_UPDATE
-#define _START_EXECUTOR 429
-#define _STORE_ATTR 430
-#define _STORE_ATTR_INSTANCE_VALUE 431
-#define _STORE_ATTR_SLOT 432
+#define _START_EXECUTOR 435
+#define _STORE_ATTR 436
+#define _STORE_ATTR_INSTANCE_VALUE 437
+#define _STORE_ATTR_SLOT 438
#define _STORE_ATTR_WITH_HINT STORE_ATTR_WITH_HINT
#define _STORE_DEREF STORE_DEREF
-#define _STORE_FAST 433
-#define _STORE_FAST_0 434
-#define _STORE_FAST_1 435
-#define _STORE_FAST_2 436
-#define _STORE_FAST_3 437
-#define _STORE_FAST_4 438
-#define _STORE_FAST_5 439
-#define _STORE_FAST_6 440
-#define _STORE_FAST_7 441
+#define _STORE_FAST 439
+#define _STORE_FAST_0 440
+#define _STORE_FAST_1 441
+#define _STORE_FAST_2 442
+#define _STORE_FAST_3 443
+#define _STORE_FAST_4 444
+#define _STORE_FAST_5 445
+#define _STORE_FAST_6 446
+#define _STORE_FAST_7 447
#define _STORE_FAST_LOAD_FAST STORE_FAST_LOAD_FAST
#define _STORE_FAST_STORE_FAST STORE_FAST_STORE_FAST
#define _STORE_GLOBAL STORE_GLOBAL
#define _STORE_NAME STORE_NAME
#define _STORE_SLICE STORE_SLICE
-#define _STORE_SUBSCR 442
+#define _STORE_SUBSCR 448
#define _STORE_SUBSCR_DICT STORE_SUBSCR_DICT
#define _STORE_SUBSCR_LIST_INT STORE_SUBSCR_LIST_INT
#define _SWAP SWAP
-#define _TIER2_RESUME_CHECK 443
-#define _TO_BOOL 444
+#define _TIER2_RESUME_CHECK 449
+#define _TO_BOOL 450
#define _TO_BOOL_BOOL TO_BOOL_BOOL
#define _TO_BOOL_INT TO_BOOL_INT
#define _TO_BOOL_LIST TO_BOOL_LIST
@@ -275,13 +280,13 @@ extern "C" {
#define _UNARY_NEGATIVE UNARY_NEGATIVE
#define _UNARY_NOT UNARY_NOT
#define _UNPACK_EX UNPACK_EX
-#define _UNPACK_SEQUENCE 445
+#define _UNPACK_SEQUENCE 451
#define _UNPACK_SEQUENCE_LIST UNPACK_SEQUENCE_LIST
#define _UNPACK_SEQUENCE_TUPLE UNPACK_SEQUENCE_TUPLE
#define _UNPACK_SEQUENCE_TWO_TUPLE UNPACK_SEQUENCE_TWO_TUPLE
#define _WITH_EXCEPT_START WITH_EXCEPT_START
#define _YIELD_VALUE YIELD_VALUE
-#define MAX_UOP_ID 445
+#define MAX_UOP_ID 451
#ifdef __cplusplus
}
diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h
index 475924d..470e95e 100644
--- a/Include/internal/pycore_uop_metadata.h
+++ b/Include/internal/pycore_uop_metadata.h
@@ -193,7 +193,13 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = {
[_CHECK_ATTR_METHOD_LAZY_DICT] = HAS_DEOPT_FLAG,
[_LOAD_ATTR_METHOD_LAZY_DICT] = HAS_ARG_FLAG,
[_CHECK_PERIODIC] = HAS_EVAL_BREAK_FLAG,
- [_CHECK_CALL_BOUND_METHOD_EXACT_ARGS] = HAS_ARG_FLAG | HAS_DEOPT_FLAG,
+ [_PY_FRAME_GENERAL] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG,
+ [_CHECK_FUNCTION_VERSION] = HAS_ARG_FLAG | HAS_EXIT_FLAG,
+ [_CHECK_METHOD_VERSION] = HAS_ARG_FLAG | HAS_EXIT_FLAG,
+ [_EXPAND_METHOD] = HAS_ARG_FLAG,
+ [_CHECK_IS_NOT_PY_CALLABLE] = HAS_ARG_FLAG | HAS_EXIT_FLAG,
+ [_CALL_NON_PY_GENERAL] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
+ [_CHECK_CALL_BOUND_METHOD_EXACT_ARGS] = HAS_ARG_FLAG | HAS_EXIT_FLAG,
[_INIT_CALL_BOUND_METHOD_EXACT_ARGS] = HAS_ARG_FLAG,
[_CHECK_PEP_523] = HAS_DEOPT_FLAG,
[_CHECK_FUNCTION_EXACT_ARGS] = HAS_ARG_FLAG | HAS_EXIT_FLAG,
@@ -295,6 +301,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = {
[_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = "_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS",
[_CALL_METHOD_DESCRIPTOR_NOARGS] = "_CALL_METHOD_DESCRIPTOR_NOARGS",
[_CALL_METHOD_DESCRIPTOR_O] = "_CALL_METHOD_DESCRIPTOR_O",
+ [_CALL_NON_PY_GENERAL] = "_CALL_NON_PY_GENERAL",
[_CALL_STR_1] = "_CALL_STR_1",
[_CALL_TUPLE_1] = "_CALL_TUPLE_1",
[_CALL_TYPE_1] = "_CALL_TYPE_1",
@@ -307,7 +314,10 @@ const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = {
[_CHECK_EXC_MATCH] = "_CHECK_EXC_MATCH",
[_CHECK_FUNCTION] = "_CHECK_FUNCTION",
[_CHECK_FUNCTION_EXACT_ARGS] = "_CHECK_FUNCTION_EXACT_ARGS",
+ [_CHECK_FUNCTION_VERSION] = "_CHECK_FUNCTION_VERSION",
+ [_CHECK_IS_NOT_PY_CALLABLE] = "_CHECK_IS_NOT_PY_CALLABLE",
[_CHECK_MANAGED_OBJECT_HAS_VALUES] = "_CHECK_MANAGED_OBJECT_HAS_VALUES",
+ [_CHECK_METHOD_VERSION] = "_CHECK_METHOD_VERSION",
[_CHECK_PEP_523] = "_CHECK_PEP_523",
[_CHECK_PERIODIC] = "_CHECK_PERIODIC",
[_CHECK_STACK_SPACE] = "_CHECK_STACK_SPACE",
@@ -339,6 +349,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = {
[_ERROR_POP_N] = "_ERROR_POP_N",
[_EXIT_INIT_CHECK] = "_EXIT_INIT_CHECK",
[_EXIT_TRACE] = "_EXIT_TRACE",
+ [_EXPAND_METHOD] = "_EXPAND_METHOD",
[_FATAL_ERROR] = "_FATAL_ERROR",
[_FORMAT_SIMPLE] = "_FORMAT_SIMPLE",
[_FORMAT_WITH_SPEC] = "_FORMAT_WITH_SPEC",
@@ -449,6 +460,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = {
[_PUSH_EXC_INFO] = "_PUSH_EXC_INFO",
[_PUSH_FRAME] = "_PUSH_FRAME",
[_PUSH_NULL] = "_PUSH_NULL",
+ [_PY_FRAME_GENERAL] = "_PY_FRAME_GENERAL",
[_REPLACE_WITH_TRUE] = "_REPLACE_WITH_TRUE",
[_RESUME_CHECK] = "_RESUME_CHECK",
[_RETURN_GENERATOR] = "_RETURN_GENERATOR",
@@ -850,6 +862,18 @@ int _PyUop_num_popped(int opcode, int oparg)
return 1;
case _CHECK_PERIODIC:
return 0;
+ case _PY_FRAME_GENERAL:
+ return 2 + oparg;
+ case _CHECK_FUNCTION_VERSION:
+ return 2 + oparg;
+ case _CHECK_METHOD_VERSION:
+ return 2 + oparg;
+ case _EXPAND_METHOD:
+ return 2 + oparg;
+ case _CHECK_IS_NOT_PY_CALLABLE:
+ return 2 + oparg;
+ case _CALL_NON_PY_GENERAL:
+ return 2 + oparg;
case _CHECK_CALL_BOUND_METHOD_EXACT_ARGS:
return 2 + oparg;
case _INIT_CALL_BOUND_METHOD_EXACT_ARGS:
diff --git a/Include/opcode_ids.h b/Include/opcode_ids.h
index 185205c..647f7c0 100644
--- a/Include/opcode_ids.h
+++ b/Include/opcode_ids.h
@@ -144,63 +144,65 @@ extern "C" {
#define BINARY_SUBSCR_TUPLE_INT 161
#define CALL_ALLOC_AND_ENTER_INIT 162
#define CALL_BOUND_METHOD_EXACT_ARGS 163
-#define CALL_BUILTIN_CLASS 164
-#define CALL_BUILTIN_FAST 165
-#define CALL_BUILTIN_FAST_WITH_KEYWORDS 166
-#define CALL_BUILTIN_O 167
-#define CALL_ISINSTANCE 168
-#define CALL_LEN 169
-#define CALL_LIST_APPEND 170
-#define CALL_METHOD_DESCRIPTOR_FAST 171
-#define CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 172
-#define CALL_METHOD_DESCRIPTOR_NOARGS 173
-#define CALL_METHOD_DESCRIPTOR_O 174
-#define CALL_PY_EXACT_ARGS 175
-#define CALL_PY_WITH_DEFAULTS 176
-#define CALL_STR_1 177
-#define CALL_TUPLE_1 178
-#define CALL_TYPE_1 179
-#define COMPARE_OP_FLOAT 180
-#define COMPARE_OP_INT 181
-#define COMPARE_OP_STR 182
-#define CONTAINS_OP_DICT 183
-#define CONTAINS_OP_SET 184
-#define FOR_ITER_GEN 185
-#define FOR_ITER_LIST 186
-#define FOR_ITER_RANGE 187
-#define FOR_ITER_TUPLE 188
-#define LOAD_ATTR_CLASS 189
-#define LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN 190
-#define LOAD_ATTR_INSTANCE_VALUE 191
-#define LOAD_ATTR_METHOD_LAZY_DICT 192
-#define LOAD_ATTR_METHOD_NO_DICT 193
-#define LOAD_ATTR_METHOD_WITH_VALUES 194
-#define LOAD_ATTR_MODULE 195
-#define LOAD_ATTR_NONDESCRIPTOR_NO_DICT 196
-#define LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 197
-#define LOAD_ATTR_PROPERTY 198
-#define LOAD_ATTR_SLOT 199
-#define LOAD_ATTR_WITH_HINT 200
-#define LOAD_GLOBAL_BUILTIN 201
-#define LOAD_GLOBAL_MODULE 202
-#define LOAD_SUPER_ATTR_ATTR 203
-#define LOAD_SUPER_ATTR_METHOD 204
-#define RESUME_CHECK 205
-#define SEND_GEN 206
-#define STORE_ATTR_INSTANCE_VALUE 207
-#define STORE_ATTR_SLOT 208
-#define STORE_ATTR_WITH_HINT 209
-#define STORE_SUBSCR_DICT 210
-#define STORE_SUBSCR_LIST_INT 211
-#define TO_BOOL_ALWAYS_TRUE 212
-#define TO_BOOL_BOOL 213
-#define TO_BOOL_INT 214
-#define TO_BOOL_LIST 215
-#define TO_BOOL_NONE 216
-#define TO_BOOL_STR 217
-#define UNPACK_SEQUENCE_LIST 218
-#define UNPACK_SEQUENCE_TUPLE 219
-#define UNPACK_SEQUENCE_TWO_TUPLE 220
+#define CALL_BOUND_METHOD_GENERAL 164
+#define CALL_BUILTIN_CLASS 165
+#define CALL_BUILTIN_FAST 166
+#define CALL_BUILTIN_FAST_WITH_KEYWORDS 167
+#define CALL_BUILTIN_O 168
+#define CALL_ISINSTANCE 169
+#define CALL_LEN 170
+#define CALL_LIST_APPEND 171
+#define CALL_METHOD_DESCRIPTOR_FAST 172
+#define CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 173
+#define CALL_METHOD_DESCRIPTOR_NOARGS 174
+#define CALL_METHOD_DESCRIPTOR_O 175
+#define CALL_NON_PY_GENERAL 176
+#define CALL_PY_EXACT_ARGS 177
+#define CALL_PY_GENERAL 178
+#define CALL_STR_1 179
+#define CALL_TUPLE_1 180
+#define CALL_TYPE_1 181
+#define COMPARE_OP_FLOAT 182
+#define COMPARE_OP_INT 183
+#define COMPARE_OP_STR 184
+#define CONTAINS_OP_DICT 185
+#define CONTAINS_OP_SET 186
+#define FOR_ITER_GEN 187
+#define FOR_ITER_LIST 188
+#define FOR_ITER_RANGE 189
+#define FOR_ITER_TUPLE 190
+#define LOAD_ATTR_CLASS 191
+#define LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN 192
+#define LOAD_ATTR_INSTANCE_VALUE 193
+#define LOAD_ATTR_METHOD_LAZY_DICT 194
+#define LOAD_ATTR_METHOD_NO_DICT 195
+#define LOAD_ATTR_METHOD_WITH_VALUES 196
+#define LOAD_ATTR_MODULE 197
+#define LOAD_ATTR_NONDESCRIPTOR_NO_DICT 198
+#define LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 199
+#define LOAD_ATTR_PROPERTY 200
+#define LOAD_ATTR_SLOT 201
+#define LOAD_ATTR_WITH_HINT 202
+#define LOAD_GLOBAL_BUILTIN 203
+#define LOAD_GLOBAL_MODULE 204
+#define LOAD_SUPER_ATTR_ATTR 205
+#define LOAD_SUPER_ATTR_METHOD 206
+#define RESUME_CHECK 207
+#define SEND_GEN 208
+#define STORE_ATTR_INSTANCE_VALUE 209
+#define STORE_ATTR_SLOT 210
+#define STORE_ATTR_WITH_HINT 211
+#define STORE_SUBSCR_DICT 212
+#define STORE_SUBSCR_LIST_INT 213
+#define TO_BOOL_ALWAYS_TRUE 214
+#define TO_BOOL_BOOL 215
+#define TO_BOOL_INT 216
+#define TO_BOOL_LIST 217
+#define TO_BOOL_NONE 218
+#define TO_BOOL_STR 219
+#define UNPACK_SEQUENCE_LIST 220
+#define UNPACK_SEQUENCE_TUPLE 221
+#define UNPACK_SEQUENCE_TWO_TUPLE 222
#define INSTRUMENTED_RESUME 236
#define INSTRUMENTED_END_FOR 237
#define INSTRUMENTED_END_SEND 238
diff --git a/Lib/_opcode_metadata.py b/Lib/_opcode_metadata.py
index b5bafe6..b3d7b81 100644
--- a/Lib/_opcode_metadata.py
+++ b/Lib/_opcode_metadata.py
@@ -88,7 +88,6 @@ _specializations = {
"CALL": [
"CALL_BOUND_METHOD_EXACT_ARGS",
"CALL_PY_EXACT_ARGS",
- "CALL_PY_WITH_DEFAULTS",
"CALL_TYPE_1",
"CALL_STR_1",
"CALL_TUPLE_1",
@@ -104,6 +103,9 @@ _specializations = {
"CALL_METHOD_DESCRIPTOR_NOARGS",
"CALL_METHOD_DESCRIPTOR_FAST",
"CALL_ALLOC_AND_ENTER_INIT",
+ "CALL_PY_GENERAL",
+ "CALL_BOUND_METHOD_GENERAL",
+ "CALL_NON_PY_GENERAL",
],
}
@@ -123,63 +125,65 @@ _specialized_opmap = {
'BINARY_SUBSCR_TUPLE_INT': 161,
'CALL_ALLOC_AND_ENTER_INIT': 162,
'CALL_BOUND_METHOD_EXACT_ARGS': 163,
- 'CALL_BUILTIN_CLASS': 164,
- 'CALL_BUILTIN_FAST': 165,
- 'CALL_BUILTIN_FAST_WITH_KEYWORDS': 166,
- 'CALL_BUILTIN_O': 167,
- 'CALL_ISINSTANCE': 168,
- 'CALL_LEN': 169,
- 'CALL_LIST_APPEND': 170,
- 'CALL_METHOD_DESCRIPTOR_FAST': 171,
- 'CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS': 172,
- 'CALL_METHOD_DESCRIPTOR_NOARGS': 173,
- 'CALL_METHOD_DESCRIPTOR_O': 174,
- 'CALL_PY_EXACT_ARGS': 175,
- 'CALL_PY_WITH_DEFAULTS': 176,
- 'CALL_STR_1': 177,
- 'CALL_TUPLE_1': 178,
- 'CALL_TYPE_1': 179,
- 'COMPARE_OP_FLOAT': 180,
- 'COMPARE_OP_INT': 181,
- 'COMPARE_OP_STR': 182,
- 'CONTAINS_OP_DICT': 183,
- 'CONTAINS_OP_SET': 184,
- 'FOR_ITER_GEN': 185,
- 'FOR_ITER_LIST': 186,
- 'FOR_ITER_RANGE': 187,
- 'FOR_ITER_TUPLE': 188,
- 'LOAD_ATTR_CLASS': 189,
- 'LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN': 190,
- 'LOAD_ATTR_INSTANCE_VALUE': 191,
- 'LOAD_ATTR_METHOD_LAZY_DICT': 192,
- 'LOAD_ATTR_METHOD_NO_DICT': 193,
- 'LOAD_ATTR_METHOD_WITH_VALUES': 194,
- 'LOAD_ATTR_MODULE': 195,
- 'LOAD_ATTR_NONDESCRIPTOR_NO_DICT': 196,
- 'LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES': 197,
- 'LOAD_ATTR_PROPERTY': 198,
- 'LOAD_ATTR_SLOT': 199,
- 'LOAD_ATTR_WITH_HINT': 200,
- 'LOAD_GLOBAL_BUILTIN': 201,
- 'LOAD_GLOBAL_MODULE': 202,
- 'LOAD_SUPER_ATTR_ATTR': 203,
- 'LOAD_SUPER_ATTR_METHOD': 204,
- 'RESUME_CHECK': 205,
- 'SEND_GEN': 206,
- 'STORE_ATTR_INSTANCE_VALUE': 207,
- 'STORE_ATTR_SLOT': 208,
- 'STORE_ATTR_WITH_HINT': 209,
- 'STORE_SUBSCR_DICT': 210,
- 'STORE_SUBSCR_LIST_INT': 211,
- 'TO_BOOL_ALWAYS_TRUE': 212,
- 'TO_BOOL_BOOL': 213,
- 'TO_BOOL_INT': 214,
- 'TO_BOOL_LIST': 215,
- 'TO_BOOL_NONE': 216,
- 'TO_BOOL_STR': 217,
- 'UNPACK_SEQUENCE_LIST': 218,
- 'UNPACK_SEQUENCE_TUPLE': 219,
- 'UNPACK_SEQUENCE_TWO_TUPLE': 220,
+ 'CALL_BOUND_METHOD_GENERAL': 164,
+ 'CALL_BUILTIN_CLASS': 165,
+ 'CALL_BUILTIN_FAST': 166,
+ 'CALL_BUILTIN_FAST_WITH_KEYWORDS': 167,
+ 'CALL_BUILTIN_O': 168,
+ 'CALL_ISINSTANCE': 169,
+ 'CALL_LEN': 170,
+ 'CALL_LIST_APPEND': 171,
+ 'CALL_METHOD_DESCRIPTOR_FAST': 172,
+ 'CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS': 173,
+ 'CALL_METHOD_DESCRIPTOR_NOARGS': 174,
+ 'CALL_METHOD_DESCRIPTOR_O': 175,
+ 'CALL_NON_PY_GENERAL': 176,
+ 'CALL_PY_EXACT_ARGS': 177,
+ 'CALL_PY_GENERAL': 178,
+ 'CALL_STR_1': 179,
+ 'CALL_TUPLE_1': 180,
+ 'CALL_TYPE_1': 181,
+ 'COMPARE_OP_FLOAT': 182,
+ 'COMPARE_OP_INT': 183,
+ 'COMPARE_OP_STR': 184,
+ 'CONTAINS_OP_DICT': 185,
+ 'CONTAINS_OP_SET': 186,
+ 'FOR_ITER_GEN': 187,
+ 'FOR_ITER_LIST': 188,
+ 'FOR_ITER_RANGE': 189,
+ 'FOR_ITER_TUPLE': 190,
+ 'LOAD_ATTR_CLASS': 191,
+ 'LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN': 192,
+ 'LOAD_ATTR_INSTANCE_VALUE': 193,
+ 'LOAD_ATTR_METHOD_LAZY_DICT': 194,
+ 'LOAD_ATTR_METHOD_NO_DICT': 195,
+ 'LOAD_ATTR_METHOD_WITH_VALUES': 196,
+ 'LOAD_ATTR_MODULE': 197,
+ 'LOAD_ATTR_NONDESCRIPTOR_NO_DICT': 198,
+ 'LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES': 199,
+ 'LOAD_ATTR_PROPERTY': 200,
+ 'LOAD_ATTR_SLOT': 201,
+ 'LOAD_ATTR_WITH_HINT': 202,
+ 'LOAD_GLOBAL_BUILTIN': 203,
+ 'LOAD_GLOBAL_MODULE': 204,
+ 'LOAD_SUPER_ATTR_ATTR': 205,
+ 'LOAD_SUPER_ATTR_METHOD': 206,
+ 'RESUME_CHECK': 207,
+ 'SEND_GEN': 208,
+ 'STORE_ATTR_INSTANCE_VALUE': 209,
+ 'STORE_ATTR_SLOT': 210,
+ 'STORE_ATTR_WITH_HINT': 211,
+ 'STORE_SUBSCR_DICT': 212,
+ 'STORE_SUBSCR_LIST_INT': 213,
+ 'TO_BOOL_ALWAYS_TRUE': 214,
+ 'TO_BOOL_BOOL': 215,
+ 'TO_BOOL_INT': 216,
+ 'TO_BOOL_LIST': 217,
+ 'TO_BOOL_NONE': 218,
+ 'TO_BOOL_STR': 219,
+ 'UNPACK_SEQUENCE_LIST': 220,
+ 'UNPACK_SEQUENCE_TUPLE': 221,
+ 'UNPACK_SEQUENCE_TWO_TUPLE': 222,
}
opmap = {
diff --git a/Lib/test/test_call.py b/Lib/test/test_call.py
index d3f4d6c..7ea2792 100644
--- a/Lib/test/test_call.py
+++ b/Lib/test/test_call.py
@@ -46,11 +46,16 @@ class FunctionCalls(unittest.TestCase):
# recovering from failed calls:
def f():
pass
- for _ in range(1000):
- try:
- f(None)
- except TypeError:
+ class C:
+ def m(self):
pass
+ callables = [f, C.m, [].__len__]
+ for c in callables:
+ for _ in range(1000):
+ try:
+ c(None)
+ except TypeError:
+ pass
# BOOM!
diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py
index 747a738..b68ed3b 100644
--- a/Lib/test/test_dis.py
+++ b/Lib/test/test_dis.py
@@ -840,7 +840,7 @@ dis_loop_test_quickened_code = """\
%3d LOAD_GLOBAL_MODULE 1 (load_test + NULL)
LOAD_FAST 0 (i)
- CALL_PY_WITH_DEFAULTS 1
+ CALL_PY_GENERAL 1
POP_TOP
JUMP_BACKWARD 16 (to L1)
diff --git a/Lib/test/test_dynamic.py b/Lib/test/test_dynamic.py
index 0aa3be6..21bece2 100644
--- a/Lib/test/test_dynamic.py
+++ b/Lib/test/test_dynamic.py
@@ -4,7 +4,7 @@ import builtins
import sys
import unittest
-from test.support import swap_item, swap_attr
+from test.support import swap_item, swap_attr, is_wasi, Py_DEBUG
class RebindBuiltinsTests(unittest.TestCase):
@@ -134,6 +134,7 @@ class RebindBuiltinsTests(unittest.TestCase):
self.assertEqual(foo(), 7)
+ @unittest.skipIf(is_wasi and Py_DEBUG, "requires too much stack")
def test_load_global_specialization_failure_keeps_oparg(self):
# https://github.com/python/cpython/issues/91625
class MyGlobals(dict):
diff --git a/Lib/test/test_glob.py b/Lib/test/test_glob.py
index 70ee35e..b72640b 100644
--- a/Lib/test/test_glob.py
+++ b/Lib/test/test_glob.py
@@ -6,6 +6,7 @@ import sys
import unittest
import warnings
+from test.support import is_wasi, Py_DEBUG
from test.support.os_helper import (TESTFN, skip_unless_symlink,
can_symlink, create_empty_file, change_cwd)
@@ -366,6 +367,8 @@ class GlobTests(unittest.TestCase):
self.assertEqual(self.rglob('mypipe', 'sub'), [])
self.assertEqual(self.rglob('mypipe', '*'), [])
+
+ @unittest.skipIf(is_wasi and Py_DEBUG, "requires too much stack")
def test_glob_many_open_files(self):
depth = 30
base = os.path.join(self.tempdir, 'deep')
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index ddada96..b2a0dc0 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -3042,7 +3042,6 @@ dummy_func(
family(CALL, INLINE_CACHE_ENTRIES_CALL) = {
CALL_BOUND_METHOD_EXACT_ARGS,
CALL_PY_EXACT_ARGS,
- CALL_PY_WITH_DEFAULTS,
CALL_TYPE_1,
CALL_STR_1,
CALL_TUPLE_1,
@@ -3058,6 +3057,9 @@ dummy_func(
CALL_METHOD_DESCRIPTOR_NOARGS,
CALL_METHOD_DESCRIPTOR_FAST,
CALL_ALLOC_AND_ENTER_INIT,
+ CALL_PY_GENERAL,
+ CALL_BOUND_METHOD_GENERAL,
+ CALL_NON_PY_GENERAL,
};
specializing op(_SPECIALIZE_CALL, (counter/1, callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) {
@@ -3147,9 +3149,108 @@ dummy_func(
macro(CALL) = _SPECIALIZE_CALL + unused/2 + _CALL + _CHECK_PERIODIC;
+ op(_PY_FRAME_GENERAL, (callable, self_or_null, args[oparg] -- new_frame: _PyInterpreterFrame*)) {
+ // oparg counts all of the args, but *not* self:
+ int total_args = oparg;
+ if (self_or_null != NULL) {
+ args--;
+ total_args++;
+ }
+ assert(Py_TYPE(callable) == &PyFunction_Type);
+ int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable))->co_flags;
+ PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable));
+ new_frame = _PyEvalFramePushAndInit(
+ tstate, (PyFunctionObject *)callable, locals,
+ args, total_args, NULL
+ );
+ // The frame has stolen all the arguments from the stack,
+ // so there is no need to clean them up.
+ SYNC_SP();
+ if (new_frame == NULL) {
+ ERROR_NO_POP();
+ }
+ }
+
+ op(_CHECK_FUNCTION_VERSION, (func_version/2, callable, unused, unused[oparg] -- callable, unused, unused[oparg])) {
+ EXIT_IF(!PyFunction_Check(callable));
+ PyFunctionObject *func = (PyFunctionObject *)callable;
+ EXIT_IF(func->func_version != func_version);
+ }
+
+ macro(CALL_PY_GENERAL) =
+ unused/1 + // Skip over the counter
+ _CHECK_PEP_523 +
+ _CHECK_FUNCTION_VERSION +
+ _PY_FRAME_GENERAL +
+ _SAVE_RETURN_OFFSET +
+ _PUSH_FRAME;
+
+ op(_CHECK_METHOD_VERSION, (func_version/2, callable, null, unused[oparg] -- callable, null, unused[oparg])) {
+ EXIT_IF(Py_TYPE(callable) != &PyMethod_Type);
+ PyObject *func = ((PyMethodObject *)callable)->im_func;
+ EXIT_IF(!PyFunction_Check(func));
+ EXIT_IF(((PyFunctionObject *)func)->func_version != func_version);
+ EXIT_IF(null != NULL);
+ }
+
+ op(_EXPAND_METHOD, (callable, null, unused[oparg] -- method, self, unused[oparg])) {
+ assert(null == NULL);
+ assert(Py_TYPE(callable) == &PyMethod_Type);
+ self = ((PyMethodObject *)callable)->im_self;
+ Py_INCREF(self);
+ stack_pointer[-1 - oparg] = self; // Patch stack as it is used by _PY_FRAME_GENERAL
+ method = ((PyMethodObject *)callable)->im_func;
+ assert(PyFunction_Check(method));
+ Py_INCREF(method);
+ Py_DECREF(callable);
+ }
+
+ macro(CALL_BOUND_METHOD_GENERAL) =
+ unused/1 + // Skip over the counter
+ _CHECK_PEP_523 +
+ _CHECK_METHOD_VERSION +
+ _EXPAND_METHOD +
+ _PY_FRAME_GENERAL +
+ _SAVE_RETURN_OFFSET +
+ _PUSH_FRAME;
+
+ op(_CHECK_IS_NOT_PY_CALLABLE, (callable, unused, unused[oparg] -- callable, unused, unused[oparg])) {
+ EXIT_IF(PyFunction_Check(callable));
+ EXIT_IF(Py_TYPE(callable) == &PyMethod_Type);
+ }
+
+ op(_CALL_NON_PY_GENERAL, (callable, self_or_null, args[oparg] -- res)) {
+#if TIER_ONE
+ assert(opcode != INSTRUMENTED_CALL);
+#endif
+ int total_args = oparg;
+ if (self_or_null != NULL) {
+ args--;
+ total_args++;
+ }
+ /* Callable is not a normal Python function */
+ res = PyObject_Vectorcall(
+ callable, args,
+ total_args | PY_VECTORCALL_ARGUMENTS_OFFSET,
+ NULL);
+ assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
+ Py_DECREF(callable);
+ for (int i = 0; i < total_args; i++) {
+ Py_DECREF(args[i]);
+ }
+ ERROR_IF(res == NULL, error);
+ }
+
+ macro(CALL_NON_PY_GENERAL) =
+ unused/1 + // Skip over the counter
+ unused/2 +
+ _CHECK_IS_NOT_PY_CALLABLE +
+ _CALL_NON_PY_GENERAL +
+ _CHECK_PERIODIC;
+
op(_CHECK_CALL_BOUND_METHOD_EXACT_ARGS, (callable, null, unused[oparg] -- callable, null, unused[oparg])) {
- DEOPT_IF(null != NULL);
- DEOPT_IF(Py_TYPE(callable) != &PyMethod_Type);
+ EXIT_IF(null != NULL);
+ EXIT_IF(Py_TYPE(callable) != &PyMethod_Type);
}
op(_INIT_CALL_BOUND_METHOD_EXACT_ARGS, (callable, unused, unused[oparg] -- func, self, unused[oparg])) {
@@ -3227,40 +3328,6 @@ dummy_func(
_SAVE_RETURN_OFFSET +
_PUSH_FRAME;
- inst(CALL_PY_WITH_DEFAULTS, (unused/1, func_version/2, callable, self_or_null, args[oparg] -- unused)) {
- DEOPT_IF(tstate->interp->eval_frame);
- int argcount = oparg;
- if (self_or_null != NULL) {
- args--;
- argcount++;
- }
- DEOPT_IF(!PyFunction_Check(callable));
- PyFunctionObject *func = (PyFunctionObject *)callable;
- DEOPT_IF(func->func_version != func_version);
- PyCodeObject *code = (PyCodeObject *)func->func_code;
- assert(func->func_defaults);
- assert(PyTuple_CheckExact(func->func_defaults));
- int defcount = (int)PyTuple_GET_SIZE(func->func_defaults);
- assert(defcount <= code->co_argcount);
- int min_args = code->co_argcount - defcount;
- DEOPT_IF(argcount > code->co_argcount);
- DEOPT_IF(argcount < min_args);
- DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize));
- STAT_INC(CALL, hit);
- _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, func, code->co_argcount);
- for (int i = 0; i < argcount; i++) {
- new_frame->localsplus[i] = args[i];
- }
- for (int i = argcount; i < code->co_argcount; i++) {
- PyObject *def = PyTuple_GET_ITEM(func->func_defaults, i - min_args);
- new_frame->localsplus[i] = Py_NewRef(def);
- }
- // Manipulate stack and cache directly since we leave using DISPATCH_INLINED().
- STACK_SHRINK(oparg + 2);
- frame->return_offset = (uint16_t)(next_instr - this_instr);
- DISPATCH_INLINED(new_frame);
- }
-
inst(CALL_TYPE_1, (unused/1, unused/2, callable, null, arg -- res)) {
assert(oparg == 1);
DEOPT_IF(null != NULL);
diff --git a/Python/ceval.c b/Python/ceval.c
index 1187469..3626ffb 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -247,10 +247,6 @@ static PyObject * import_name(PyThreadState *, _PyInterpreterFrame *,
static PyObject * import_from(PyThreadState *, PyObject *, PyObject *);
static int check_args_iterable(PyThreadState *, PyObject *func, PyObject *vararg);
static int get_exception_handler(PyCodeObject *, int, int*, int*, int*);
-static _PyInterpreterFrame *
-_PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func,
- PyObject *locals, PyObject* const* args,
- size_t argcount, PyObject *kwnames);
static _PyInterpreterFrame *
_PyEvalFramePushAndInit_Ex(PyThreadState *tstate, PyFunctionObject *func,
PyObject *locals, Py_ssize_t nargs, PyObject *callargs, PyObject *kwargs);
@@ -1716,7 +1712,7 @@ _PyEval_FrameClearAndPop(PyThreadState *tstate, _PyInterpreterFrame * frame)
}
/* Consumes references to func, locals and all the args */
-static _PyInterpreterFrame *
+_PyInterpreterFrame *
_PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func,
PyObject *locals, PyObject* const* args,
size_t argcount, PyObject *kwnames)
@@ -1736,6 +1732,8 @@ _PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func,
return frame;
fail:
/* Consume the references */
+ Py_DECREF(func);
+ Py_XDECREF(locals);
for (size_t i = 0; i < argcount; i++) {
Py_DECREF(args[i]);
}
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index d0b794c..5f15f67 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -3032,6 +3032,153 @@
break;
}
+ case _PY_FRAME_GENERAL: {
+ PyObject **args;
+ PyObject *self_or_null;
+ PyObject *callable;
+ _PyInterpreterFrame *new_frame;
+ oparg = CURRENT_OPARG();
+ args = &stack_pointer[-oparg];
+ self_or_null = stack_pointer[-1 - oparg];
+ callable = stack_pointer[-2 - oparg];
+ // oparg counts all of the args, but *not* self:
+ int total_args = oparg;
+ if (self_or_null != NULL) {
+ args--;
+ total_args++;
+ }
+ assert(Py_TYPE(callable) == &PyFunction_Type);
+ int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable))->co_flags;
+ PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable));
+ new_frame = _PyEvalFramePushAndInit(
+ tstate, (PyFunctionObject *)callable, locals,
+ args, total_args, NULL
+ );
+ // The frame has stolen all the arguments from the stack,
+ // so there is no need to clean them up.
+ stack_pointer += -2 - oparg;
+ if (new_frame == NULL) {
+ JUMP_TO_ERROR();
+ }
+ stack_pointer[0] = (PyObject *)new_frame;
+ stack_pointer += 1;
+ break;
+ }
+
+ case _CHECK_FUNCTION_VERSION: {
+ PyObject *callable;
+ oparg = CURRENT_OPARG();
+ callable = stack_pointer[-2 - oparg];
+ uint32_t func_version = (uint32_t)CURRENT_OPERAND();
+ if (!PyFunction_Check(callable)) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ PyFunctionObject *func = (PyFunctionObject *)callable;
+ if (func->func_version != func_version) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ break;
+ }
+
+ case _CHECK_METHOD_VERSION: {
+ PyObject *null;
+ PyObject *callable;
+ oparg = CURRENT_OPARG();
+ null = stack_pointer[-1 - oparg];
+ callable = stack_pointer[-2 - oparg];
+ uint32_t func_version = (uint32_t)CURRENT_OPERAND();
+ if (Py_TYPE(callable) != &PyMethod_Type) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ PyObject *func = ((PyMethodObject *)callable)->im_func;
+ if (!PyFunction_Check(func)) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ if (((PyFunctionObject *)func)->func_version != func_version) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ if (null != NULL) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ break;
+ }
+
+ case _EXPAND_METHOD: {
+ PyObject *null;
+ PyObject *callable;
+ PyObject *method;
+ PyObject *self;
+ oparg = CURRENT_OPARG();
+ null = stack_pointer[-1 - oparg];
+ callable = stack_pointer[-2 - oparg];
+ assert(null == NULL);
+ assert(Py_TYPE(callable) == &PyMethod_Type);
+ self = ((PyMethodObject *)callable)->im_self;
+ Py_INCREF(self);
+ stack_pointer[-1 - oparg] = self; // Patch stack as it is used by _PY_FRAME_GENERAL
+ method = ((PyMethodObject *)callable)->im_func;
+ assert(PyFunction_Check(method));
+ Py_INCREF(method);
+ Py_DECREF(callable);
+ stack_pointer[-2 - oparg] = method;
+ stack_pointer[-1 - oparg] = self;
+ break;
+ }
+
+ case _CHECK_IS_NOT_PY_CALLABLE: {
+ PyObject *callable;
+ oparg = CURRENT_OPARG();
+ callable = stack_pointer[-2 - oparg];
+ if (PyFunction_Check(callable)) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ if (Py_TYPE(callable) == &PyMethod_Type) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ break;
+ }
+
+ case _CALL_NON_PY_GENERAL: {
+ PyObject **args;
+ PyObject *self_or_null;
+ PyObject *callable;
+ PyObject *res;
+ oparg = CURRENT_OPARG();
+ args = &stack_pointer[-oparg];
+ self_or_null = stack_pointer[-1 - oparg];
+ callable = stack_pointer[-2 - oparg];
+ #if TIER_ONE
+ assert(opcode != INSTRUMENTED_CALL);
+ #endif
+ int total_args = oparg;
+ if (self_or_null != NULL) {
+ args--;
+ total_args++;
+ }
+ /* Callable is not a normal Python function */
+ res = PyObject_Vectorcall(
+ callable, args,
+ total_args | PY_VECTORCALL_ARGUMENTS_OFFSET,
+ NULL);
+ assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
+ Py_DECREF(callable);
+ for (int i = 0; i < total_args; i++) {
+ Py_DECREF(args[i]);
+ }
+ if (res == NULL) JUMP_TO_ERROR();
+ stack_pointer[-2 - oparg] = res;
+ stack_pointer += -1 - oparg;
+ break;
+ }
+
case _CHECK_CALL_BOUND_METHOD_EXACT_ARGS: {
PyObject *null;
PyObject *callable;
@@ -3276,8 +3423,6 @@
break;
}
- /* _CALL_PY_WITH_DEFAULTS is not a viable micro-op for tier 2 because it uses the 'this_instr' variable */
-
case _CALL_TYPE_1: {
PyObject *arg;
PyObject *null;
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 800d192..87098b0 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -1002,6 +1002,97 @@
DISPATCH();
}
+ TARGET(CALL_BOUND_METHOD_GENERAL) {
+ _Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr;
+ next_instr += 4;
+ INSTRUCTION_STATS(CALL_BOUND_METHOD_GENERAL);
+ static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size");
+ PyObject *null;
+ PyObject *callable;
+ PyObject *method;
+ PyObject *self;
+ PyObject **args;
+ PyObject *self_or_null;
+ _PyInterpreterFrame *new_frame;
+ /* Skip 1 cache entry */
+ // _CHECK_PEP_523
+ {
+ DEOPT_IF(tstate->interp->eval_frame, CALL);
+ }
+ // _CHECK_METHOD_VERSION
+ null = stack_pointer[-1 - oparg];
+ callable = stack_pointer[-2 - oparg];
+ {
+ uint32_t func_version = read_u32(&this_instr[2].cache);
+ DEOPT_IF(Py_TYPE(callable) != &PyMethod_Type, CALL);
+ PyObject *func = ((PyMethodObject *)callable)->im_func;
+ DEOPT_IF(!PyFunction_Check(func), CALL);
+ DEOPT_IF(((PyFunctionObject *)func)->func_version != func_version, CALL);
+ DEOPT_IF(null != NULL, CALL);
+ }
+ // _EXPAND_METHOD
+ {
+ assert(null == NULL);
+ assert(Py_TYPE(callable) == &PyMethod_Type);
+ self = ((PyMethodObject *)callable)->im_self;
+ Py_INCREF(self);
+ stack_pointer[-1 - oparg] = self; // Patch stack as it is used by _PY_FRAME_GENERAL
+ method = ((PyMethodObject *)callable)->im_func;
+ assert(PyFunction_Check(method));
+ Py_INCREF(method);
+ Py_DECREF(callable);
+ }
+ // _PY_FRAME_GENERAL
+ args = &stack_pointer[-oparg];
+ self_or_null = self;
+ callable = method;
+ {
+ // oparg counts all of the args, but *not* self:
+ int total_args = oparg;
+ if (self_or_null != NULL) {
+ args--;
+ total_args++;
+ }
+ assert(Py_TYPE(callable) == &PyFunction_Type);
+ int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable))->co_flags;
+ PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable));
+ new_frame = _PyEvalFramePushAndInit(
+ tstate, (PyFunctionObject *)callable, locals,
+ args, total_args, NULL
+ );
+ // The frame has stolen all the arguments from the stack,
+ // so there is no need to clean them up.
+ stack_pointer += -2 - oparg;
+ if (new_frame == NULL) {
+ goto error;
+ }
+ }
+ // _SAVE_RETURN_OFFSET
+ {
+ #if TIER_ONE
+ frame->return_offset = (uint16_t)(next_instr - this_instr);
+ #endif
+ #if TIER_TWO
+ frame->return_offset = oparg;
+ #endif
+ }
+ // _PUSH_FRAME
+ {
+ // Write it out explicitly because it's subtly different.
+ // Eventually this should be the only occurrence of this code.
+ assert(tstate->interp->eval_frame == NULL);
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ new_frame->previous = frame;
+ CALL_STAT_INC(inlined_py_calls);
+ frame = tstate->current_frame = new_frame;
+ tstate->py_recursion_remaining--;
+ LOAD_SP();
+ LOAD_IP(0);
+ LLTRACE_RESUME_FRAME();
+ }
+ DISPATCH();
+ }
+
TARGET(CALL_BUILTIN_CLASS) {
frame->instr_ptr = next_instr;
next_instr += 4;
@@ -1713,6 +1804,56 @@
DISPATCH();
}
+ TARGET(CALL_NON_PY_GENERAL) {
+ frame->instr_ptr = next_instr;
+ next_instr += 4;
+ INSTRUCTION_STATS(CALL_NON_PY_GENERAL);
+ static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size");
+ PyObject *callable;
+ PyObject **args;
+ PyObject *self_or_null;
+ PyObject *res;
+ /* Skip 1 cache entry */
+ /* Skip 2 cache entries */
+ // _CHECK_IS_NOT_PY_CALLABLE
+ callable = stack_pointer[-2 - oparg];
+ {
+ DEOPT_IF(PyFunction_Check(callable), CALL);
+ DEOPT_IF(Py_TYPE(callable) == &PyMethod_Type, CALL);
+ }
+ // _CALL_NON_PY_GENERAL
+ args = &stack_pointer[-oparg];
+ self_or_null = stack_pointer[-1 - oparg];
+ {
+ #if TIER_ONE
+ assert(opcode != INSTRUMENTED_CALL);
+ #endif
+ int total_args = oparg;
+ if (self_or_null != NULL) {
+ args--;
+ total_args++;
+ }
+ /* Callable is not a normal Python function */
+ res = PyObject_Vectorcall(
+ callable, args,
+ total_args | PY_VECTORCALL_ARGUMENTS_OFFSET,
+ NULL);
+ assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
+ Py_DECREF(callable);
+ for (int i = 0; i < total_args; i++) {
+ Py_DECREF(args[i]);
+ }
+ if (res == NULL) { stack_pointer += -2 - oparg; goto error; }
+ }
+ // _CHECK_PERIODIC
+ {
+ }
+ stack_pointer[-2 - oparg] = res;
+ stack_pointer += -1 - oparg;
+ CHECK_EVAL_BREAKER();
+ DISPATCH();
+ }
+
TARGET(CALL_PY_EXACT_ARGS) {
_Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr;
next_instr += 4;
@@ -1786,50 +1927,76 @@
DISPATCH();
}
- TARGET(CALL_PY_WITH_DEFAULTS) {
+ TARGET(CALL_PY_GENERAL) {
_Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr;
next_instr += 4;
- INSTRUCTION_STATS(CALL_PY_WITH_DEFAULTS);
+ INSTRUCTION_STATS(CALL_PY_GENERAL);
static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size");
+ PyObject *callable;
PyObject **args;
PyObject *self_or_null;
- PyObject *callable;
+ _PyInterpreterFrame *new_frame;
/* Skip 1 cache entry */
+ // _CHECK_PEP_523
+ {
+ DEOPT_IF(tstate->interp->eval_frame, CALL);
+ }
+ // _CHECK_FUNCTION_VERSION
+ callable = stack_pointer[-2 - oparg];
+ {
+ uint32_t func_version = read_u32(&this_instr[2].cache);
+ DEOPT_IF(!PyFunction_Check(callable), CALL);
+ PyFunctionObject *func = (PyFunctionObject *)callable;
+ DEOPT_IF(func->func_version != func_version, CALL);
+ }
+ // _PY_FRAME_GENERAL
args = &stack_pointer[-oparg];
self_or_null = stack_pointer[-1 - oparg];
- callable = stack_pointer[-2 - oparg];
- uint32_t func_version = read_u32(&this_instr[2].cache);
- DEOPT_IF(tstate->interp->eval_frame, CALL);
- int argcount = oparg;
- if (self_or_null != NULL) {
- args--;
- argcount++;
- }
- DEOPT_IF(!PyFunction_Check(callable), CALL);
- PyFunctionObject *func = (PyFunctionObject *)callable;
- DEOPT_IF(func->func_version != func_version, CALL);
- PyCodeObject *code = (PyCodeObject *)func->func_code;
- assert(func->func_defaults);
- assert(PyTuple_CheckExact(func->func_defaults));
- int defcount = (int)PyTuple_GET_SIZE(func->func_defaults);
- assert(defcount <= code->co_argcount);
- int min_args = code->co_argcount - defcount;
- DEOPT_IF(argcount > code->co_argcount, CALL);
- DEOPT_IF(argcount < min_args, CALL);
- DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), CALL);
- STAT_INC(CALL, hit);
- _PyInterpreterFrame *new_frame = _PyFrame_PushUnchecked(tstate, func, code->co_argcount);
- for (int i = 0; i < argcount; i++) {
- new_frame->localsplus[i] = args[i];
+ {
+ // oparg counts all of the args, but *not* self:
+ int total_args = oparg;
+ if (self_or_null != NULL) {
+ args--;
+ total_args++;
+ }
+ assert(Py_TYPE(callable) == &PyFunction_Type);
+ int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable))->co_flags;
+ PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable));
+ new_frame = _PyEvalFramePushAndInit(
+ tstate, (PyFunctionObject *)callable, locals,
+ args, total_args, NULL
+ );
+ // The frame has stolen all the arguments from the stack,
+ // so there is no need to clean them up.
+ stack_pointer += -2 - oparg;
+ if (new_frame == NULL) {
+ goto error;
+ }
}
- for (int i = argcount; i < code->co_argcount; i++) {
- PyObject *def = PyTuple_GET_ITEM(func->func_defaults, i - min_args);
- new_frame->localsplus[i] = Py_NewRef(def);
+ // _SAVE_RETURN_OFFSET
+ {
+ #if TIER_ONE
+ frame->return_offset = (uint16_t)(next_instr - this_instr);
+ #endif
+ #if TIER_TWO
+ frame->return_offset = oparg;
+ #endif
}
- // Manipulate stack and cache directly since we leave using DISPATCH_INLINED().
- STACK_SHRINK(oparg + 2);
- frame->return_offset = (uint16_t)(next_instr - this_instr);
- DISPATCH_INLINED(new_frame);
+ // _PUSH_FRAME
+ {
+ // Write it out explicitly because it's subtly different.
+ // Eventually this should be the only occurrence of this code.
+ assert(tstate->interp->eval_frame == NULL);
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ new_frame->previous = frame;
+ CALL_STAT_INC(inlined_py_calls);
+ frame = tstate->current_frame = new_frame;
+ tstate->py_recursion_remaining--;
+ LOAD_SP();
+ LOAD_IP(0);
+ LLTRACE_RESUME_FRAME();
+ }
+ DISPATCH();
}
TARGET(CALL_STR_1) {
diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h
index 4061ba3..fa4f1f8 100644
--- a/Python/opcode_targets.h
+++ b/Python/opcode_targets.h
@@ -163,6 +163,7 @@ static void *opcode_targets[256] = {
&&TARGET_BINARY_SUBSCR_TUPLE_INT,
&&TARGET_CALL_ALLOC_AND_ENTER_INIT,
&&TARGET_CALL_BOUND_METHOD_EXACT_ARGS,
+ &&TARGET_CALL_BOUND_METHOD_GENERAL,
&&TARGET_CALL_BUILTIN_CLASS,
&&TARGET_CALL_BUILTIN_FAST,
&&TARGET_CALL_BUILTIN_FAST_WITH_KEYWORDS,
@@ -174,8 +175,9 @@ static void *opcode_targets[256] = {
&&TARGET_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS,
&&TARGET_CALL_METHOD_DESCRIPTOR_NOARGS,
&&TARGET_CALL_METHOD_DESCRIPTOR_O,
+ &&TARGET_CALL_NON_PY_GENERAL,
&&TARGET_CALL_PY_EXACT_ARGS,
- &&TARGET_CALL_PY_WITH_DEFAULTS,
+ &&TARGET_CALL_PY_GENERAL,
&&TARGET_CALL_STR_1,
&&TARGET_CALL_TUPLE_1,
&&TARGET_CALL_TYPE_1,
@@ -233,8 +235,6 @@ static void *opcode_targets[256] = {
&&_unknown_opcode,
&&_unknown_opcode,
&&_unknown_opcode,
- &&_unknown_opcode,
- &&_unknown_opcode,
&&TARGET_INSTRUMENTED_RESUME,
&&TARGET_INSTRUMENTED_END_FOR,
&&TARGET_INSTRUMENTED_END_SEND,
diff --git a/Python/optimizer.c b/Python/optimizer.c
index c0e1be9..8be2c0f 100644
--- a/Python/optimizer.c
+++ b/Python/optimizer.c
@@ -987,6 +987,7 @@ static void make_exit(_PyUOpInstruction *inst, int opcode, int target)
{
inst->opcode = opcode;
inst->oparg = 0;
+ inst->operand = 0;
inst->format = UOP_FORMAT_TARGET;
inst->target = target;
}
diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c
index 6076328..928bc03 100644
--- a/Python/optimizer_bytecodes.c
+++ b/Python/optimizer_bytecodes.c
@@ -629,6 +629,15 @@ dummy_func(void) {
frame_new(ctx, co, localsplus_start, n_locals_already_filled, 0));
}
+ op(_PY_FRAME_GENERAL, (callable, self_or_null, args[oparg] -- new_frame: _Py_UOpsAbstractFrame *)) {
+ /* The _Py_UOpsAbstractFrame design assumes that we can copy arguments across directly */
+ (void)callable;
+ (void)self_or_null;
+ (void)args;
+ first_valid_check_stack = NULL;
+ goto done;
+ }
+
op(_POP_FRAME, (retval -- res)) {
SYNC_SP();
ctx->frame->stack_pointer = stack_pointer;
@@ -718,7 +727,7 @@ dummy_func(void) {
if (first_valid_check_stack == NULL) {
first_valid_check_stack = corresponding_check_stack;
}
- else {
+ else if (corresponding_check_stack) {
// delete all but the first valid _CHECK_STACK_SPACE
corresponding_check_stack->opcode = _NOP;
}
diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h
index b602d66..2a4efd7 100644
--- a/Python/optimizer_cases.c.h
+++ b/Python/optimizer_cases.c.h
@@ -1559,6 +1559,58 @@
break;
}
+ case _PY_FRAME_GENERAL: {
+ _Py_UopsSymbol **args;
+ _Py_UopsSymbol *self_or_null;
+ _Py_UopsSymbol *callable;
+ _Py_UOpsAbstractFrame *new_frame;
+ args = &stack_pointer[-oparg];
+ self_or_null = stack_pointer[-1 - oparg];
+ callable = stack_pointer[-2 - oparg];
+ /* The _Py_UOpsAbstractFrame design assumes that we can copy arguments across directly */
+ (void)callable;
+ (void)self_or_null;
+ (void)args;
+ first_valid_check_stack = NULL;
+ goto done;
+ stack_pointer[-2 - oparg] = (_Py_UopsSymbol *)new_frame;
+ stack_pointer += -1 - oparg;
+ break;
+ }
+
+ case _CHECK_FUNCTION_VERSION: {
+ break;
+ }
+
+ case _CHECK_METHOD_VERSION: {
+ break;
+ }
+
+ case _EXPAND_METHOD: {
+ _Py_UopsSymbol *method;
+ _Py_UopsSymbol *self;
+ method = sym_new_not_null(ctx);
+ if (method == NULL) goto out_of_space;
+ self = sym_new_not_null(ctx);
+ if (self == NULL) goto out_of_space;
+ stack_pointer[-2 - oparg] = method;
+ stack_pointer[-1 - oparg] = self;
+ break;
+ }
+
+ case _CHECK_IS_NOT_PY_CALLABLE: {
+ break;
+ }
+
+ case _CALL_NON_PY_GENERAL: {
+ _Py_UopsSymbol *res;
+ res = sym_new_not_null(ctx);
+ if (res == NULL) goto out_of_space;
+ stack_pointer[-2 - oparg] = res;
+ stack_pointer += -1 - oparg;
+ break;
+ }
+
case _CHECK_CALL_BOUND_METHOD_EXACT_ARGS: {
_Py_UopsSymbol *null;
_Py_UopsSymbol *callable;
@@ -1692,7 +1744,7 @@
if (first_valid_check_stack == NULL) {
first_valid_check_stack = corresponding_check_stack;
}
- else {
+ else if (corresponding_check_stack) {
// delete all but the first valid _CHECK_STACK_SPACE
corresponding_check_stack->opcode = _NOP;
}
@@ -1700,8 +1752,6 @@
break;
}
- /* _CALL_PY_WITH_DEFAULTS is not a viable micro-op for tier 2 */
-
case _CALL_TYPE_1: {
_Py_UopsSymbol *res;
res = sym_new_not_null(ctx);
diff --git a/Python/specialize.c b/Python/specialize.c
index 72114f2..9ac428c 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -1789,8 +1789,7 @@ specialize_class_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs)
return -1;
}
if (Py_TYPE(tp) != &PyType_Type) {
- SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_METACLASS);
- return -1;
+ goto generic;
}
if (tp->tp_new == PyBaseObject_Type.tp_new) {
PyFunctionObject *init = get_init_for_simple_managed_python_class(tp);
@@ -1807,58 +1806,11 @@ specialize_class_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs)
_Py_SET_OPCODE(*instr, CALL_ALLOC_AND_ENTER_INIT);
return 0;
}
- return -1;
- }
- SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_CLASS_MUTABLE);
- return -1;
-}
-
-#ifdef Py_STATS
-static int
-builtin_call_fail_kind(int ml_flags)
-{
- switch (ml_flags & (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O |
- METH_KEYWORDS | METH_METHOD)) {
- case METH_VARARGS:
- return SPEC_FAIL_CALL_CFUNC_VARARGS;
- case METH_VARARGS | METH_KEYWORDS:
- return SPEC_FAIL_CALL_CFUNC_VARARGS_KEYWORDS;
- case METH_NOARGS:
- return SPEC_FAIL_CALL_CFUNC_NOARGS;
- case METH_METHOD | METH_FASTCALL | METH_KEYWORDS:
- return SPEC_FAIL_CALL_CFUNC_METHOD_FASTCALL_KEYWORDS;
- /* These cases should be optimized, but return "other" just in case */
- case METH_O:
- case METH_FASTCALL:
- case METH_FASTCALL | METH_KEYWORDS:
- return SPEC_FAIL_OTHER;
- default:
- return SPEC_FAIL_CALL_BAD_CALL_FLAGS;
- }
-}
-
-static int
-meth_descr_call_fail_kind(int ml_flags)
-{
- switch (ml_flags & (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O |
- METH_KEYWORDS | METH_METHOD)) {
- case METH_VARARGS:
- return SPEC_FAIL_CALL_METH_DESCR_VARARGS;
- case METH_VARARGS | METH_KEYWORDS:
- return SPEC_FAIL_CALL_METH_DESCR_VARARGS_KEYWORDS;
- case METH_METHOD | METH_FASTCALL | METH_KEYWORDS:
- return SPEC_FAIL_CALL_METH_DESCR_METHOD_FASTCALL_KEYWORDS;
- /* These cases should be optimized, but return "other" just in case */
- case METH_NOARGS:
- case METH_O:
- case METH_FASTCALL:
- case METH_FASTCALL | METH_KEYWORDS:
- return SPEC_FAIL_OTHER;
- default:
- return SPEC_FAIL_CALL_BAD_CALL_FLAGS;
}
+generic:
+ instr->op.code = CALL_NON_PY_GENERAL;
+ return 0;
}
-#endif // Py_STATS
static int
specialize_method_descriptor(PyMethodDescrObject *descr, _Py_CODEUNIT *instr,
@@ -1901,8 +1853,8 @@ specialize_method_descriptor(PyMethodDescrObject *descr, _Py_CODEUNIT *instr,
return 0;
}
}
- SPECIALIZATION_FAIL(CALL, meth_descr_call_fail_kind(descr->d_method->ml_flags));
- return -1;
+ instr->op.code = CALL_NON_PY_GENERAL;
+ return 0;
}
static int
@@ -1917,36 +1869,25 @@ specialize_py_call(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs,
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PEP_523);
return -1;
}
- if (kind != SIMPLE_FUNCTION) {
- SPECIALIZATION_FAIL(CALL, kind);
+ int argcount = -1;
+ if (kind == SPEC_FAIL_CODE_NOT_OPTIMIZED) {
+ SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CODE_NOT_OPTIMIZED);
return -1;
}
- int argcount = code->co_argcount;
- int defcount = func->func_defaults == NULL ? 0 : (int)PyTuple_GET_SIZE(func->func_defaults);
- int min_args = argcount-defcount;
- // GH-105840: min_args is negative when somebody sets too many __defaults__!
- if (min_args < 0 || nargs > argcount || nargs < min_args) {
- SPECIALIZATION_FAIL(CALL, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
- return -1;
+ if (kind == SIMPLE_FUNCTION) {
+ argcount = code->co_argcount;
}
- assert(nargs <= argcount && nargs >= min_args);
- assert(min_args >= 0 && defcount >= 0);
- assert(defcount == 0 || func->func_defaults != NULL);
int version = _PyFunction_GetVersionForCurrentState(func);
if (version == 0) {
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OUT_OF_VERSIONS);
return -1;
}
write_u32(cache->func_version, version);
- if (argcount == nargs) {
+ if (argcount == nargs + bound_method) {
instr->op.code = bound_method ? CALL_BOUND_METHOD_EXACT_ARGS : CALL_PY_EXACT_ARGS;
}
- else if (bound_method) {
- SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_BOUND_METHOD);
- return -1;
- }
else {
- instr->op.code = CALL_PY_WITH_DEFAULTS;
+ instr->op.code = bound_method ? CALL_BOUND_METHOD_GENERAL : CALL_PY_GENERAL;
}
return 0;
}
@@ -1955,6 +1896,7 @@ static int
specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs)
{
if (PyCFunction_GET_FUNCTION(callable) == NULL) {
+ SPECIALIZATION_FAIL(CALL, SPEC_FAIL_OTHER);
return 1;
}
switch (PyCFunction_GET_FLAGS(callable) &
@@ -1991,38 +1933,10 @@ specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs)
return 0;
}
default:
- SPECIALIZATION_FAIL(CALL,
- builtin_call_fail_kind(PyCFunction_GET_FLAGS(callable)));
- return 1;
- }
-}
-
-#ifdef Py_STATS
-static int
-call_fail_kind(PyObject *callable)
-{
- assert(!PyCFunction_CheckExact(callable));
- assert(!PyFunction_Check(callable));
- assert(!PyType_Check(callable));
- assert(!Py_IS_TYPE(callable, &PyMethodDescr_Type));
- assert(!PyMethod_Check(callable));
- if (PyInstanceMethod_Check(callable)) {
- return SPEC_FAIL_CALL_INSTANCE_METHOD;
- }
- // builtin method
- else if (PyCMethod_Check(callable)) {
- return SPEC_FAIL_CALL_CMETHOD;
- }
- else if (Py_TYPE(callable) == &PyWrapperDescr_Type) {
- return SPEC_FAIL_CALL_OPERATOR_WRAPPER;
- }
- else if (Py_TYPE(callable) == &_PyMethodWrapper_Type) {
- return SPEC_FAIL_CALL_METHOD_WRAPPER;
+ instr->op.code = CALL_NON_PY_GENERAL;
+ return 0;
}
- return SPEC_FAIL_OTHER;
}
-#endif // Py_STATS
-
void
_Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr, int nargs)
@@ -2047,7 +1961,7 @@ _Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr, int nargs)
else if (PyMethod_Check(callable)) {
PyObject *func = ((PyMethodObject *)callable)->im_func;
if (PyFunction_Check(func)) {
- fail = specialize_py_call((PyFunctionObject *)func, instr, nargs+1, true);
+ fail = specialize_py_call((PyFunctionObject *)func, instr, nargs, true);
}
else {
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_BOUND_METHOD);
@@ -2055,8 +1969,8 @@ _Py_Specialize_Call(PyObject *callable, _Py_CODEUNIT *instr, int nargs)
}
}
else {
- SPECIALIZATION_FAIL(CALL, call_fail_kind(callable));
- fail = -1;
+ instr->op.code = CALL_NON_PY_GENERAL;
+ fail = 0;
}
if (fail) {
STAT_INC(CALL, failure);