mirror of
https://github.com/python/cpython.git
synced 2025-09-12 03:37:09 +00:00
gh-107901: add the HAS_EVAL_BREAK instruction flag (#108375)
This commit is contained in:
parent
5a25daa512
commit
5f41376e93
3 changed files with 28 additions and 21 deletions
36
Include/internal/pycore_opcode_metadata.h
generated
36
Include/internal/pycore_opcode_metadata.h
generated
|
@ -1158,12 +1158,14 @@ enum InstructionFormat {
|
||||||
#define HAS_JUMP_FLAG (8)
|
#define HAS_JUMP_FLAG (8)
|
||||||
#define HAS_FREE_FLAG (16)
|
#define HAS_FREE_FLAG (16)
|
||||||
#define HAS_LOCAL_FLAG (32)
|
#define HAS_LOCAL_FLAG (32)
|
||||||
|
#define HAS_EVAL_BREAK_FLAG (64)
|
||||||
#define OPCODE_HAS_ARG(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_ARG_FLAG))
|
#define OPCODE_HAS_ARG(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_ARG_FLAG))
|
||||||
#define OPCODE_HAS_CONST(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_CONST_FLAG))
|
#define OPCODE_HAS_CONST(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_CONST_FLAG))
|
||||||
#define OPCODE_HAS_NAME(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_NAME_FLAG))
|
#define OPCODE_HAS_NAME(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_NAME_FLAG))
|
||||||
#define OPCODE_HAS_JUMP(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_JUMP_FLAG))
|
#define OPCODE_HAS_JUMP(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_JUMP_FLAG))
|
||||||
#define OPCODE_HAS_FREE(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_FREE_FLAG))
|
#define OPCODE_HAS_FREE(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_FREE_FLAG))
|
||||||
#define OPCODE_HAS_LOCAL(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_LOCAL_FLAG))
|
#define OPCODE_HAS_LOCAL(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_LOCAL_FLAG))
|
||||||
|
#define OPCODE_HAS_EVAL_BREAK(OP) (_PyOpcode_opcode_metadata[OP].flags & (HAS_EVAL_BREAK_FLAG))
|
||||||
|
|
||||||
struct opcode_metadata {
|
struct opcode_metadata {
|
||||||
bool valid_entry;
|
bool valid_entry;
|
||||||
|
@ -1196,8 +1198,8 @@ extern const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SI
|
||||||
#ifdef NEED_OPCODE_METADATA
|
#ifdef NEED_OPCODE_METADATA
|
||||||
const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = {
|
const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = {
|
||||||
[NOP] = { true, INSTR_FMT_IX, 0 },
|
[NOP] = { true, INSTR_FMT_IX, 0 },
|
||||||
[RESUME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
|
[RESUME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG },
|
||||||
[INSTRUMENTED_RESUME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
|
[INSTRUMENTED_RESUME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG },
|
||||||
[LOAD_CLOSURE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG },
|
[LOAD_CLOSURE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG },
|
||||||
[LOAD_FAST_CHECK] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG },
|
[LOAD_FAST_CHECK] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG },
|
||||||
[LOAD_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG },
|
[LOAD_FAST] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_LOCAL_FLAG },
|
||||||
|
@ -1333,10 +1335,10 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = {
|
||||||
[IMPORT_NAME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG },
|
[IMPORT_NAME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG },
|
||||||
[IMPORT_FROM] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG },
|
[IMPORT_FROM] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_NAME_FLAG },
|
||||||
[JUMP_FORWARD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_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 },
|
[JUMP_BACKWARD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EVAL_BREAK_FLAG },
|
||||||
[JUMP] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_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_NO_INTERRUPT] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG },
|
||||||
[ENTER_EXECUTOR] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG },
|
[ENTER_EXECUTOR] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EVAL_BREAK_FLAG },
|
||||||
[POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG },
|
[POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG },
|
||||||
[POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG },
|
[POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG },
|
||||||
[POP_JUMP_IF_NONE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG },
|
[POP_JUMP_IF_NONE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG },
|
||||||
|
@ -1370,28 +1372,28 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = {
|
||||||
[LOAD_ATTR_METHOD_LAZY_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG },
|
[LOAD_ATTR_METHOD_LAZY_DICT] = { true, INSTR_FMT_IBC00000000, HAS_ARG_FLAG },
|
||||||
[KW_NAMES] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_CONST_FLAG },
|
[KW_NAMES] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_CONST_FLAG },
|
||||||
[INSTRUMENTED_CALL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
|
[INSTRUMENTED_CALL] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
|
||||||
[CALL] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
|
[CALL] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG },
|
||||||
[CALL_BOUND_METHOD_EXACT_ARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
|
[CALL_BOUND_METHOD_EXACT_ARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
|
||||||
[CALL_PY_EXACT_ARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
|
[CALL_PY_EXACT_ARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
|
||||||
[CALL_PY_WITH_DEFAULTS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
|
[CALL_PY_WITH_DEFAULTS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
|
||||||
[CALL_NO_KW_TYPE_1] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
|
[CALL_NO_KW_TYPE_1] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
|
||||||
[CALL_NO_KW_STR_1] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
|
[CALL_NO_KW_STR_1] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG },
|
||||||
[CALL_NO_KW_TUPLE_1] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
|
[CALL_NO_KW_TUPLE_1] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG },
|
||||||
[CALL_NO_KW_ALLOC_AND_ENTER_INIT] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
|
[CALL_NO_KW_ALLOC_AND_ENTER_INIT] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
|
||||||
[EXIT_INIT_CHECK] = { true, INSTR_FMT_IX, 0 },
|
[EXIT_INIT_CHECK] = { true, INSTR_FMT_IX, 0 },
|
||||||
[CALL_BUILTIN_CLASS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
|
[CALL_BUILTIN_CLASS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG },
|
||||||
[CALL_NO_KW_BUILTIN_O] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
|
[CALL_NO_KW_BUILTIN_O] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG },
|
||||||
[CALL_NO_KW_BUILTIN_FAST] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
|
[CALL_NO_KW_BUILTIN_FAST] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG },
|
||||||
[CALL_BUILTIN_FAST_WITH_KEYWORDS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
|
[CALL_BUILTIN_FAST_WITH_KEYWORDS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG },
|
||||||
[CALL_NO_KW_LEN] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
|
[CALL_NO_KW_LEN] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
|
||||||
[CALL_NO_KW_ISINSTANCE] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
|
[CALL_NO_KW_ISINSTANCE] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
|
||||||
[CALL_NO_KW_LIST_APPEND] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
|
[CALL_NO_KW_LIST_APPEND] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
|
||||||
[CALL_NO_KW_METHOD_DESCRIPTOR_O] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
|
[CALL_NO_KW_METHOD_DESCRIPTOR_O] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG },
|
||||||
[CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
|
[CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG },
|
||||||
[CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
|
[CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG },
|
||||||
[CALL_NO_KW_METHOD_DESCRIPTOR_FAST] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG },
|
[CALL_NO_KW_METHOD_DESCRIPTOR_FAST] = { true, INSTR_FMT_IBC00, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG },
|
||||||
[INSTRUMENTED_CALL_FUNCTION_EX] = { true, INSTR_FMT_IX, 0 },
|
[INSTRUMENTED_CALL_FUNCTION_EX] = { true, INSTR_FMT_IX, 0 },
|
||||||
[CALL_FUNCTION_EX] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
|
[CALL_FUNCTION_EX] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG },
|
||||||
[MAKE_FUNCTION] = { true, INSTR_FMT_IX, 0 },
|
[MAKE_FUNCTION] = { true, INSTR_FMT_IX, 0 },
|
||||||
[SET_FUNCTION_ATTRIBUTE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
|
[SET_FUNCTION_ATTRIBUTE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
|
||||||
[RETURN_GENERATOR] = { true, INSTR_FMT_IX, 0 },
|
[RETURN_GENERATOR] = { true, INSTR_FMT_IX, 0 },
|
||||||
|
@ -1404,7 +1406,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[OPCODE_METADATA_SIZE] = {
|
||||||
[SWAP] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
|
[SWAP] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
|
||||||
[INSTRUMENTED_INSTRUCTION] = { true, INSTR_FMT_IX, 0 },
|
[INSTRUMENTED_INSTRUCTION] = { true, INSTR_FMT_IX, 0 },
|
||||||
[INSTRUMENTED_JUMP_FORWARD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
|
[INSTRUMENTED_JUMP_FORWARD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
|
||||||
[INSTRUMENTED_JUMP_BACKWARD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
|
[INSTRUMENTED_JUMP_BACKWARD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG },
|
||||||
[INSTRUMENTED_POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
|
[INSTRUMENTED_POP_JUMP_IF_TRUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
|
||||||
[INSTRUMENTED_POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
|
[INSTRUMENTED_POP_JUMP_IF_FALSE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
|
||||||
[INSTRUMENTED_POP_JUMP_IF_NONE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
|
[INSTRUMENTED_POP_JUMP_IF_NONE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
|
||||||
|
|
|
@ -381,7 +381,8 @@ class Analyzer:
|
||||||
# Make sure the targets have the same fmt
|
# Make sure the targets have the same fmt
|
||||||
fmts = list(set([t.instr_fmt for t in targets]))
|
fmts = list(set([t.instr_fmt for t in targets]))
|
||||||
assert len(fmts) == 1
|
assert len(fmts) == 1
|
||||||
assert len(list(set([t.instr_flags.bitmap() for t in targets]))) == 1
|
ignored_flags = {'HAS_EVAL_BREAK_FLAG'}
|
||||||
|
assert len({t.instr_flags.bitmap(ignore=ignored_flags) for t in targets}) == 1
|
||||||
return PseudoInstruction(pseudo.name, targets, fmts[0], targets[0].instr_flags)
|
return PseudoInstruction(pseudo.name, targets, fmts[0], targets[0].instr_flags)
|
||||||
|
|
||||||
def analyze_instruction(
|
def analyze_instruction(
|
||||||
|
|
|
@ -3,6 +3,7 @@ import dataclasses
|
||||||
from formatting import Formatter
|
from formatting import Formatter
|
||||||
import lexer as lx
|
import lexer as lx
|
||||||
import parsing
|
import parsing
|
||||||
|
from typing import AbstractSet
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass
|
@dataclasses.dataclass
|
||||||
|
@ -15,6 +16,7 @@ class InstructionFlags:
|
||||||
HAS_JUMP_FLAG: bool
|
HAS_JUMP_FLAG: bool
|
||||||
HAS_FREE_FLAG: bool
|
HAS_FREE_FLAG: bool
|
||||||
HAS_LOCAL_FLAG: bool
|
HAS_LOCAL_FLAG: bool
|
||||||
|
HAS_EVAL_BREAK_FLAG: bool
|
||||||
|
|
||||||
def __post_init__(self) -> None:
|
def __post_init__(self) -> None:
|
||||||
self.bitmask = {name: (1 << i) for i, name in enumerate(self.names())}
|
self.bitmask = {name: (1 << i) for i, name in enumerate(self.names())}
|
||||||
|
@ -37,11 +39,12 @@ class InstructionFlags:
|
||||||
variable_used(instr, "GETLOCAL") or variable_used(instr, "SETLOCAL")
|
variable_used(instr, "GETLOCAL") or variable_used(instr, "SETLOCAL")
|
||||||
)
|
)
|
||||||
and not has_free,
|
and not has_free,
|
||||||
|
HAS_EVAL_BREAK_FLAG=variable_used(instr, "CHECK_EVAL_BREAKER"),
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def newEmpty() -> "InstructionFlags":
|
def newEmpty() -> "InstructionFlags":
|
||||||
return InstructionFlags(False, False, False, False, False, False)
|
return InstructionFlags(False, False, False, False, False, False, False)
|
||||||
|
|
||||||
def add(self, other: "InstructionFlags") -> None:
|
def add(self, other: "InstructionFlags") -> None:
|
||||||
for name, value in dataclasses.asdict(other).items():
|
for name, value in dataclasses.asdict(other).items():
|
||||||
|
@ -53,10 +56,11 @@ class InstructionFlags:
|
||||||
return list(dataclasses.asdict(self).keys())
|
return list(dataclasses.asdict(self).keys())
|
||||||
return [n for n, v in dataclasses.asdict(self).items() if v == value]
|
return [n for n, v in dataclasses.asdict(self).items() if v == value]
|
||||||
|
|
||||||
def bitmap(self) -> int:
|
def bitmap(self, ignore: AbstractSet[str] = frozenset()) -> int:
|
||||||
flags = 0
|
flags = 0
|
||||||
|
assert all(hasattr(self, name) for name in ignore)
|
||||||
for name in self.names():
|
for name in self.names():
|
||||||
if getattr(self, name):
|
if getattr(self, name) and name not in ignore:
|
||||||
flags |= self.bitmask[name]
|
flags |= self.bitmask[name]
|
||||||
return flags
|
return flags
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue