case INSTRUMENTED_CALL:
return 2 + oparg;
case INSTRUMENTED_CALL_FUNCTION_EX:
- return 0;
+ return 4;
case INSTRUMENTED_CALL_KW:
- return 0;
+ return 3 + oparg;
case INSTRUMENTED_END_FOR:
return 2;
case INSTRUMENTED_END_SEND:
case INSTRUMENTED_LINE:
return 0;
case INSTRUMENTED_LOAD_SUPER_ATTR:
- return 0;
+ return 3;
case INSTRUMENTED_NOT_TAKEN:
return 0;
case INSTRUMENTED_POP_ITER:
case INSTRUMENTED_CALL:
return 1;
case INSTRUMENTED_CALL_FUNCTION_EX:
- return 0;
+ return 1;
case INSTRUMENTED_CALL_KW:
- return 0;
+ return 1;
case INSTRUMENTED_END_FOR:
return 1;
case INSTRUMENTED_END_SEND:
case INSTRUMENTED_LINE:
return 0;
case INSTRUMENTED_LOAD_SUPER_ATTR:
- return 0;
+ return 1 + (oparg & 1);
case INSTRUMENTED_NOT_TAKEN:
return 0;
case INSTRUMENTED_POP_ITER:
return 0;
}
case INSTRUMENTED_CALL_KW: {
- *effect = 0;
+ *effect = Py_MAX(0, -2 - oparg);
return 0;
}
case INSTRUMENTED_END_FOR: {
return 0;
}
case INSTRUMENTED_LOAD_SUPER_ATTR: {
- *effect = 0;
+ *effect = Py_MAX(-2, -2 + (oparg & 1));
return 0;
}
case INSTRUMENTED_NOT_TAKEN: {
[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 },
[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_KW] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
+ [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_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_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_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_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_POP_ITER] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG },
[INSTRUMENTED_POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG },
#define _INIT_CALL_PY_EXACT_ARGS_2 396
#define _INIT_CALL_PY_EXACT_ARGS_3 397
#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_INSTRUCTION INSTRUMENTED_INSTRUCTION
#define _INSTRUMENTED_JUMP_FORWARD INSTRUMENTED_JUMP_FORWARD
#define _INSTRUMENTED_LINE INSTRUMENTED_LINE
-#define _INSTRUMENTED_LOAD_SUPER_ATTR INSTRUMENTED_LOAD_SUPER_ATTR
#define _INSTRUMENTED_NOT_TAKEN INSTRUMENTED_NOT_TAKEN
#define _INSTRUMENTED_POP_JUMP_IF_FALSE INSTRUMENTED_POP_JUMP_IF_FALSE
#define _INSTRUMENTED_POP_JUMP_IF_NONE INSTRUMENTED_POP_JUMP_IF_NONE
#define _MAYBE_EXPAND_METHOD 447
#define _MAYBE_EXPAND_METHOD_KW 448
#define _MONITOR_CALL 449
-#define _MONITOR_JUMP_BACKWARD 450
-#define _MONITOR_RESUME 451
+#define _MONITOR_CALL_KW 450
+#define _MONITOR_JUMP_BACKWARD 451
+#define _MONITOR_RESUME 452
#define _NOP NOP
#define _POP_EXCEPT POP_EXCEPT
-#define _POP_JUMP_IF_FALSE 452
-#define _POP_JUMP_IF_TRUE 453
+#define _POP_JUMP_IF_FALSE 453
+#define _POP_JUMP_IF_TRUE 454
#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_FRAME 455
+#define _PUSH_FRAME 456
#define _PUSH_NULL PUSH_NULL
-#define _PUSH_NULL_CONDITIONAL 456
-#define _PY_FRAME_GENERAL 457
-#define _PY_FRAME_KW 458
-#define _QUICKEN_RESUME 459
-#define _REPLACE_WITH_TRUE 460
+#define _PUSH_NULL_CONDITIONAL 457
+#define _PY_FRAME_GENERAL 458
+#define _PY_FRAME_KW 459
+#define _QUICKEN_RESUME 460
+#define _REPLACE_WITH_TRUE 461
#define _RESUME_CHECK RESUME_CHECK
#define _RETURN_GENERATOR RETURN_GENERATOR
#define _RETURN_VALUE RETURN_VALUE
-#define _SAVE_RETURN_OFFSET 461
-#define _SEND 462
-#define _SEND_GEN_FRAME 463
+#define _SAVE_RETURN_OFFSET 462
+#define _SEND 463
+#define _SEND_GEN_FRAME 464
#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 464
-#define _STORE_ATTR 465
-#define _STORE_ATTR_INSTANCE_VALUE 466
-#define _STORE_ATTR_SLOT 467
-#define _STORE_ATTR_WITH_HINT 468
+#define _START_EXECUTOR 465
+#define _STORE_ATTR 466
+#define _STORE_ATTR_INSTANCE_VALUE 467
+#define _STORE_ATTR_SLOT 468
+#define _STORE_ATTR_WITH_HINT 469
#define _STORE_DEREF STORE_DEREF
-#define _STORE_FAST 469
-#define _STORE_FAST_0 470
-#define _STORE_FAST_1 471
-#define _STORE_FAST_2 472
-#define _STORE_FAST_3 473
-#define _STORE_FAST_4 474
-#define _STORE_FAST_5 475
-#define _STORE_FAST_6 476
-#define _STORE_FAST_7 477
+#define _STORE_FAST 470
+#define _STORE_FAST_0 471
+#define _STORE_FAST_1 472
+#define _STORE_FAST_2 473
+#define _STORE_FAST_3 474
+#define _STORE_FAST_4 475
+#define _STORE_FAST_5 476
+#define _STORE_FAST_6 477
+#define _STORE_FAST_7 478
#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 478
-#define _STORE_SUBSCR 479
+#define _STORE_SLICE 479
+#define _STORE_SUBSCR 480
#define _STORE_SUBSCR_DICT STORE_SUBSCR_DICT
#define _STORE_SUBSCR_LIST_INT STORE_SUBSCR_LIST_INT
#define _SWAP SWAP
-#define _TIER2_RESUME_CHECK 480
-#define _TO_BOOL 481
+#define _TIER2_RESUME_CHECK 481
+#define _TO_BOOL 482
#define _TO_BOOL_BOOL TO_BOOL_BOOL
#define _TO_BOOL_INT TO_BOOL_INT
#define _TO_BOOL_LIST TO_BOOL_LIST
#define _UNARY_NEGATIVE UNARY_NEGATIVE
#define _UNARY_NOT UNARY_NOT
#define _UNPACK_EX UNPACK_EX
-#define _UNPACK_SEQUENCE 482
+#define _UNPACK_SEQUENCE 483
#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 482
+#define MAX_UOP_ID 483
#ifdef __cplusplus
}
#define INSTRUMENTED_END_FOR 235
#define INSTRUMENTED_POP_ITER 236
#define INSTRUMENTED_END_SEND 237
-#define INSTRUMENTED_LOAD_SUPER_ATTR 238
-#define INSTRUMENTED_FOR_ITER 239
-#define INSTRUMENTED_CALL_KW 240
-#define INSTRUMENTED_CALL_FUNCTION_EX 241
-#define INSTRUMENTED_INSTRUCTION 242
-#define INSTRUMENTED_JUMP_FORWARD 243
-#define INSTRUMENTED_NOT_TAKEN 244
-#define INSTRUMENTED_POP_JUMP_IF_TRUE 245
-#define INSTRUMENTED_POP_JUMP_IF_FALSE 246
-#define INSTRUMENTED_POP_JUMP_IF_NONE 247
-#define INSTRUMENTED_POP_JUMP_IF_NOT_NONE 248
-#define INSTRUMENTED_RESUME 249
-#define INSTRUMENTED_RETURN_VALUE 250
-#define INSTRUMENTED_YIELD_VALUE 251
-#define INSTRUMENTED_CALL 252
+#define INSTRUMENTED_FOR_ITER 238
+#define INSTRUMENTED_INSTRUCTION 239
+#define INSTRUMENTED_JUMP_FORWARD 240
+#define INSTRUMENTED_NOT_TAKEN 241
+#define INSTRUMENTED_POP_JUMP_IF_TRUE 242
+#define INSTRUMENTED_POP_JUMP_IF_FALSE 243
+#define INSTRUMENTED_POP_JUMP_IF_NONE 244
+#define INSTRUMENTED_POP_JUMP_IF_NOT_NONE 245
+#define INSTRUMENTED_RESUME 246
+#define INSTRUMENTED_RETURN_VALUE 247
+#define INSTRUMENTED_YIELD_VALUE 248
+#define INSTRUMENTED_LOAD_SUPER_ATTR 249
+#define INSTRUMENTED_CALL 250
+#define INSTRUMENTED_CALL_KW 251
+#define INSTRUMENTED_CALL_FUNCTION_EX 252
#define INSTRUMENTED_JUMP_BACKWARD 253
#define INSTRUMENTED_LINE 254
#define ENTER_EXECUTOR 255
'INSTRUMENTED_END_FOR': 235,
'INSTRUMENTED_POP_ITER': 236,
'INSTRUMENTED_END_SEND': 237,
- 'INSTRUMENTED_LOAD_SUPER_ATTR': 238,
- 'INSTRUMENTED_FOR_ITER': 239,
- 'INSTRUMENTED_CALL_KW': 240,
- 'INSTRUMENTED_CALL_FUNCTION_EX': 241,
- 'INSTRUMENTED_INSTRUCTION': 242,
- 'INSTRUMENTED_JUMP_FORWARD': 243,
- 'INSTRUMENTED_NOT_TAKEN': 244,
- 'INSTRUMENTED_POP_JUMP_IF_TRUE': 245,
- 'INSTRUMENTED_POP_JUMP_IF_FALSE': 246,
- 'INSTRUMENTED_POP_JUMP_IF_NONE': 247,
- 'INSTRUMENTED_POP_JUMP_IF_NOT_NONE': 248,
- 'INSTRUMENTED_RESUME': 249,
- 'INSTRUMENTED_RETURN_VALUE': 250,
- 'INSTRUMENTED_YIELD_VALUE': 251,
- 'INSTRUMENTED_CALL': 252,
+ 'INSTRUMENTED_FOR_ITER': 238,
+ 'INSTRUMENTED_INSTRUCTION': 239,
+ 'INSTRUMENTED_JUMP_FORWARD': 240,
+ 'INSTRUMENTED_NOT_TAKEN': 241,
+ 'INSTRUMENTED_POP_JUMP_IF_TRUE': 242,
+ 'INSTRUMENTED_POP_JUMP_IF_FALSE': 243,
+ 'INSTRUMENTED_POP_JUMP_IF_NONE': 244,
+ 'INSTRUMENTED_POP_JUMP_IF_NOT_NONE': 245,
+ 'INSTRUMENTED_RESUME': 246,
+ 'INSTRUMENTED_RETURN_VALUE': 247,
+ 'INSTRUMENTED_YIELD_VALUE': 248,
+ 'INSTRUMENTED_LOAD_SUPER_ATTR': 249,
+ 'INSTRUMENTED_CALL': 250,
+ 'INSTRUMENTED_CALL_KW': 251,
+ 'INSTRUMENTED_CALL_FUNCTION_EX': 252,
'INSTRUMENTED_JUMP_BACKWARD': 253,
'JUMP': 256,
'JUMP_IF_FALSE': 257,
#include "ceval_macros.h"
/* Flow control macros */
-#define GO_TO_INSTRUCTION(instname) ((void)0)
#define inst(name, ...) case name:
#define op(name, ...) /* NAME is ignored */
ERROR_IF(err != 0, error);
}
- inst(INSTRUMENTED_LOAD_SUPER_ATTR, (unused/1 -- )) {
- // cancel out the decrement that will happen in LOAD_SUPER_ATTR; we
- // don't want to specialize instrumented instructions
- PAUSE_ADAPTIVE_COUNTER(this_instr[1].counter);
- GO_TO_INSTRUCTION(LOAD_SUPER_ATTR);
- }
+ macro(INSTRUMENTED_LOAD_SUPER_ATTR) =
+ counter/1 +
+ _LOAD_SUPER_ATTR +
+ _PUSH_NULL_CONDITIONAL;
family(LOAD_SUPER_ATTR, INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR) = {
LOAD_SUPER_ATTR_ATTR,
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)) {
PyObject *global_super = PyStackRef_AsPyObjectBorrow(global_super_st);
CALL_KW_NON_PY,
};
- inst(INSTRUMENTED_CALL_KW, (counter/1, version/2 -- )) {
- int is_meth = !PyStackRef_IsNull(PEEK(oparg + 2));
- int total_args = oparg + is_meth;
- PyObject *function = PyStackRef_AsPyObjectBorrow(PEEK(oparg + 3));
- PyObject *arg = total_args == 0 ? &_PyInstrumentation_MISSING
- : PyStackRef_AsPyObjectBorrow(PEEK(total_args + 1));
+ 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(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]);
int err = _Py_call_instrumentation_2args(
tstate, PY_MONITORING_EVENT_CALL,
frame, this_instr, function, arg);
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)) {
_MAYBE_EXPAND_METHOD_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)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable[0]);
EXIT_IF(PyFunction_Check(callable_o));
_CALL_KW_NON_PY +
_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)) {
PyObject *callargs_o = PyStackRef_AsPyObjectBorrow(callargs);
if (PyTuple_CheckExact(callargs_o)) {
_DO_CALL_FUNCTION_EX +
_CHECK_PERIODIC;
+ macro(INSTRUMENTED_CALL_FUNCTION_EX) =
+ _MAKE_CALLARGS_A_TUPLE +
+ _DO_CALL_FUNCTION_EX +
+ _CHECK_PERIODIC;
inst(MAKE_FUNCTION, (codeobj_st -- func)) {
PyObject *codeobj = PyStackRef_AsPyObjectBorrow(codeobj_st);
break;
}
- /* _INSTRUMENTED_LOAD_SUPER_ATTR is not a viable micro-op for tier 2 because it is instrumented */
-
case _LOAD_SUPER_ATTR_ATTR: {
_PyStackRef self_st;
_PyStackRef class_st;
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: {
_PyStackRef kwnames_in;
break;
}
- /* _INSTRUMENTED_CALL_FUNCTION_EX is not a viable micro-op for tier 2 because it is instrumented */
-
case _MAKE_CALLARGS_A_TUPLE: {
_PyStackRef kwargs_in;
_PyStackRef callargs;
PREDICTED_CALL:;
_Py_CODEUNIT* const this_instr = next_instr - 4;
(void)this_instr;
+ opcode = CALL;
_PyStackRef *callable;
_PyStackRef *self_or_null;
_PyStackRef *args;
}
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;
INSTRUCTION_STATS(CALL_FUNCTION_EX);
- PREDICTED_CALL_FUNCTION_EX:;
- _Py_CODEUNIT* const this_instr = next_instr - 1;
- (void)this_instr;
+ opcode = CALL_FUNCTION_EX;
_PyStackRef func;
_PyStackRef callargs;
_PyStackRef kwargs_in;
PREDICTED_CALL_KW:;
_Py_CODEUNIT* const this_instr = next_instr - 4;
(void)this_instr;
+ opcode = CALL_KW;
_PyStackRef *callable;
_PyStackRef *self_or_null;
_PyStackRef *args;
frame->instr_ptr = next_instr;
next_instr += 4;
INSTRUCTION_STATS(CALL_KW_NON_PY);
+ opcode = CALL_KW_NON_PY;
static_assert(INLINE_CACHE_ENTRIES_CALL_KW == 3, "incorrect cache size");
_PyStackRef *callable;
_PyStackRef kwnames;
frame->instr_ptr = next_instr;
next_instr += 4;
INSTRUCTION_STATS(CALL_NON_PY_GENERAL);
+ opcode = CALL_NON_PY_GENERAL;
static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size");
_PyStackRef *callable;
_PyStackRef *self_or_null;
(void)this_instr;
next_instr += 1;
INSTRUCTION_STATS(ENTER_EXECUTOR);
+ opcode = ENTER_EXECUTOR;
#ifdef _Py_TIER2
PyCodeObject *code = _PyFrame_GetCode(frame);
_PyExecutorObject *executor = code->co_executors->executors[oparg & 255];
frame->instr_ptr = next_instr;
next_instr += 1;
INSTRUCTION_STATS(EXTENDED_ARG);
+ opcode = EXTENDED_ARG;
assert(oparg);
opcode = next_instr->op.code;
oparg = oparg << 8 | next_instr->op.arg;
(void)this_instr;
next_instr += 4;
INSTRUCTION_STATS(INSTRUMENTED_CALL);
+ opcode = INSTRUMENTED_CALL;
_PyStackRef *callable;
_PyStackRef *self_or_null;
_PyStackRef *args;
}
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;
INSTRUCTION_STATS(INSTRUMENTED_CALL_FUNCTION_EX);
-
- goto PREDICTED_CALL_FUNCTION_EX;
+ opcode = INSTRUMENTED_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) {
(void)this_instr;
next_instr += 4;
INSTRUCTION_STATS(INSTRUMENTED_CALL_KW);
- uint16_t counter = read_u16(&this_instr[1].cache);
- (void)counter;
- uint32_t version = read_u32(&this_instr[2].cache);
- (void)version;
- int is_meth = !PyStackRef_IsNull(PEEK(oparg + 2));
- int total_args = oparg + is_meth;
- PyObject *function = PyStackRef_AsPyObjectBorrow(PEEK(oparg + 3));
- PyObject *arg = total_args == 0 ? &_PyInstrumentation_MISSING
- : PyStackRef_AsPyObjectBorrow(PEEK(total_args + 1));
- _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;
+ opcode = INSTRUMENTED_CALL_KW;
+ _PyStackRef *callable;
+ _PyStackRef *self_or_null;
+ _PyStackRef *args;
+ _PyStackRef kwnames;
+ _PyStackRef kwnames_in;
+ _PyStackRef *func;
+ _PyStackRef *maybe_self;
+ _PyStackRef kwnames_out;
+ _PyStackRef res;
+ /* Skip 1 cache entry */
+ /* Skip 2 cache entries */
+ // _MONITOR_CALL_KW
+ {
+ args = &stack_pointer[-1 - oparg];
+ 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);
- goto PREDICTED_CALL_KW;
+ // _MAYBE_EXPAND_METHOD_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) {
(void)this_instr;
next_instr += 1;
INSTRUCTION_STATS(INSTRUMENTED_INSTRUCTION);
+ opcode = INSTRUMENTED_INSTRUCTION;
_PyFrame_SetStackPointer(frame, stack_pointer);
int next_opcode = _Py_call_instrumentation_instruction(
tstate, frame, this_instr);
(void)this_instr;
next_instr += 1;
INSTRUCTION_STATS(INSTRUMENTED_LINE);
+ opcode = INSTRUMENTED_LINE;
int original_opcode = 0;
if (tstate->tracing) {
PyCodeObject *code = _PyFrame_GetCode(frame);
(void)this_instr;
next_instr += 2;
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 */
- // cancel out the decrement that will happen in LOAD_SUPER_ATTR; we
- // don't want to specialize instrumented instructions
- PAUSE_ADAPTIVE_COUNTER(this_instr[1].counter);
- goto PREDICTED_LOAD_SUPER_ATTR;
+ // _LOAD_SUPER_ATTR
+ {
+ self_st = stack_pointer[-1];
+ 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) {
PREDICTED_LOAD_SUPER_ATTR:;
_Py_CODEUNIT* const this_instr = next_instr - 2;
(void)this_instr;
+ opcode = LOAD_SUPER_ATTR;
_PyStackRef global_super_st;
_PyStackRef class_st;
_PyStackRef self_st;
&&TARGET_INSTRUMENTED_END_FOR,
&&TARGET_INSTRUMENTED_POP_ITER,
&&TARGET_INSTRUMENTED_END_SEND,
- &&TARGET_INSTRUMENTED_LOAD_SUPER_ATTR,
&&TARGET_INSTRUMENTED_FOR_ITER,
- &&TARGET_INSTRUMENTED_CALL_KW,
- &&TARGET_INSTRUMENTED_CALL_FUNCTION_EX,
&&TARGET_INSTRUMENTED_INSTRUCTION,
&&TARGET_INSTRUMENTED_JUMP_FORWARD,
&&TARGET_INSTRUMENTED_NOT_TAKEN,
&&TARGET_INSTRUMENTED_RESUME,
&&TARGET_INSTRUMENTED_RETURN_VALUE,
&&TARGET_INSTRUMENTED_YIELD_VALUE,
+ &&TARGET_INSTRUMENTED_LOAD_SUPER_ATTR,
&&TARGET_INSTRUMENTED_CALL,
+ &&TARGET_INSTRUMENTED_CALL_KW,
+ &&TARGET_INSTRUMENTED_CALL_FUNCTION_EX,
&&TARGET_INSTRUMENTED_JUMP_BACKWARD,
&&TARGET_INSTRUMENTED_LINE,
&&TARGET_ENTER_EXECUTOR,
break;
}
- /* _INSTRUMENTED_LOAD_SUPER_ATTR is not a viable micro-op for tier 2 */
-
case _LOAD_SUPER_ATTR_ATTR: {
JitOptSymbol *attr_st;
attr_st = sym_new_not_null(ctx);
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: {
JitOptSymbol **func;
break;
}
- /* _INSTRUMENTED_CALL_FUNCTION_EX is not a viable micro-op for tier 2 */
-
case _MAKE_CALLARGS_A_TUPLE: {
JitOptSymbol *tuple;
JitOptSymbol *kwargs_out;
has_free: bool
side_exit: bool
pure: bool
+ uses_opcode: bool
tier: int | None = None
oparg_and_1: bool = False
const_oparg: int = -1
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_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),
side_exit=any(p.side_exit for p in properties),
pure=all(p.pure for p in properties),
uses_co_consts=False,
uses_co_names=False,
uses_locals=False,
+ uses_opcode=False,
has_free=False,
side_exit=False,
pure=True,
EXITS = {
"DISPATCH",
- "GO_TO_INSTRUCTION",
"Py_UNREACHABLE",
"DISPATCH_INLINED",
"DISPATCH_GOTO",
uses_co_consts=variable_used(op, "FRAME_CO_CONSTS"),
uses_co_names=variable_used(op, "FRAME_CO_NAMES"),
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,
pure="pure" in op.annotations,
no_save_ip="no_save_ip" in op.annotations,
add_label(node, labels)
case _:
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():
uop.instruction_size = get_instruction_size_for_uop(instructions, uop)
# Special case BINARY_OP_INPLACE_ADD_UNICODE
"PyStackRef_AsPyObjectSteal": self.stackref_steal,
"DISPATCH": self.dispatch,
"INSTRUCTION_SIZE": self.instruction_size,
- "POP_INPUT": self.pop_input,
- "GO_TO_INSTRUCTION": self.go_to_instruction,
+ "POP_INPUT": self.pop_input
}
self.out = out
self._print_storage(storage)
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:
storage.save(self.out)
self._print_storage(storage)
if needs_this:
out.emit(f"_Py_CODEUNIT* const this_instr = next_instr - {inst.size};\n")
out.emit(unused_guard)
+ if inst.properties.uses_opcode:
+ out.emit(f"opcode = {name};\n")
if inst.family is not None:
out.emit(
f"static_assert({inst.family.size} == {inst.size-1}"