]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-118095: Use broader specializations of CALL in tier 1, for better tier 2 support...
authorMark Shannon <mark@hotpy.org>
Sat, 4 May 2024 11:11:11 +0000 (12:11 +0100)
committerGitHub <noreply@github.com>
Sat, 4 May 2024 11:11:11 +0000 (12:11 +0100)
* 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

19 files changed:
Include/internal/pycore_frame.h
Include/internal/pycore_opcode_metadata.h
Include/internal/pycore_uop_ids.h
Include/internal/pycore_uop_metadata.h
Include/opcode_ids.h
Lib/_opcode_metadata.py
Lib/test/test_call.py
Lib/test/test_dis.py
Lib/test/test_dynamic.py
Lib/test/test_glob.py
Python/bytecodes.c
Python/ceval.c
Python/executor_cases.c.h
Python/generated_cases.c.h
Python/opcode_targets.h
Python/optimizer.c
Python/optimizer_bytecodes.c
Python/optimizer_cases.c.h
Python/specialize.c

index 37ae5ae850389b3021c362e8abeb156901c179ee..e13fdd9bb2e01ccccbc3661ba790547de4f37ecc 100644 (file)
@@ -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
index d10224c70f82f51d228056d5acebdd89cd13133d..2a237bc6dd8ee536d455da5626a3a6ed463cf521 100644 (file)
@@ -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: \
index 988464bcc210c8988d161b32c36cb9a4b6e00876..1e6ef8e54a221ac7a535fc83048e0806367e9836 100644 (file)
@@ -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
 }
index 475924dcd9c6b837abb8075fec8ab0d99884eef4..470e95e2b3b041584e199c4044db67c8e3d3fdba 100644 (file)
@@ -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:
index 185205c6870edcc5454755ffac30964e01720b1e..647f7c0ecb1ec83a84c4db190338ac3e60f818d1 100644 (file)
@@ -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
index b5bafe6302bc9ea6c57c976cbac7f87298445a8a..b3d7b8103e86c4bea6e314957b8d173e8e68fa27 100644 (file)
@@ -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 = {
index d3f4d6c29c553675d62fc7d0db8fd70c53bef5ea..7ea27929138da3c424aec976e0a97b4f4b85be02 100644 (file)
@@ -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!
 
 
index 747a73829fa70582d41b42eea4a18ba4eabe1bff..b68ed3baadc652e5a78b77ca2f2a544e1fdb313a 100644 (file)
@@ -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)
 
index 0aa3be6a1bde6ae6b050ee1daccb49d8bd663897..21bece26b893c66766372a2207f957b0e28e648e 100644 (file)
@@ -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):
index 70ee35ed2850bc0c82d14c40400f0012702e3daa..b72640bd871ba6562c754cdc14a50f4cdbd3047b 100644 (file)
@@ -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')
index ddada96bea71b8ca61625088f8e1397fbda1a69a..b2a0dc030e20cc7aecd68f8e25414d6d4cc8d53e 100644 (file)
@@ -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);
index 118746909902f3b546b5b813abc1018c262059b3..3626ffbd02ff401c9115a132632dcef6716710a1 100644 (file)
@@ -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]);
     }
index d0b794c61ef4a823933045dd11b57dce50696723..5f15f67324292b6f300109d91e2be609632a9b6d 100644 (file)
             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;
             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;
index 800d19229e3d6a5c90af74365ef206d2be3c24ba..87098b0506522f0528df56ffe513acc35a725801 100644 (file)
             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;
             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;
             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) {
index 4061ba33cea53ea5dff41e95ee7065fbfad38355..fa4f1f8cbb475a0fccb598ec23446eb0bf9bb234 100644 (file)
@@ -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,
index c0e1be96353d3fb9f164666e747d156bd773ebd3..8be2c0ffbd78e91fe5c4385a0e0693f36d1c80f7 100644 (file)
@@ -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;
 }
index 60763286178c71d7765d7d69e4d060cc6108908f..928bc03382b8fbcba36c134846ffceae57de977e 100644 (file)
@@ -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;
         }
index b602d663b08ba6cc030719a23106932151375381..2a4efd73d794df5fed8dcb9f06c20385ad7a8615 100644 (file)
             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;
             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;
             }
             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);
index 72114f27f69c52a4066e0c76a9c813116114990e..9ac428c3593f563c1d2e5cc4b553b63a2f5fa615 100644 (file)
@@ -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);