GH-128563: Generate opcode = ... in instructions that need opcode (GH-129608)

* Remove support for GO_TO_INSTRUCTION
This commit is contained in:
Mark Shannon 2025-02-03 15:09:21 +00:00 committed by GitHub
parent 808071b994
commit 75b628adeb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 558 additions and 172 deletions

View file

@ -226,9 +226,9 @@ int _PyOpcode_num_popped(int opcode, int oparg) {
case INSTRUMENTED_CALL: case INSTRUMENTED_CALL:
return 2 + oparg; return 2 + oparg;
case INSTRUMENTED_CALL_FUNCTION_EX: case INSTRUMENTED_CALL_FUNCTION_EX:
return 0; return 4;
case INSTRUMENTED_CALL_KW: case INSTRUMENTED_CALL_KW:
return 0; return 3 + oparg;
case INSTRUMENTED_END_FOR: case INSTRUMENTED_END_FOR:
return 2; return 2;
case INSTRUMENTED_END_SEND: case INSTRUMENTED_END_SEND:
@ -244,7 +244,7 @@ int _PyOpcode_num_popped(int opcode, int oparg) {
case INSTRUMENTED_LINE: case INSTRUMENTED_LINE:
return 0; return 0;
case INSTRUMENTED_LOAD_SUPER_ATTR: case INSTRUMENTED_LOAD_SUPER_ATTR:
return 0; return 3;
case INSTRUMENTED_NOT_TAKEN: case INSTRUMENTED_NOT_TAKEN:
return 0; return 0;
case INSTRUMENTED_POP_ITER: case INSTRUMENTED_POP_ITER:
@ -701,9 +701,9 @@ int _PyOpcode_num_pushed(int opcode, int oparg) {
case INSTRUMENTED_CALL: case INSTRUMENTED_CALL:
return 1; return 1;
case INSTRUMENTED_CALL_FUNCTION_EX: case INSTRUMENTED_CALL_FUNCTION_EX:
return 0; return 1;
case INSTRUMENTED_CALL_KW: case INSTRUMENTED_CALL_KW:
return 0; return 1;
case INSTRUMENTED_END_FOR: case INSTRUMENTED_END_FOR:
return 1; return 1;
case INSTRUMENTED_END_SEND: case INSTRUMENTED_END_SEND:
@ -719,7 +719,7 @@ int _PyOpcode_num_pushed(int opcode, int oparg) {
case INSTRUMENTED_LINE: case INSTRUMENTED_LINE:
return 0; return 0;
case INSTRUMENTED_LOAD_SUPER_ATTR: case INSTRUMENTED_LOAD_SUPER_ATTR:
return 0; return 1 + (oparg & 1);
case INSTRUMENTED_NOT_TAKEN: case INSTRUMENTED_NOT_TAKEN:
return 0; return 0;
case INSTRUMENTED_POP_ITER: case INSTRUMENTED_POP_ITER:
@ -1388,7 +1388,7 @@ int _PyOpcode_max_stack_effect(int opcode, int oparg, int *effect) {
return 0; return 0;
} }
case INSTRUMENTED_CALL_KW: { case INSTRUMENTED_CALL_KW: {
*effect = 0; *effect = Py_MAX(0, -2 - oparg);
return 0; return 0;
} }
case INSTRUMENTED_END_FOR: { case INSTRUMENTED_END_FOR: {
@ -1420,7 +1420,7 @@ int _PyOpcode_max_stack_effect(int opcode, int oparg, int *effect) {
return 0; return 0;
} }
case INSTRUMENTED_LOAD_SUPER_ATTR: { case INSTRUMENTED_LOAD_SUPER_ATTR: {
*effect = 0; *effect = Py_MAX(-2, -2 + (oparg & 1));
return 0; return 0;
} }
case INSTRUMENTED_NOT_TAKEN: { case INSTRUMENTED_NOT_TAKEN: {
@ -2104,8 +2104,8 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[266] = {
[IMPORT_FROM] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [IMPORT_FROM] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[IMPORT_NAME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [IMPORT_NAME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[INSTRUMENTED_CALL] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [INSTRUMENTED_CALL] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
[INSTRUMENTED_CALL_FUNCTION_EX] = { true, INSTR_FMT_IX, 0 }, [INSTRUMENTED_CALL_FUNCTION_EX] = { true, INSTR_FMT_IX, HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
[INSTRUMENTED_CALL_KW] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [INSTRUMENTED_CALL_KW] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
[INSTRUMENTED_END_FOR] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_NO_SAVE_IP_FLAG }, [INSTRUMENTED_END_FOR] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_NO_SAVE_IP_FLAG },
[INSTRUMENTED_END_SEND] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [INSTRUMENTED_END_SEND] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
[INSTRUMENTED_FOR_ITER] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [INSTRUMENTED_FOR_ITER] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
@ -2113,7 +2113,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[266] = {
[INSTRUMENTED_JUMP_BACKWARD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [INSTRUMENTED_JUMP_BACKWARD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[INSTRUMENTED_JUMP_FORWARD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, [INSTRUMENTED_JUMP_FORWARD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
[INSTRUMENTED_LINE] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG }, [INSTRUMENTED_LINE] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG },
[INSTRUMENTED_LOAD_SUPER_ATTR] = { true, INSTR_FMT_IXC, 0 }, [INSTRUMENTED_LOAD_SUPER_ATTR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
[INSTRUMENTED_NOT_TAKEN] = { true, INSTR_FMT_IX, 0 }, [INSTRUMENTED_NOT_TAKEN] = { true, INSTR_FMT_IX, 0 },
[INSTRUMENTED_POP_ITER] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG }, [INSTRUMENTED_POP_ITER] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG },
[INSTRUMENTED_POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG }, [INSTRUMENTED_POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG },

View file

@ -152,13 +152,10 @@ extern "C" {
#define _INIT_CALL_PY_EXACT_ARGS_2 396 #define _INIT_CALL_PY_EXACT_ARGS_2 396
#define _INIT_CALL_PY_EXACT_ARGS_3 397 #define _INIT_CALL_PY_EXACT_ARGS_3 397
#define _INIT_CALL_PY_EXACT_ARGS_4 398 #define _INIT_CALL_PY_EXACT_ARGS_4 398
#define _INSTRUMENTED_CALL_FUNCTION_EX INSTRUMENTED_CALL_FUNCTION_EX
#define _INSTRUMENTED_CALL_KW INSTRUMENTED_CALL_KW
#define _INSTRUMENTED_FOR_ITER INSTRUMENTED_FOR_ITER #define _INSTRUMENTED_FOR_ITER INSTRUMENTED_FOR_ITER
#define _INSTRUMENTED_INSTRUCTION INSTRUMENTED_INSTRUCTION #define _INSTRUMENTED_INSTRUCTION INSTRUMENTED_INSTRUCTION
#define _INSTRUMENTED_JUMP_FORWARD INSTRUMENTED_JUMP_FORWARD #define _INSTRUMENTED_JUMP_FORWARD INSTRUMENTED_JUMP_FORWARD
#define _INSTRUMENTED_LINE INSTRUMENTED_LINE #define _INSTRUMENTED_LINE INSTRUMENTED_LINE
#define _INSTRUMENTED_LOAD_SUPER_ATTR INSTRUMENTED_LOAD_SUPER_ATTR
#define _INSTRUMENTED_NOT_TAKEN INSTRUMENTED_NOT_TAKEN #define _INSTRUMENTED_NOT_TAKEN INSTRUMENTED_NOT_TAKEN
#define _INSTRUMENTED_POP_JUMP_IF_FALSE INSTRUMENTED_POP_JUMP_IF_FALSE #define _INSTRUMENTED_POP_JUMP_IF_FALSE INSTRUMENTED_POP_JUMP_IF_FALSE
#define _INSTRUMENTED_POP_JUMP_IF_NONE INSTRUMENTED_POP_JUMP_IF_NONE #define _INSTRUMENTED_POP_JUMP_IF_NONE INSTRUMENTED_POP_JUMP_IF_NONE
@ -242,58 +239,59 @@ extern "C" {
#define _MAYBE_EXPAND_METHOD 447 #define _MAYBE_EXPAND_METHOD 447
#define _MAYBE_EXPAND_METHOD_KW 448 #define _MAYBE_EXPAND_METHOD_KW 448
#define _MONITOR_CALL 449 #define _MONITOR_CALL 449
#define _MONITOR_JUMP_BACKWARD 450 #define _MONITOR_CALL_KW 450
#define _MONITOR_RESUME 451 #define _MONITOR_JUMP_BACKWARD 451
#define _MONITOR_RESUME 452
#define _NOP NOP #define _NOP NOP
#define _POP_EXCEPT POP_EXCEPT #define _POP_EXCEPT POP_EXCEPT
#define _POP_JUMP_IF_FALSE 452 #define _POP_JUMP_IF_FALSE 453
#define _POP_JUMP_IF_TRUE 453 #define _POP_JUMP_IF_TRUE 454
#define _POP_TOP POP_TOP #define _POP_TOP POP_TOP
#define _POP_TOP_LOAD_CONST_INLINE_BORROW 454 #define _POP_TOP_LOAD_CONST_INLINE_BORROW 455
#define _PUSH_EXC_INFO PUSH_EXC_INFO #define _PUSH_EXC_INFO PUSH_EXC_INFO
#define _PUSH_FRAME 455 #define _PUSH_FRAME 456
#define _PUSH_NULL PUSH_NULL #define _PUSH_NULL PUSH_NULL
#define _PUSH_NULL_CONDITIONAL 456 #define _PUSH_NULL_CONDITIONAL 457
#define _PY_FRAME_GENERAL 457 #define _PY_FRAME_GENERAL 458
#define _PY_FRAME_KW 458 #define _PY_FRAME_KW 459
#define _QUICKEN_RESUME 459 #define _QUICKEN_RESUME 460
#define _REPLACE_WITH_TRUE 460 #define _REPLACE_WITH_TRUE 461
#define _RESUME_CHECK RESUME_CHECK #define _RESUME_CHECK RESUME_CHECK
#define _RETURN_GENERATOR RETURN_GENERATOR #define _RETURN_GENERATOR RETURN_GENERATOR
#define _RETURN_VALUE RETURN_VALUE #define _RETURN_VALUE RETURN_VALUE
#define _SAVE_RETURN_OFFSET 461 #define _SAVE_RETURN_OFFSET 462
#define _SEND 462 #define _SEND 463
#define _SEND_GEN_FRAME 463 #define _SEND_GEN_FRAME 464
#define _SETUP_ANNOTATIONS SETUP_ANNOTATIONS #define _SETUP_ANNOTATIONS SETUP_ANNOTATIONS
#define _SET_ADD SET_ADD #define _SET_ADD SET_ADD
#define _SET_FUNCTION_ATTRIBUTE SET_FUNCTION_ATTRIBUTE #define _SET_FUNCTION_ATTRIBUTE SET_FUNCTION_ATTRIBUTE
#define _SET_UPDATE SET_UPDATE #define _SET_UPDATE SET_UPDATE
#define _START_EXECUTOR 464 #define _START_EXECUTOR 465
#define _STORE_ATTR 465 #define _STORE_ATTR 466
#define _STORE_ATTR_INSTANCE_VALUE 466 #define _STORE_ATTR_INSTANCE_VALUE 467
#define _STORE_ATTR_SLOT 467 #define _STORE_ATTR_SLOT 468
#define _STORE_ATTR_WITH_HINT 468 #define _STORE_ATTR_WITH_HINT 469
#define _STORE_DEREF STORE_DEREF #define _STORE_DEREF STORE_DEREF
#define _STORE_FAST 469 #define _STORE_FAST 470
#define _STORE_FAST_0 470 #define _STORE_FAST_0 471
#define _STORE_FAST_1 471 #define _STORE_FAST_1 472
#define _STORE_FAST_2 472 #define _STORE_FAST_2 473
#define _STORE_FAST_3 473 #define _STORE_FAST_3 474
#define _STORE_FAST_4 474 #define _STORE_FAST_4 475
#define _STORE_FAST_5 475 #define _STORE_FAST_5 476
#define _STORE_FAST_6 476 #define _STORE_FAST_6 477
#define _STORE_FAST_7 477 #define _STORE_FAST_7 478
#define _STORE_FAST_LOAD_FAST STORE_FAST_LOAD_FAST #define _STORE_FAST_LOAD_FAST STORE_FAST_LOAD_FAST
#define _STORE_FAST_STORE_FAST STORE_FAST_STORE_FAST #define _STORE_FAST_STORE_FAST STORE_FAST_STORE_FAST
#define _STORE_GLOBAL STORE_GLOBAL #define _STORE_GLOBAL STORE_GLOBAL
#define _STORE_NAME STORE_NAME #define _STORE_NAME STORE_NAME
#define _STORE_SLICE 478 #define _STORE_SLICE 479
#define _STORE_SUBSCR 479 #define _STORE_SUBSCR 480
#define _STORE_SUBSCR_DICT STORE_SUBSCR_DICT #define _STORE_SUBSCR_DICT STORE_SUBSCR_DICT
#define _STORE_SUBSCR_LIST_INT STORE_SUBSCR_LIST_INT #define _STORE_SUBSCR_LIST_INT STORE_SUBSCR_LIST_INT
#define _SWAP SWAP #define _SWAP SWAP
#define _TIER2_RESUME_CHECK 480 #define _TIER2_RESUME_CHECK 481
#define _TO_BOOL 481 #define _TO_BOOL 482
#define _TO_BOOL_BOOL TO_BOOL_BOOL #define _TO_BOOL_BOOL TO_BOOL_BOOL
#define _TO_BOOL_INT TO_BOOL_INT #define _TO_BOOL_INT TO_BOOL_INT
#define _TO_BOOL_LIST TO_BOOL_LIST #define _TO_BOOL_LIST TO_BOOL_LIST
@ -303,13 +301,13 @@ extern "C" {
#define _UNARY_NEGATIVE UNARY_NEGATIVE #define _UNARY_NEGATIVE UNARY_NEGATIVE
#define _UNARY_NOT UNARY_NOT #define _UNARY_NOT UNARY_NOT
#define _UNPACK_EX UNPACK_EX #define _UNPACK_EX UNPACK_EX
#define _UNPACK_SEQUENCE 482 #define _UNPACK_SEQUENCE 483
#define _UNPACK_SEQUENCE_LIST UNPACK_SEQUENCE_LIST #define _UNPACK_SEQUENCE_LIST UNPACK_SEQUENCE_LIST
#define _UNPACK_SEQUENCE_TUPLE UNPACK_SEQUENCE_TUPLE #define _UNPACK_SEQUENCE_TUPLE UNPACK_SEQUENCE_TUPLE
#define _UNPACK_SEQUENCE_TWO_TUPLE UNPACK_SEQUENCE_TWO_TUPLE #define _UNPACK_SEQUENCE_TWO_TUPLE UNPACK_SEQUENCE_TWO_TUPLE
#define _WITH_EXCEPT_START WITH_EXCEPT_START #define _WITH_EXCEPT_START WITH_EXCEPT_START
#define _YIELD_VALUE YIELD_VALUE #define _YIELD_VALUE YIELD_VALUE
#define MAX_UOP_ID 482 #define MAX_UOP_ID 483
#ifdef __cplusplus #ifdef __cplusplus
} }

30
Include/opcode_ids.h generated
View file

@ -214,21 +214,21 @@ extern "C" {
#define INSTRUMENTED_END_FOR 235 #define INSTRUMENTED_END_FOR 235
#define INSTRUMENTED_POP_ITER 236 #define INSTRUMENTED_POP_ITER 236
#define INSTRUMENTED_END_SEND 237 #define INSTRUMENTED_END_SEND 237
#define INSTRUMENTED_LOAD_SUPER_ATTR 238 #define INSTRUMENTED_FOR_ITER 238
#define INSTRUMENTED_FOR_ITER 239 #define INSTRUMENTED_INSTRUCTION 239
#define INSTRUMENTED_CALL_KW 240 #define INSTRUMENTED_JUMP_FORWARD 240
#define INSTRUMENTED_CALL_FUNCTION_EX 241 #define INSTRUMENTED_NOT_TAKEN 241
#define INSTRUMENTED_INSTRUCTION 242 #define INSTRUMENTED_POP_JUMP_IF_TRUE 242
#define INSTRUMENTED_JUMP_FORWARD 243 #define INSTRUMENTED_POP_JUMP_IF_FALSE 243
#define INSTRUMENTED_NOT_TAKEN 244 #define INSTRUMENTED_POP_JUMP_IF_NONE 244
#define INSTRUMENTED_POP_JUMP_IF_TRUE 245 #define INSTRUMENTED_POP_JUMP_IF_NOT_NONE 245
#define INSTRUMENTED_POP_JUMP_IF_FALSE 246 #define INSTRUMENTED_RESUME 246
#define INSTRUMENTED_POP_JUMP_IF_NONE 247 #define INSTRUMENTED_RETURN_VALUE 247
#define INSTRUMENTED_POP_JUMP_IF_NOT_NONE 248 #define INSTRUMENTED_YIELD_VALUE 248
#define INSTRUMENTED_RESUME 249 #define INSTRUMENTED_LOAD_SUPER_ATTR 249
#define INSTRUMENTED_RETURN_VALUE 250 #define INSTRUMENTED_CALL 250
#define INSTRUMENTED_YIELD_VALUE 251 #define INSTRUMENTED_CALL_KW 251
#define INSTRUMENTED_CALL 252 #define INSTRUMENTED_CALL_FUNCTION_EX 252
#define INSTRUMENTED_JUMP_BACKWARD 253 #define INSTRUMENTED_JUMP_BACKWARD 253
#define INSTRUMENTED_LINE 254 #define INSTRUMENTED_LINE 254
#define ENTER_EXECUTOR 255 #define ENTER_EXECUTOR 255

View file

@ -334,21 +334,21 @@ opmap = {
'INSTRUMENTED_END_FOR': 235, 'INSTRUMENTED_END_FOR': 235,
'INSTRUMENTED_POP_ITER': 236, 'INSTRUMENTED_POP_ITER': 236,
'INSTRUMENTED_END_SEND': 237, 'INSTRUMENTED_END_SEND': 237,
'INSTRUMENTED_LOAD_SUPER_ATTR': 238, 'INSTRUMENTED_FOR_ITER': 238,
'INSTRUMENTED_FOR_ITER': 239, 'INSTRUMENTED_INSTRUCTION': 239,
'INSTRUMENTED_CALL_KW': 240, 'INSTRUMENTED_JUMP_FORWARD': 240,
'INSTRUMENTED_CALL_FUNCTION_EX': 241, 'INSTRUMENTED_NOT_TAKEN': 241,
'INSTRUMENTED_INSTRUCTION': 242, 'INSTRUMENTED_POP_JUMP_IF_TRUE': 242,
'INSTRUMENTED_JUMP_FORWARD': 243, 'INSTRUMENTED_POP_JUMP_IF_FALSE': 243,
'INSTRUMENTED_NOT_TAKEN': 244, 'INSTRUMENTED_POP_JUMP_IF_NONE': 244,
'INSTRUMENTED_POP_JUMP_IF_TRUE': 245, 'INSTRUMENTED_POP_JUMP_IF_NOT_NONE': 245,
'INSTRUMENTED_POP_JUMP_IF_FALSE': 246, 'INSTRUMENTED_RESUME': 246,
'INSTRUMENTED_POP_JUMP_IF_NONE': 247, 'INSTRUMENTED_RETURN_VALUE': 247,
'INSTRUMENTED_POP_JUMP_IF_NOT_NONE': 248, 'INSTRUMENTED_YIELD_VALUE': 248,
'INSTRUMENTED_RESUME': 249, 'INSTRUMENTED_LOAD_SUPER_ATTR': 249,
'INSTRUMENTED_RETURN_VALUE': 250, 'INSTRUMENTED_CALL': 250,
'INSTRUMENTED_YIELD_VALUE': 251, 'INSTRUMENTED_CALL_KW': 251,
'INSTRUMENTED_CALL': 252, 'INSTRUMENTED_CALL_FUNCTION_EX': 252,
'INSTRUMENTED_JUMP_BACKWARD': 253, 'INSTRUMENTED_JUMP_BACKWARD': 253,
'JUMP': 256, 'JUMP': 256,
'JUMP_IF_FALSE': 257, 'JUMP_IF_FALSE': 257,

View file

@ -45,7 +45,6 @@
#include "ceval_macros.h" #include "ceval_macros.h"
/* Flow control macros */ /* Flow control macros */
#define GO_TO_INSTRUCTION(instname) ((void)0)
#define inst(name, ...) case name: #define inst(name, ...) case name:
#define op(name, ...) /* NAME is ignored */ #define op(name, ...) /* NAME is ignored */
@ -2019,12 +2018,10 @@ dummy_func(
ERROR_IF(err != 0, error); ERROR_IF(err != 0, error);
} }
inst(INSTRUMENTED_LOAD_SUPER_ATTR, (unused/1 -- )) { macro(INSTRUMENTED_LOAD_SUPER_ATTR) =
// cancel out the decrement that will happen in LOAD_SUPER_ATTR; we counter/1 +
// don't want to specialize instrumented instructions _LOAD_SUPER_ATTR +
PAUSE_ADAPTIVE_COUNTER(this_instr[1].counter); _PUSH_NULL_CONDITIONAL;
GO_TO_INSTRUCTION(LOAD_SUPER_ATTR);
}
family(LOAD_SUPER_ATTR, INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR) = { family(LOAD_SUPER_ATTR, INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR) = {
LOAD_SUPER_ATTR_ATTR, LOAD_SUPER_ATTR_ATTR,
@ -2088,7 +2085,10 @@ dummy_func(
attr = PyStackRef_FromPyObjectSteal(attr_o); attr = PyStackRef_FromPyObjectSteal(attr_o);
} }
macro(LOAD_SUPER_ATTR) = _SPECIALIZE_LOAD_SUPER_ATTR + _LOAD_SUPER_ATTR + _PUSH_NULL_CONDITIONAL; macro(LOAD_SUPER_ATTR) =
_SPECIALIZE_LOAD_SUPER_ATTR +
_LOAD_SUPER_ATTR +
_PUSH_NULL_CONDITIONAL;
inst(LOAD_SUPER_ATTR_ATTR, (unused/1, global_super_st, class_st, self_st -- attr_st)) { inst(LOAD_SUPER_ATTR_ATTR, (unused/1, global_super_st, class_st, self_st -- attr_st)) {
PyObject *global_super = PyStackRef_AsPyObjectBorrow(global_super_st); PyObject *global_super = PyStackRef_AsPyObjectBorrow(global_super_st);
@ -4331,18 +4331,23 @@ dummy_func(
CALL_KW_NON_PY, CALL_KW_NON_PY,
}; };
inst(INSTRUMENTED_CALL_KW, (counter/1, version/2 -- )) { op(_MONITOR_CALL_KW, (callable[1], self_or_null[1], args[oparg], kwnames -- callable[1], self_or_null[1], args[oparg], kwnames)) {
int is_meth = !PyStackRef_IsNull(PEEK(oparg + 2)); int is_meth = !PyStackRef_IsNull(self_or_null[0]);
int total_args = oparg + is_meth; PyObject *arg;
PyObject *function = PyStackRef_AsPyObjectBorrow(PEEK(oparg + 3)); if (is_meth) {
PyObject *arg = total_args == 0 ? &_PyInstrumentation_MISSING arg = PyStackRef_AsPyObjectBorrow(self_or_null[0]);
: PyStackRef_AsPyObjectBorrow(PEEK(total_args + 1)); }
else if (args) {
arg = PyStackRef_AsPyObjectBorrow(args[0]);
}
else {
arg = &_PyInstrumentation_MISSING;
}
PyObject *function = PyStackRef_AsPyObjectBorrow(callable[0]);
int err = _Py_call_instrumentation_2args( int err = _Py_call_instrumentation_2args(
tstate, PY_MONITORING_EVENT_CALL, tstate, PY_MONITORING_EVENT_CALL,
frame, this_instr, function, arg); frame, this_instr, function, arg);
ERROR_IF(err, error); ERROR_IF(err, error);
PAUSE_ADAPTIVE_COUNTER(this_instr[1].counter);
GO_TO_INSTRUCTION(CALL_KW);
} }
op(_MAYBE_EXPAND_METHOD_KW, (callable[1], self_or_null[1], args[oparg], kwnames_in -- func[1], maybe_self[1], args[oparg], kwnames_out)) { op(_MAYBE_EXPAND_METHOD_KW, (callable[1], self_or_null[1], args[oparg], kwnames_in -- func[1], maybe_self[1], args[oparg], kwnames_out)) {
@ -4520,6 +4525,13 @@ dummy_func(
_MAYBE_EXPAND_METHOD_KW + _MAYBE_EXPAND_METHOD_KW +
_DO_CALL_KW; _DO_CALL_KW;
macro(INSTRUMENTED_CALL_KW) =
counter/1 +
unused/2 +
_MONITOR_CALL_KW +
_MAYBE_EXPAND_METHOD_KW +
_DO_CALL_KW;
op(_CHECK_IS_NOT_PY_CALLABLE_KW, (callable[1], unused[1], unused[oparg], kwnames -- callable[1], unused[1], unused[oparg], kwnames)) { op(_CHECK_IS_NOT_PY_CALLABLE_KW, (callable[1], unused[1], unused[oparg], kwnames -- callable[1], unused[1], unused[oparg], kwnames)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]); PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
EXIT_IF(PyFunction_Check(callable_o)); EXIT_IF(PyFunction_Check(callable_o));
@ -4566,10 +4578,6 @@ dummy_func(
_CALL_KW_NON_PY + _CALL_KW_NON_PY +
_CHECK_PERIODIC; _CHECK_PERIODIC;
inst(INSTRUMENTED_CALL_FUNCTION_EX, ( -- )) {
GO_TO_INSTRUCTION(CALL_FUNCTION_EX);
}
op(_MAKE_CALLARGS_A_TUPLE, (func, unused, callargs, kwargs_in -- func, unused, tuple, kwargs_out)) { op(_MAKE_CALLARGS_A_TUPLE, (func, unused, callargs, kwargs_in -- func, unused, tuple, kwargs_out)) {
PyObject *callargs_o = PyStackRef_AsPyObjectBorrow(callargs); PyObject *callargs_o = PyStackRef_AsPyObjectBorrow(callargs);
if (PyTuple_CheckExact(callargs_o)) { if (PyTuple_CheckExact(callargs_o)) {
@ -4678,6 +4686,10 @@ dummy_func(
_DO_CALL_FUNCTION_EX + _DO_CALL_FUNCTION_EX +
_CHECK_PERIODIC; _CHECK_PERIODIC;
macro(INSTRUMENTED_CALL_FUNCTION_EX) =
_MAKE_CALLARGS_A_TUPLE +
_DO_CALL_FUNCTION_EX +
_CHECK_PERIODIC;
inst(MAKE_FUNCTION, (codeobj_st -- func)) { inst(MAKE_FUNCTION, (codeobj_st -- func)) {
PyObject *codeobj = PyStackRef_AsPyObjectBorrow(codeobj_st); PyObject *codeobj = PyStackRef_AsPyObjectBorrow(codeobj_st);

View file

@ -2706,8 +2706,6 @@
break; break;
} }
/* _INSTRUMENTED_LOAD_SUPER_ATTR is not a viable micro-op for tier 2 because it is instrumented */
case _LOAD_SUPER_ATTR_ATTR: { case _LOAD_SUPER_ATTR_ATTR: {
_PyStackRef self_st; _PyStackRef self_st;
_PyStackRef class_st; _PyStackRef class_st;
@ -5665,7 +5663,7 @@
break; break;
} }
/* _INSTRUMENTED_CALL_KW is not a viable micro-op for tier 2 because it is instrumented */ /* _MONITOR_CALL_KW is not a viable micro-op for tier 2 because it uses the 'this_instr' variable */
case _MAYBE_EXPAND_METHOD_KW: { case _MAYBE_EXPAND_METHOD_KW: {
_PyStackRef kwnames_in; _PyStackRef kwnames_in;
@ -5896,8 +5894,6 @@
break; break;
} }
/* _INSTRUMENTED_CALL_FUNCTION_EX is not a viable micro-op for tier 2 because it is instrumented */
case _MAKE_CALLARGS_A_TUPLE: { case _MAKE_CALLARGS_A_TUPLE: {
_PyStackRef kwargs_in; _PyStackRef kwargs_in;
_PyStackRef callargs; _PyStackRef callargs;

View file

@ -966,6 +966,7 @@
PREDICTED_CALL:; PREDICTED_CALL:;
_Py_CODEUNIT* const this_instr = next_instr - 4; _Py_CODEUNIT* const this_instr = next_instr - 4;
(void)this_instr; (void)this_instr;
opcode = CALL;
_PyStackRef *callable; _PyStackRef *callable;
_PyStackRef *self_or_null; _PyStackRef *self_or_null;
_PyStackRef *args; _PyStackRef *args;
@ -1744,12 +1745,11 @@
} }
TARGET(CALL_FUNCTION_EX) { TARGET(CALL_FUNCTION_EX) {
frame->instr_ptr = next_instr; _Py_CODEUNIT* const this_instr = frame->instr_ptr = next_instr;
(void)this_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(CALL_FUNCTION_EX); INSTRUCTION_STATS(CALL_FUNCTION_EX);
PREDICTED_CALL_FUNCTION_EX:; opcode = CALL_FUNCTION_EX;
_Py_CODEUNIT* const this_instr = next_instr - 1;
(void)this_instr;
_PyStackRef func; _PyStackRef func;
_PyStackRef callargs; _PyStackRef callargs;
_PyStackRef kwargs_in; _PyStackRef kwargs_in;
@ -2030,6 +2030,7 @@
PREDICTED_CALL_KW:; PREDICTED_CALL_KW:;
_Py_CODEUNIT* const this_instr = next_instr - 4; _Py_CODEUNIT* const this_instr = next_instr - 4;
(void)this_instr; (void)this_instr;
opcode = CALL_KW;
_PyStackRef *callable; _PyStackRef *callable;
_PyStackRef *self_or_null; _PyStackRef *self_or_null;
_PyStackRef *args; _PyStackRef *args;
@ -2297,6 +2298,7 @@
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 4; next_instr += 4;
INSTRUCTION_STATS(CALL_KW_NON_PY); INSTRUCTION_STATS(CALL_KW_NON_PY);
opcode = CALL_KW_NON_PY;
static_assert(INLINE_CACHE_ENTRIES_CALL_KW == 3, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_CALL_KW == 3, "incorrect cache size");
_PyStackRef *callable; _PyStackRef *callable;
_PyStackRef kwnames; _PyStackRef kwnames;
@ -2914,6 +2916,7 @@
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 4; next_instr += 4;
INSTRUCTION_STATS(CALL_NON_PY_GENERAL); INSTRUCTION_STATS(CALL_NON_PY_GENERAL);
opcode = CALL_NON_PY_GENERAL;
static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size");
_PyStackRef *callable; _PyStackRef *callable;
_PyStackRef *self_or_null; _PyStackRef *self_or_null;
@ -4045,6 +4048,7 @@
(void)this_instr; (void)this_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(ENTER_EXECUTOR); INSTRUCTION_STATS(ENTER_EXECUTOR);
opcode = ENTER_EXECUTOR;
#ifdef _Py_TIER2 #ifdef _Py_TIER2
PyCodeObject *code = _PyFrame_GetCode(frame); PyCodeObject *code = _PyFrame_GetCode(frame);
_PyExecutorObject *executor = code->co_executors->executors[oparg & 255]; _PyExecutorObject *executor = code->co_executors->executors[oparg & 255];
@ -4097,6 +4101,7 @@
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(EXTENDED_ARG); INSTRUCTION_STATS(EXTENDED_ARG);
opcode = EXTENDED_ARG;
assert(oparg); assert(oparg);
opcode = next_instr->op.code; opcode = next_instr->op.code;
oparg = oparg << 8 | next_instr->op.arg; oparg = oparg << 8 | next_instr->op.arg;
@ -4646,6 +4651,7 @@
(void)this_instr; (void)this_instr;
next_instr += 4; next_instr += 4;
INSTRUCTION_STATS(INSTRUMENTED_CALL); INSTRUCTION_STATS(INSTRUMENTED_CALL);
opcode = INSTRUMENTED_CALL;
_PyStackRef *callable; _PyStackRef *callable;
_PyStackRef *self_or_null; _PyStackRef *self_or_null;
_PyStackRef *args; _PyStackRef *args;
@ -4815,11 +4821,188 @@
} }
TARGET(INSTRUMENTED_CALL_FUNCTION_EX) { TARGET(INSTRUMENTED_CALL_FUNCTION_EX) {
frame->instr_ptr = next_instr; _Py_CODEUNIT* const this_instr = frame->instr_ptr = next_instr;
(void)this_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(INSTRUMENTED_CALL_FUNCTION_EX); INSTRUCTION_STATS(INSTRUMENTED_CALL_FUNCTION_EX);
opcode = INSTRUMENTED_CALL_FUNCTION_EX;
goto PREDICTED_CALL_FUNCTION_EX; _PyStackRef func;
_PyStackRef callargs;
_PyStackRef kwargs_in;
_PyStackRef tuple;
_PyStackRef kwargs_out;
_PyStackRef func_st;
_PyStackRef null;
_PyStackRef callargs_st;
_PyStackRef kwargs_st;
_PyStackRef result;
// _MAKE_CALLARGS_A_TUPLE
{
kwargs_in = stack_pointer[-1];
callargs = stack_pointer[-2];
func = stack_pointer[-4];
PyObject *callargs_o = PyStackRef_AsPyObjectBorrow(callargs);
if (PyTuple_CheckExact(callargs_o)) {
tuple = callargs;
kwargs_out = kwargs_in;
}
else {
_PyFrame_SetStackPointer(frame, stack_pointer);
int err = _Py_Check_ArgsIterable(tstate, PyStackRef_AsPyObjectBorrow(func), callargs_o);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (err < 0) {
goto error;
}
_PyFrame_SetStackPointer(frame, stack_pointer);
PyObject *tuple_o = PySequence_Tuple(callargs_o);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (tuple_o == NULL) {
goto error;
}
kwargs_out = kwargs_in;
stack_pointer += -2;
assert(WITHIN_STACK_BOUNDS());
_PyFrame_SetStackPointer(frame, stack_pointer);
PyStackRef_CLOSE(callargs);
stack_pointer = _PyFrame_GetStackPointer(frame);
tuple = PyStackRef_FromPyObjectSteal(tuple_o);
stack_pointer += 2;
assert(WITHIN_STACK_BOUNDS());
}
}
// _DO_CALL_FUNCTION_EX
{
kwargs_st = kwargs_out;
callargs_st = tuple;
null = stack_pointer[-3];
func_st = func;
(void)null;
PyObject *func = PyStackRef_AsPyObjectBorrow(func_st);
// DICT_MERGE is called before this opcode if there are kwargs.
// It converts all dict subtypes in kwargs into regular dicts.
EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_FUNCTION_EX, func);
PyObject *result_o;
assert(!_PyErr_Occurred(tstate));
if (opcode == INSTRUMENTED_CALL_FUNCTION_EX) {
PyObject *callargs = PyStackRef_AsPyObjectBorrow(callargs_st);
PyObject *kwargs = PyStackRef_AsPyObjectBorrow(kwargs_st);
assert(kwargs == NULL || PyDict_CheckExact(kwargs));
assert(PyTuple_CheckExact(callargs));
PyObject *arg = PyTuple_GET_SIZE(callargs) > 0 ?
PyTuple_GET_ITEM(callargs, 0) : &_PyInstrumentation_MISSING;
stack_pointer[-2] = callargs_st;
stack_pointer[-1] = kwargs_st;
_PyFrame_SetStackPointer(frame, stack_pointer);
int err = _Py_call_instrumentation_2args(
tstate, PY_MONITORING_EVENT_CALL,
frame, this_instr, func, arg);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (err) {
goto error;
}
_PyFrame_SetStackPointer(frame, stack_pointer);
result_o = PyObject_Call(func, callargs, kwargs);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (!PyFunction_Check(func) && !PyMethod_Check(func)) {
if (result_o == NULL) {
_PyFrame_SetStackPointer(frame, stack_pointer);
_Py_call_instrumentation_exc2(
tstate, PY_MONITORING_EVENT_C_RAISE,
frame, this_instr, func, arg);
stack_pointer = _PyFrame_GetStackPointer(frame);
}
else {
_PyFrame_SetStackPointer(frame, stack_pointer);
int err = _Py_call_instrumentation_2args(
tstate, PY_MONITORING_EVENT_C_RETURN,
frame, this_instr, func, arg);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (err < 0) {
Py_CLEAR(result_o);
}
}
}
}
else {
if (Py_TYPE(func) == &PyFunction_Type &&
tstate->interp->eval_frame == NULL &&
((PyFunctionObject *)func)->vectorcall == _PyFunction_Vectorcall) {
PyObject *callargs = PyStackRef_AsPyObjectSteal(callargs_st);
assert(PyTuple_CheckExact(callargs));
PyObject *kwargs = PyStackRef_IsNull(kwargs_st) ? NULL : PyStackRef_AsPyObjectSteal(kwargs_st);
assert(kwargs == NULL || PyDict_CheckExact(kwargs));
Py_ssize_t nargs = PyTuple_GET_SIZE(callargs);
int code_flags = ((PyCodeObject *)PyFunction_GET_CODE(func))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(func));
stack_pointer += -2;
assert(WITHIN_STACK_BOUNDS());
_PyFrame_SetStackPointer(frame, stack_pointer);
_PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit_Ex(
tstate, func_st, locals,
nargs, callargs, kwargs, frame);
stack_pointer = _PyFrame_GetStackPointer(frame);
// Need to sync the stack since we exit with DISPATCH_INLINED.
stack_pointer += -2;
assert(WITHIN_STACK_BOUNDS());
if (new_frame == NULL) {
goto error;
}
assert( 1 == 1);
frame->return_offset = 1;
DISPATCH_INLINED(new_frame);
}
PyObject *callargs = PyStackRef_AsPyObjectBorrow(callargs_st);
assert(PyTuple_CheckExact(callargs));
PyObject *kwargs = PyStackRef_AsPyObjectBorrow(kwargs_st);
assert(kwargs == NULL || PyDict_CheckExact(kwargs));
stack_pointer[-2] = callargs_st;
stack_pointer[-1] = kwargs_st;
_PyFrame_SetStackPointer(frame, stack_pointer);
result_o = PyObject_Call(func, callargs, kwargs);
stack_pointer = _PyFrame_GetStackPointer(frame);
}
stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
_PyFrame_SetStackPointer(frame, stack_pointer);
PyStackRef_XCLOSE(kwargs_st);
stack_pointer = _PyFrame_GetStackPointer(frame);
stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
_PyFrame_SetStackPointer(frame, stack_pointer);
PyStackRef_CLOSE(callargs_st);
stack_pointer = _PyFrame_GetStackPointer(frame);
stack_pointer += -2;
assert(WITHIN_STACK_BOUNDS());
_PyFrame_SetStackPointer(frame, stack_pointer);
PyStackRef_CLOSE(func_st);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (result_o == NULL) {
goto error;
}
result = PyStackRef_FromPyObjectSteal(result_o);
}
// _CHECK_PERIODIC
{
_Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY();
QSBR_QUIESCENT_STATE(tstate);
if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) {
stack_pointer[0] = result;
stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
_PyFrame_SetStackPointer(frame, stack_pointer);
int err = _Py_HandlePending(tstate);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (err != 0) {
goto error;
}
stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
}
}
stack_pointer[0] = result;
stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
} }
TARGET(INSTRUMENTED_CALL_KW) { TARGET(INSTRUMENTED_CALL_KW) {
@ -4827,25 +5010,170 @@
(void)this_instr; (void)this_instr;
next_instr += 4; next_instr += 4;
INSTRUCTION_STATS(INSTRUMENTED_CALL_KW); INSTRUCTION_STATS(INSTRUMENTED_CALL_KW);
uint16_t counter = read_u16(&this_instr[1].cache); opcode = INSTRUMENTED_CALL_KW;
(void)counter; _PyStackRef *callable;
uint32_t version = read_u32(&this_instr[2].cache); _PyStackRef *self_or_null;
(void)version; _PyStackRef *args;
int is_meth = !PyStackRef_IsNull(PEEK(oparg + 2)); _PyStackRef kwnames;
int total_args = oparg + is_meth; _PyStackRef kwnames_in;
PyObject *function = PyStackRef_AsPyObjectBorrow(PEEK(oparg + 3)); _PyStackRef *func;
PyObject *arg = total_args == 0 ? &_PyInstrumentation_MISSING _PyStackRef *maybe_self;
: PyStackRef_AsPyObjectBorrow(PEEK(total_args + 1)); _PyStackRef kwnames_out;
_PyFrame_SetStackPointer(frame, stack_pointer); _PyStackRef res;
int err = _Py_call_instrumentation_2args( /* Skip 1 cache entry */
tstate, PY_MONITORING_EVENT_CALL, /* Skip 2 cache entries */
frame, this_instr, function, arg); // _MONITOR_CALL_KW
stack_pointer = _PyFrame_GetStackPointer(frame); {
if (err) { args = &stack_pointer[-1 - oparg];
goto error; self_or_null = &stack_pointer[-2 - oparg];
callable = &stack_pointer[-3 - oparg];
int is_meth = !PyStackRef_IsNull(self_or_null[0]);
PyObject *arg;
if (is_meth) {
arg = PyStackRef_AsPyObjectBorrow(self_or_null[0]);
}
else {
if (args) {
arg = PyStackRef_AsPyObjectBorrow(args[0]);
}
else {
arg = &_PyInstrumentation_MISSING;
}
}
PyObject *function = PyStackRef_AsPyObjectBorrow(callable[0]);
_PyFrame_SetStackPointer(frame, stack_pointer);
int err = _Py_call_instrumentation_2args(
tstate, PY_MONITORING_EVENT_CALL,
frame, this_instr, function, arg);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (err) {
goto error;
}
} }
PAUSE_ADAPTIVE_COUNTER(this_instr[1].counter); // _MAYBE_EXPAND_METHOD_KW
goto PREDICTED_CALL_KW; {
kwnames_in = stack_pointer[-1];
func = &stack_pointer[-3 - oparg];
maybe_self = &stack_pointer[-2 - oparg];
if (PyStackRef_TYPE(callable[0]) == &PyMethod_Type && PyStackRef_IsNull(self_or_null[0])) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
PyObject *self = ((PyMethodObject *)callable_o)->im_self;
maybe_self[0] = PyStackRef_FromPyObjectNew(self);
PyObject *method = ((PyMethodObject *)callable_o)->im_func;
_PyStackRef temp = callable[0];
func[0] = PyStackRef_FromPyObjectNew(method);
_PyFrame_SetStackPointer(frame, stack_pointer);
PyStackRef_CLOSE(temp);
stack_pointer = _PyFrame_GetStackPointer(frame);
}
kwnames_out = kwnames_in;
}
// _DO_CALL_KW
{
kwnames = kwnames_out;
args = &stack_pointer[-1 - oparg];
self_or_null = &stack_pointer[-2 - oparg];
callable = &stack_pointer[-3 - oparg];
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
PyObject *kwnames_o = PyStackRef_AsPyObjectBorrow(kwnames);
// oparg counts all of the args, but *not* self:
int total_args = oparg;
_PyStackRef *arguments = args;
if (!PyStackRef_IsNull(self_or_null[0])) {
arguments--;
total_args++;
}
int positional_args = total_args - (int)PyTuple_GET_SIZE(kwnames_o);
// Check if the call can be inlined or not
if (Py_TYPE(callable_o) == &PyFunction_Type &&
tstate->interp->eval_frame == NULL &&
((PyFunctionObject *)callable_o)->vectorcall == _PyFunction_Vectorcall)
{
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(callable_o))->co_flags;
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(callable_o));
stack_pointer[-1] = kwnames;
_PyFrame_SetStackPointer(frame, stack_pointer);
_PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit(
tstate, callable[0], locals,
arguments, positional_args, kwnames_o, frame
);
stack_pointer = _PyFrame_GetStackPointer(frame);
stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
_PyFrame_SetStackPointer(frame, stack_pointer);
PyStackRef_CLOSE(kwnames);
stack_pointer = _PyFrame_GetStackPointer(frame);
// Sync stack explicitly since we leave using DISPATCH_INLINED().
stack_pointer += -2 - oparg;
assert(WITHIN_STACK_BOUNDS());
// The frame has stolen all the arguments from the stack,
// so there is no need to clean them up.
if (new_frame == NULL) {
goto error;
}
assert( 4 == 1 + INLINE_CACHE_ENTRIES_CALL_KW);
frame->return_offset = 4 ;
DISPATCH_INLINED(new_frame);
}
/* Callable is not a normal Python function */
STACKREFS_TO_PYOBJECTS(arguments, total_args, args_o);
if (CONVERSION_FAILED(args_o)) {
PyStackRef_CLOSE(callable[0]);
PyStackRef_XCLOSE(self_or_null[0]);
for (int _i = oparg; --_i >= 0;) {
PyStackRef_CLOSE(args[_i]);
}
PyStackRef_CLOSE(kwnames);
stack_pointer += -3 - oparg;
assert(WITHIN_STACK_BOUNDS());
goto error;
}
stack_pointer[-1] = kwnames;
_PyFrame_SetStackPointer(frame, stack_pointer);
PyObject *res_o = PyObject_Vectorcall(
callable_o, args_o,
positional_args | PY_VECTORCALL_ARGUMENTS_OFFSET,
kwnames_o);
stack_pointer = _PyFrame_GetStackPointer(frame);
STACKREFS_TO_PYOBJECTS_CLEANUP(args_o);
if (opcode == INSTRUMENTED_CALL_KW) {
PyObject *arg = total_args == 0 ?
&_PyInstrumentation_MISSING : PyStackRef_AsPyObjectBorrow(arguments[0]);
if (res_o == NULL) {
_PyFrame_SetStackPointer(frame, stack_pointer);
_Py_call_instrumentation_exc2(
tstate, PY_MONITORING_EVENT_C_RAISE,
frame, this_instr, callable_o, arg);
stack_pointer = _PyFrame_GetStackPointer(frame);
}
else {
_PyFrame_SetStackPointer(frame, stack_pointer);
int err = _Py_call_instrumentation_2args(
tstate, PY_MONITORING_EVENT_C_RETURN,
frame, this_instr, callable_o, arg);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (err < 0) {
Py_CLEAR(res_o);
}
}
}
PyStackRef_CLOSE(callable[0]);
PyStackRef_XCLOSE(self_or_null[0]);
for (int _i = oparg; --_i >= 0;) {
PyStackRef_CLOSE(args[_i]);
}
PyStackRef_CLOSE(kwnames);
if (res_o == NULL) {
stack_pointer += -3 - oparg;
assert(WITHIN_STACK_BOUNDS());
goto error;
}
res = PyStackRef_FromPyObjectSteal(res_o);
}
stack_pointer[-3 - oparg] = res;
stack_pointer += -2 - oparg;
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
} }
TARGET(INSTRUMENTED_END_FOR) { TARGET(INSTRUMENTED_END_FOR) {
@ -4944,6 +5272,7 @@
(void)this_instr; (void)this_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(INSTRUMENTED_INSTRUCTION); INSTRUCTION_STATS(INSTRUMENTED_INSTRUCTION);
opcode = INSTRUMENTED_INSTRUCTION;
_PyFrame_SetStackPointer(frame, stack_pointer); _PyFrame_SetStackPointer(frame, stack_pointer);
int next_opcode = _Py_call_instrumentation_instruction( int next_opcode = _Py_call_instrumentation_instruction(
tstate, frame, this_instr); tstate, frame, this_instr);
@ -5001,6 +5330,7 @@
(void)this_instr; (void)this_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(INSTRUMENTED_LINE); INSTRUCTION_STATS(INSTRUMENTED_LINE);
opcode = INSTRUMENTED_LINE;
int original_opcode = 0; int original_opcode = 0;
if (tstate->tracing) { if (tstate->tracing) {
PyCodeObject *code = _PyFrame_GetCode(frame); PyCodeObject *code = _PyFrame_GetCode(frame);
@ -5038,11 +5368,88 @@
(void)this_instr; (void)this_instr;
next_instr += 2; next_instr += 2;
INSTRUCTION_STATS(INSTRUMENTED_LOAD_SUPER_ATTR); INSTRUCTION_STATS(INSTRUMENTED_LOAD_SUPER_ATTR);
opcode = INSTRUMENTED_LOAD_SUPER_ATTR;
_PyStackRef global_super_st;
_PyStackRef class_st;
_PyStackRef self_st;
_PyStackRef attr;
_PyStackRef null = PyStackRef_NULL;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
// cancel out the decrement that will happen in LOAD_SUPER_ATTR; we // _LOAD_SUPER_ATTR
// don't want to specialize instrumented instructions {
PAUSE_ADAPTIVE_COUNTER(this_instr[1].counter); self_st = stack_pointer[-1];
goto PREDICTED_LOAD_SUPER_ATTR; class_st = stack_pointer[-2];
global_super_st = stack_pointer[-3];
PyObject *global_super = PyStackRef_AsPyObjectBorrow(global_super_st);
PyObject *class = PyStackRef_AsPyObjectBorrow(class_st);
PyObject *self = PyStackRef_AsPyObjectBorrow(self_st);
if (opcode == INSTRUMENTED_LOAD_SUPER_ATTR) {
PyObject *arg = oparg & 2 ? class : &_PyInstrumentation_MISSING;
_PyFrame_SetStackPointer(frame, stack_pointer);
int err = _Py_call_instrumentation_2args(
tstate, PY_MONITORING_EVENT_CALL,
frame, this_instr, global_super, arg);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (err) {
PyStackRef_CLOSE(global_super_st);
PyStackRef_CLOSE(class_st);
PyStackRef_CLOSE(self_st);
goto pop_3_error;
}
}
// we make no attempt to optimize here; specializations should
// handle any case whose performance we care about
PyObject *stack[] = {class, self};
_PyFrame_SetStackPointer(frame, stack_pointer);
PyObject *super = PyObject_Vectorcall(global_super, stack, oparg & 2, NULL);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (opcode == INSTRUMENTED_LOAD_SUPER_ATTR) {
PyObject *arg = oparg & 2 ? class : &_PyInstrumentation_MISSING;
if (super == NULL) {
_PyFrame_SetStackPointer(frame, stack_pointer);
_Py_call_instrumentation_exc2(
tstate, PY_MONITORING_EVENT_C_RAISE,
frame, this_instr, global_super, arg);
stack_pointer = _PyFrame_GetStackPointer(frame);
}
else {
_PyFrame_SetStackPointer(frame, stack_pointer);
int err = _Py_call_instrumentation_2args(
tstate, PY_MONITORING_EVENT_C_RETURN,
frame, this_instr, global_super, arg);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (err < 0) {
Py_CLEAR(super);
}
}
}
PyStackRef_CLOSE(global_super_st);
PyStackRef_CLOSE(class_st);
PyStackRef_CLOSE(self_st);
if (super == NULL) {
goto pop_3_error;
}
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2);
stack_pointer += -3;
assert(WITHIN_STACK_BOUNDS());
_PyFrame_SetStackPointer(frame, stack_pointer);
PyObject *attr_o = PyObject_GetAttr(super, name);
Py_DECREF(super);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (attr_o == NULL) {
goto error;
}
attr = PyStackRef_FromPyObjectSteal(attr_o);
}
// _PUSH_NULL_CONDITIONAL
{
null = PyStackRef_NULL;
}
stack_pointer[0] = attr;
if (oparg & 1) stack_pointer[1] = null;
stack_pointer += 1 + (oparg & 1);
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
} }
TARGET(INSTRUMENTED_NOT_TAKEN) { TARGET(INSTRUMENTED_NOT_TAKEN) {
@ -6862,6 +7269,7 @@
PREDICTED_LOAD_SUPER_ATTR:; PREDICTED_LOAD_SUPER_ATTR:;
_Py_CODEUNIT* const this_instr = next_instr - 2; _Py_CODEUNIT* const this_instr = next_instr - 2;
(void)this_instr; (void)this_instr;
opcode = LOAD_SUPER_ATTR;
_PyStackRef global_super_st; _PyStackRef global_super_st;
_PyStackRef class_st; _PyStackRef class_st;
_PyStackRef self_st; _PyStackRef self_st;

View file

@ -237,10 +237,7 @@ static void *opcode_targets[256] = {
&&TARGET_INSTRUMENTED_END_FOR, &&TARGET_INSTRUMENTED_END_FOR,
&&TARGET_INSTRUMENTED_POP_ITER, &&TARGET_INSTRUMENTED_POP_ITER,
&&TARGET_INSTRUMENTED_END_SEND, &&TARGET_INSTRUMENTED_END_SEND,
&&TARGET_INSTRUMENTED_LOAD_SUPER_ATTR,
&&TARGET_INSTRUMENTED_FOR_ITER, &&TARGET_INSTRUMENTED_FOR_ITER,
&&TARGET_INSTRUMENTED_CALL_KW,
&&TARGET_INSTRUMENTED_CALL_FUNCTION_EX,
&&TARGET_INSTRUMENTED_INSTRUCTION, &&TARGET_INSTRUMENTED_INSTRUCTION,
&&TARGET_INSTRUMENTED_JUMP_FORWARD, &&TARGET_INSTRUMENTED_JUMP_FORWARD,
&&TARGET_INSTRUMENTED_NOT_TAKEN, &&TARGET_INSTRUMENTED_NOT_TAKEN,
@ -251,7 +248,10 @@ static void *opcode_targets[256] = {
&&TARGET_INSTRUMENTED_RESUME, &&TARGET_INSTRUMENTED_RESUME,
&&TARGET_INSTRUMENTED_RETURN_VALUE, &&TARGET_INSTRUMENTED_RETURN_VALUE,
&&TARGET_INSTRUMENTED_YIELD_VALUE, &&TARGET_INSTRUMENTED_YIELD_VALUE,
&&TARGET_INSTRUMENTED_LOAD_SUPER_ATTR,
&&TARGET_INSTRUMENTED_CALL, &&TARGET_INSTRUMENTED_CALL,
&&TARGET_INSTRUMENTED_CALL_KW,
&&TARGET_INSTRUMENTED_CALL_FUNCTION_EX,
&&TARGET_INSTRUMENTED_JUMP_BACKWARD, &&TARGET_INSTRUMENTED_JUMP_BACKWARD,
&&TARGET_INSTRUMENTED_LINE, &&TARGET_INSTRUMENTED_LINE,
&&TARGET_ENTER_EXECUTOR, &&TARGET_ENTER_EXECUTOR,

View file

@ -1105,8 +1105,6 @@
break; break;
} }
/* _INSTRUMENTED_LOAD_SUPER_ATTR is not a viable micro-op for tier 2 */
case _LOAD_SUPER_ATTR_ATTR: { case _LOAD_SUPER_ATTR_ATTR: {
JitOptSymbol *attr_st; JitOptSymbol *attr_st;
attr_st = sym_new_not_null(ctx); attr_st = sym_new_not_null(ctx);
@ -2153,7 +2151,7 @@
break; break;
} }
/* _INSTRUMENTED_CALL_KW is not a viable micro-op for tier 2 */ /* _MONITOR_CALL_KW is not a viable micro-op for tier 2 */
case _MAYBE_EXPAND_METHOD_KW: { case _MAYBE_EXPAND_METHOD_KW: {
JitOptSymbol **func; JitOptSymbol **func;
@ -2222,8 +2220,6 @@
break; break;
} }
/* _INSTRUMENTED_CALL_FUNCTION_EX is not a viable micro-op for tier 2 */
case _MAKE_CALLARGS_A_TUPLE: { case _MAKE_CALLARGS_A_TUPLE: {
JitOptSymbol *tuple; JitOptSymbol *tuple;
JitOptSymbol *kwargs_out; JitOptSymbol *kwargs_out;

View file

@ -31,6 +31,7 @@ class Properties:
has_free: bool has_free: bool
side_exit: bool side_exit: bool
pure: bool pure: bool
uses_opcode: bool
tier: int | None = None tier: int | None = None
oparg_and_1: bool = False oparg_and_1: bool = False
const_oparg: int = -1 const_oparg: int = -1
@ -66,6 +67,7 @@ class Properties:
uses_co_consts=any(p.uses_co_consts for p in properties), uses_co_consts=any(p.uses_co_consts for p in properties),
uses_co_names=any(p.uses_co_names for p in properties), uses_co_names=any(p.uses_co_names for p in properties),
uses_locals=any(p.uses_locals for p in properties), uses_locals=any(p.uses_locals for p in properties),
uses_opcode=any(p.uses_opcode for p in properties),
has_free=any(p.has_free for p in properties), has_free=any(p.has_free for p in properties),
side_exit=any(p.side_exit for p in properties), side_exit=any(p.side_exit for p in properties),
pure=all(p.pure for p in properties), pure=all(p.pure for p in properties),
@ -92,6 +94,7 @@ SKIP_PROPERTIES = Properties(
uses_co_consts=False, uses_co_consts=False,
uses_co_names=False, uses_co_names=False,
uses_locals=False, uses_locals=False,
uses_opcode=False,
has_free=False, has_free=False,
side_exit=False, side_exit=False,
pure=True, pure=True,
@ -755,7 +758,6 @@ def find_escaping_api_calls(instr: parser.InstDef) -> dict[lexer.Token, Escaping
EXITS = { EXITS = {
"DISPATCH", "DISPATCH",
"GO_TO_INSTRUCTION",
"Py_UNREACHABLE", "Py_UNREACHABLE",
"DISPATCH_INLINED", "DISPATCH_INLINED",
"DISPATCH_GOTO", "DISPATCH_GOTO",
@ -865,7 +867,8 @@ def compute_properties(op: parser.InstDef) -> Properties:
uses_co_consts=variable_used(op, "FRAME_CO_CONSTS"), uses_co_consts=variable_used(op, "FRAME_CO_CONSTS"),
uses_co_names=variable_used(op, "FRAME_CO_NAMES"), uses_co_names=variable_used(op, "FRAME_CO_NAMES"),
uses_locals=(variable_used(op, "GETLOCAL") or variable_used(op, "SETLOCAL")) uses_locals=(variable_used(op, "GETLOCAL") or variable_used(op, "SETLOCAL"))
and not has_free, and not has_free,
uses_opcode=variable_used(op, "opcode"),
has_free=has_free, has_free=has_free,
pure="pure" in op.annotations, pure="pure" in op.annotations,
no_save_ip="no_save_ip" in op.annotations, no_save_ip="no_save_ip" in op.annotations,
@ -1200,17 +1203,6 @@ def analyze_forest(forest: list[parser.AstNode]) -> Analysis:
add_label(node, labels) add_label(node, labels)
case _: case _:
pass pass
for uop in uops.values():
tkn_iter = iter(uop.body)
for tkn in tkn_iter:
if tkn.kind == "IDENTIFIER" and tkn.text == "GO_TO_INSTRUCTION":
if next(tkn_iter).kind != "LPAREN":
continue
target = next(tkn_iter)
if target.kind != "IDENTIFIER":
continue
if target.text in instructions:
instructions[target.text].is_target = True
for uop in uops.values(): for uop in uops.values():
uop.instruction_size = get_instruction_size_for_uop(instructions, uop) uop.instruction_size = get_instruction_size_for_uop(instructions, uop)
# Special case BINARY_OP_INPLACE_ADD_UNICODE # Special case BINARY_OP_INPLACE_ADD_UNICODE

View file

@ -124,8 +124,7 @@ class Emitter:
"PyStackRef_AsPyObjectSteal": self.stackref_steal, "PyStackRef_AsPyObjectSteal": self.stackref_steal,
"DISPATCH": self.dispatch, "DISPATCH": self.dispatch,
"INSTRUCTION_SIZE": self.instruction_size, "INSTRUCTION_SIZE": self.instruction_size,
"POP_INPUT": self.pop_input, "POP_INPUT": self.pop_input
"GO_TO_INSTRUCTION": self.go_to_instruction,
} }
self.out = out self.out = out
@ -381,23 +380,6 @@ class Emitter:
self._print_storage(storage) self._print_storage(storage)
return True return True
def go_to_instruction(
self,
tkn: Token,
tkn_iter: TokenIterator,
uop: Uop,
storage: Storage,
inst: Instruction | None,
) -> bool:
next(tkn_iter)
name = next(tkn_iter)
next(tkn_iter)
next(tkn_iter)
assert name.kind == "IDENTIFIER"
self.emit("\n")
self.emit(f"goto PREDICTED_{name.text};\n")
return True
def emit_save(self, storage: Storage) -> None: def emit_save(self, storage: Storage) -> None:
storage.save(self.out) storage.save(self.out)
self._print_storage(storage) self._print_storage(storage)

View file

@ -220,6 +220,8 @@ def generate_tier1_cases(
if needs_this: if needs_this:
out.emit(f"_Py_CODEUNIT* const this_instr = next_instr - {inst.size};\n") out.emit(f"_Py_CODEUNIT* const this_instr = next_instr - {inst.size};\n")
out.emit(unused_guard) out.emit(unused_guard)
if inst.properties.uses_opcode:
out.emit(f"opcode = {name};\n")
if inst.family is not None: if inst.family is not None:
out.emit( out.emit(
f"static_assert({inst.family.size} == {inst.size-1}" f"static_assert({inst.family.size} == {inst.size-1}"