#define OPARG_BOTTOM 6
#define OPARG_SAVE_RETURN_OFFSET 7
-#define OPCODE_METADATA_FMT(OP) (_PyOpcode_opcode_metadata[(OP)].instr_format)
+#define OPCODE_METADATA_FLAGS(OP) (_PyOpcode_opcode_metadata[(OP)].flags & (HAS_ARG_FLAG | HAS_JUMP_FLAG))
#define SAME_OPCODE_METADATA(OP1, OP2) \
- (OPCODE_METADATA_FMT(OP1) == OPCODE_METADATA_FMT(OP2))
+ (OPCODE_METADATA_FLAGS(OP1) == OPCODE_METADATA_FLAGS(OP2))
#define OPCODE_METADATA_SIZE 512
#define OPCODE_UOP_NAME_SIZE 512
[RESUME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG },
[RESUME_CHECK] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG },
[INSTRUMENTED_RESUME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG },
- [LOAD_CLOSURE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG },
+ [LOAD_CLOSURE] = { true, 0, HAS_ARG_FLAG | HAS_LOCAL_FLAG },
[LOAD_FAST_CHECK] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG | HAS_ERROR_FLAG },
[LOAD_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG },
[LOAD_FAST_AND_CLEAR] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG },
[LOAD_FAST_LOAD_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG },
[LOAD_CONST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_CONST_FLAG },
[STORE_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG },
- [STORE_FAST_MAYBE_NULL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG },
+ [STORE_FAST_MAYBE_NULL] = { true, 0, HAS_ARG_FLAG | HAS_LOCAL_FLAG },
[STORE_FAST_LOAD_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG },
[STORE_FAST_STORE_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG },
[POP_TOP] = { true, INSTR_FMT_IX, 0 },
[MAP_ADD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG },
[INSTRUMENTED_LOAD_SUPER_ATTR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG },
[LOAD_SUPER_ATTR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG },
- [LOAD_SUPER_METHOD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG },
- [LOAD_ZERO_SUPER_METHOD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG },
- [LOAD_ZERO_SUPER_ATTR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG },
+ [LOAD_SUPER_METHOD] = { true, 0, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG },
+ [LOAD_ZERO_SUPER_METHOD] = { true, 0, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG },
+ [LOAD_ZERO_SUPER_ATTR] = { true, 0, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG },
[LOAD_SUPER_ATTR_ATTR] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG },
[LOAD_SUPER_ATTR_METHOD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG },
[LOAD_ATTR] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG },
- [LOAD_METHOD] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG },
+ [LOAD_METHOD] = { true, 0, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG },
[_GUARD_TYPE_VERSION] = { true, INSTR_FMT_IXC0, HAS_DEOPT_FLAG },
[_CHECK_MANAGED_OBJECT_HAS_VALUES] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG },
[_LOAD_ATTR_INSTANCE_VALUE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG },
[IMPORT_NAME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG },
[IMPORT_FROM] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG },
[JUMP_FORWARD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG },
- [JUMP_BACKWARD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG },
- [JUMP] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG },
- [JUMP_NO_INTERRUPT] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG },
+ [JUMP_BACKWARD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG },
+ [JUMP] = { true, 0, HAS_ARG_FLAG | HAS_JUMP_FLAG },
+ [JUMP_NO_INTERRUPT] = { true, 0, HAS_ARG_FLAG | HAS_JUMP_FLAG },
[ENTER_EXECUTOR] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG },
[POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG },
[POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG },
[BEFORE_ASYNC_WITH] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG },
[BEFORE_WITH] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG },
[WITH_EXCEPT_START] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG },
- [SETUP_FINALLY] = { true, INSTR_FMT_IX, 0 },
- [SETUP_CLEANUP] = { true, INSTR_FMT_IX, 0 },
- [SETUP_WITH] = { true, INSTR_FMT_IX, 0 },
- [POP_BLOCK] = { true, INSTR_FMT_IX, 0 },
+ [SETUP_FINALLY] = { true, 0, 0 },
+ [SETUP_CLEANUP] = { true, 0, 0 },
+ [SETUP_WITH] = { true, 0, 0 },
+ [POP_BLOCK] = { true, 0, 0 },
[PUSH_EXC_INFO] = { true, INSTR_FMT_IX, 0 },
[_GUARD_DORV_VALUES_INST_ATTR_FROM_DICT] = { true, INSTR_FMT_IX, HAS_DEOPT_FLAG },
[_GUARD_KEYS_VERSION] = { true, INSTR_FMT_IXC0, HAS_DEOPT_FLAG },
[SWAP] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
[INSTRUMENTED_INSTRUCTION] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG },
[INSTRUMENTED_JUMP_FORWARD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
- [INSTRUMENTED_JUMP_BACKWARD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG },
+ [INSTRUMENTED_JUMP_BACKWARD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG },
[INSTRUMENTED_POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG },
[INSTRUMENTED_POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG },
[INSTRUMENTED_POP_JUMP_IF_NONE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG },
[LOAD_GLOBAL_MODULE] = { .nuops = 2, .uops = { { _GUARD_GLOBALS_VERSION, 1, 1 }, { _LOAD_GLOBAL_MODULE, 1, 3 } } },
[LOAD_GLOBAL_BUILTIN] = { .nuops = 3, .uops = { { _GUARD_GLOBALS_VERSION, 1, 1 }, { _GUARD_BUILTINS_VERSION, 1, 2 }, { _LOAD_GLOBAL_BUILTINS, 1, 3 } } },
[DELETE_FAST] = { .nuops = 1, .uops = { { DELETE_FAST, 0, 0 } } },
+ [MAKE_CELL] = { .nuops = 1, .uops = { { MAKE_CELL, 0, 0 } } },
[DELETE_DEREF] = { .nuops = 1, .uops = { { DELETE_DEREF, 0, 0 } } },
[LOAD_FROM_DICT_OR_DEREF] = { .nuops = 1, .uops = { { LOAD_FROM_DICT_OR_DEREF, 0, 0 } } },
[LOAD_DEREF] = { .nuops = 1, .uops = { { LOAD_DEREF, 0, 0 } } },
[MATCH_KEYS] = { .nuops = 1, .uops = { { MATCH_KEYS, 0, 0 } } },
[GET_ITER] = { .nuops = 1, .uops = { { GET_ITER, 0, 0 } } },
[GET_YIELD_FROM_ITER] = { .nuops = 1, .uops = { { GET_YIELD_FROM_ITER, 0, 0 } } },
+ [BEFORE_ASYNC_WITH] = { .nuops = 1, .uops = { { BEFORE_ASYNC_WITH, 0, 0 } } },
[WITH_EXCEPT_START] = { .nuops = 1, .uops = { { WITH_EXCEPT_START, 0, 0 } } },
[PUSH_EXC_INFO] = { .nuops = 1, .uops = { { PUSH_EXC_INFO, 0, 0 } } },
[LOAD_ATTR_METHOD_WITH_VALUES] = { .nuops = 4, .uops = { { _GUARD_TYPE_VERSION, 2, 1 }, { _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT, 0, 0 }, { _GUARD_KEYS_VERSION, 2, 3 }, { _LOAD_ATTR_METHOD_WITH_VALUES, 4, 5 } } },
[LOAD_SUPER_ATTR] = 1,
[LOAD_ATTR] = 9,
[COMPARE_OP] = 1,
+ [JUMP_BACKWARD] = 1,
[POP_JUMP_IF_FALSE] = 1,
[POP_JUMP_IF_TRUE] = 1,
[POP_JUMP_IF_NONE] = 1,
[FOR_ITER] = 1,
[CALL] = 3,
[BINARY_OP] = 1,
- [JUMP_BACKWARD] = 1,
};
#endif // NEED_OPCODE_METADATA
}
inst(RAISE_VARARGS, (args[oparg] -- )) {
+ TIER_ONE_ONLY
PyObject *cause = NULL, *exc = NULL;
switch (oparg) {
case 2:
}
inst(RERAISE, (values[oparg], exc -- values[oparg])) {
+ TIER_ONE_ONLY
assert(oparg >= 0 && oparg <= 2);
if (oparg) {
PyObject *lasti = values[0];
}
inst(END_ASYNC_FOR, (awaitable, exc -- )) {
+ TIER_ONE_ONLY
assert(exc && PyExceptionInstance_Check(exc));
if (PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration)) {
DECREF_INPUTS();
}
inst(CLEANUP_THROW, (sub_iter, last_sent_val, exc_value -- none, value)) {
+ TIER_ONE_ONLY
assert(throwflag);
assert(exc_value && PyExceptionInstance_Check(exc_value));
if (PyErr_GivenExceptionMatches(exc_value, PyExc_StopIteration)) {
PyObject *initial = GETLOCAL(oparg);
PyObject *cell = PyCell_New(initial);
if (cell == NULL) {
- goto resume_with_error;
+ goto error;
}
SETLOCAL(oparg, cell);
}
}
inst(IMPORT_NAME, (level, fromlist -- res)) {
+ TIER_ONE_ONLY
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
res = import_name(tstate, frame, name, fromlist, level);
DECREF_INPUTS();
}
inst(IMPORT_FROM, (from -- from, res)) {
+ TIER_ONE_ONLY
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
res = import_from(tstate, from, name);
ERROR_IF(res == NULL, error);
JUMPBY(oparg);
}
- inst(JUMP_BACKWARD, (--)) {
+ inst(JUMP_BACKWARD, (unused/1 --)) {
CHECK_EVAL_BREAKER();
assert(oparg <= INSTR_OFFSET());
- JUMPBY(1-oparg);
+ JUMPBY(-oparg);
#if ENABLE_SPECIALIZATION
this_instr[1].cache += (1 << OPTIMIZER_BITS_IN_COUNTER);
if (this_instr[1].cache > tstate->interp->optimizer_backedge_threshold &&
};
inst(ENTER_EXECUTOR, (--)) {
+ TIER_ONE_ONLY
CHECK_EVAL_BREAKER();
PyCodeObject *code = _PyFrame_GetCode(frame);
}
inst(BEFORE_WITH, (mgr -- exit, res)) {
+ TIER_ONE_ONLY
/* pop the context manager, push its __exit__ and the
* value returned from calling its __enter__
*/
INSTRUMENTED_JUMP(this_instr, next_instr + oparg, PY_MONITORING_EVENT_JUMP);
}
- inst(INSTRUMENTED_JUMP_BACKWARD, ( -- )) {
+ inst(INSTRUMENTED_JUMP_BACKWARD, (unused/1 -- )) {
CHECK_EVAL_BREAKER();
- INSTRUMENTED_JUMP(this_instr, next_instr + 1 - oparg, PY_MONITORING_EVENT_JUMP);
+ INSTRUMENTED_JUMP(this_instr, next_instr - oparg, PY_MONITORING_EVENT_JUMP);
}
inst(INSTRUMENTED_POP_JUMP_IF_TRUE, (unused/1 -- )) {
INSTRUCTION_STATS(RAISE_VARARGS);
PyObject **args;
args = stack_pointer - oparg;
+ TIER_ONE_ONLY
PyObject *cause = NULL, *exc = NULL;
switch (oparg) {
case 2:
PyObject **values;
exc = stack_pointer[-1];
values = stack_pointer - 1 - oparg;
+ TIER_ONE_ONLY
assert(oparg >= 0 && oparg <= 2);
if (oparg) {
PyObject *lasti = values[0];
PyObject *awaitable;
exc = stack_pointer[-1];
awaitable = stack_pointer[-2];
+ TIER_ONE_ONLY
assert(exc && PyExceptionInstance_Check(exc));
if (PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration)) {
Py_DECREF(awaitable);
exc_value = stack_pointer[-1];
last_sent_val = stack_pointer[-2];
sub_iter = stack_pointer[-3];
+ TIER_ONE_ONLY
assert(throwflag);
assert(exc_value && PyExceptionInstance_Check(exc_value));
if (PyErr_GivenExceptionMatches(exc_value, PyExc_StopIteration)) {
PyObject *initial = GETLOCAL(oparg);
PyObject *cell = PyCell_New(initial);
if (cell == NULL) {
- goto resume_with_error;
+ goto error;
}
SETLOCAL(oparg, cell);
DISPATCH();
PyObject *res;
fromlist = stack_pointer[-1];
level = stack_pointer[-2];
+ TIER_ONE_ONLY
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
res = import_name(tstate, frame, name, fromlist, level);
Py_DECREF(level);
PyObject *from;
PyObject *res;
from = stack_pointer[-1];
+ TIER_ONE_ONLY
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
res = import_from(tstate, from, name);
if (res == NULL) goto error;
TARGET(JUMP_BACKWARD) {
_Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr;
- next_instr += 1;
+ next_instr += 2;
INSTRUCTION_STATS(JUMP_BACKWARD);
CHECK_EVAL_BREAKER();
assert(oparg <= INSTR_OFFSET());
- JUMPBY(1-oparg);
+ JUMPBY(-oparg);
#if ENABLE_SPECIALIZATION
this_instr[1].cache += (1 << OPTIMIZER_BITS_IN_COUNTER);
if (this_instr[1].cache > tstate->interp->optimizer_backedge_threshold &&
frame->instr_ptr = next_instr;
next_instr += 1;
INSTRUCTION_STATS(ENTER_EXECUTOR);
+ TIER_ONE_ONLY
CHECK_EVAL_BREAKER();
PyCodeObject *code = _PyFrame_GetCode(frame);
PyObject *exit;
PyObject *res;
mgr = stack_pointer[-1];
+ TIER_ONE_ONLY
/* pop the context manager, push its __exit__ and the
* value returned from calling its __enter__
*/
TARGET(INSTRUMENTED_JUMP_BACKWARD) {
_Py_CODEUNIT *this_instr = frame->instr_ptr = next_instr;
- next_instr += 1;
+ next_instr += 2;
INSTRUCTION_STATS(INSTRUMENTED_JUMP_BACKWARD);
CHECK_EVAL_BREAKER();
- INSTRUMENTED_JUMP(this_instr, next_instr + 1 - oparg, PY_MONITORING_EVENT_JUMP);
+ INSTRUMENTED_JUMP(this_instr, next_instr - oparg, PY_MONITORING_EVENT_JUMP);
DISPATCH();
}
case parsing.Macro():
format = self.macro_instrs[thing.name].instr_fmt
case parsing.Pseudo():
- for target in self.pseudos[thing.name].targets:
- target_instr = self.instrs.get(target)
- assert target_instr
- if format is None:
- format = target_instr.instr_fmt
- else:
- assert format == target_instr.instr_fmt
+ # Pseudo instructions exist only in the compiler,
+ # so do not have a format
+ continue
case _:
assert_never(thing)
assert format is not None
self.out.emit("")
self.out.emit(
- "#define OPCODE_METADATA_FMT(OP) "
- "(_PyOpcode_opcode_metadata[(OP)].instr_format)"
+ "#define OPCODE_METADATA_FLAGS(OP) "
+ "(_PyOpcode_opcode_metadata[(OP)].flags & (HAS_ARG_FLAG | HAS_JUMP_FLAG))"
)
self.out.emit("#define SAME_OPCODE_METADATA(OP1, OP2) \\")
self.out.emit(
- " (OPCODE_METADATA_FMT(OP1) == OPCODE_METADATA_FMT(OP2))"
+ " (OPCODE_METADATA_FLAGS(OP1) == OPCODE_METADATA_FLAGS(OP2))"
)
self.out.emit("")
and not mac.name.startswith("INSTRUMENTED_")
):
self.out.emit(f"[{mac.name}] = {mac.cache_offset},")
- # Irregular case:
- self.out.emit("[JUMP_BACKWARD] = 1,")
deoptcodes = {}
for name, op in self.opmap.items():
f"{{ .nuops = {len(pieces)}, .uops = {{ {', '.join(pieces)} }} }},"
)
- def emit_metadata_entry(self, name: str, fmt: str, flags: InstructionFlags) -> None:
+ def emit_metadata_entry(self, name: str, fmt: str | None, flags: InstructionFlags) -> None:
flag_names = flags.names(value=True)
if not flag_names:
flag_names.append("0")
+ fmt_macro = "0" if fmt is None else INSTR_FMT_PREFIX + fmt
self.out.emit(
- f"[{name}] = {{ true, {INSTR_FMT_PREFIX}{fmt},"
+ f"[{name}] = {{ true, {fmt_macro},"
f" {' | '.join(flag_names)} }},"
)
def write_metadata_for_pseudo(self, ps: PseudoInstruction) -> None:
"""Write metadata for a macro-instruction."""
- self.emit_metadata_entry(ps.name, ps.instr_fmt, ps.instr_flags)
+ self.emit_metadata_entry(ps.name, None, ps.instr_flags)
def write_instructions(
self, output_filename: str, emit_line_directives: bool