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
This commit is contained in:
Mark Shannon 2024-05-04 12:11:11 +01:00 committed by GitHub
parent 00da0afa0d
commit 1ab6356ebe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 862 additions and 447 deletions

View 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

View 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: \

View 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
}

View 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:

116
Include/opcode_ids.h generated
View 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

120
Lib/_opcode_metadata.py generated
View 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 = {

View 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!

View 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)

View 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):

View 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')

View 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);

View 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]);
}

View File

@ -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;

View File

@ -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++;
{
// 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;
}
}
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];
// _SAVE_RETURN_OFFSET
{
#if TIER_ONE
frame->return_offset = (uint16_t)(next_instr - this_instr);
#endif
#if TIER_TWO
frame->return_offset = oparg;
#endif
}
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);
// _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();
}
// 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);
DISPATCH();
}
TARGET(CALL_STR_1) {

View 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,

View 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;
}

View 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;
}

View File

@ -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);

View 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,59 +1806,12 @@ 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;
generic:
instr->op.code = CALL_NON_PY_GENERAL;
return 0;
}
#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;
}
}
#endif // Py_STATS
static int
specialize_method_descriptor(PyMethodDescrObject *descr, _Py_CODEUNIT *instr,
int nargs)
@ -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,39 +1933,11 @@ 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;
instr->op.code = CALL_NON_PY_GENERAL;
return 0;
}
}
#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;
}
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);