diff options
author | Mark Shannon <mark@hotpy.org> | 2023-11-09 11:19:51 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-09 11:19:51 (GMT) |
commit | 25c49564880e6868e4c76602f9f1650f0bc71c75 (patch) | |
tree | 4708ad2263b88f3a37cf5f057976aaf5d06f9b43 /Tools/cases_generator | |
parent | 6046aec377311efb89c4438f7cf412e2c6568ba1 (diff) | |
download | cpython-25c49564880e6868e4c76602f9f1650f0bc71c75.zip cpython-25c49564880e6868e4c76602f9f1650f0bc71c75.tar.gz cpython-25c49564880e6868e4c76602f9f1650f0bc71c75.tar.bz2 |
GH-109369: Exit tier 2 if executor is invalid (GH-111657)
Diffstat (limited to 'Tools/cases_generator')
-rw-r--r-- | Tools/cases_generator/analysis.py | 2 | ||||
-rw-r--r-- | Tools/cases_generator/flags.py | 54 |
2 files changed, 55 insertions, 1 deletions
diff --git a/Tools/cases_generator/analysis.py b/Tools/cases_generator/analysis.py index ee93b88..603b155 100644 --- a/Tools/cases_generator/analysis.py +++ b/Tools/cases_generator/analysis.py @@ -390,7 +390,7 @@ class Analyzer: else: targets.append(self.macro_instrs[target_name]) assert targets - ignored_flags = {"HAS_EVAL_BREAK_FLAG", "HAS_DEOPT_FLAG", "HAS_ERROR_FLAG"} + ignored_flags = {"HAS_EVAL_BREAK_FLAG", "HAS_DEOPT_FLAG", "HAS_ERROR_FLAG", "HAS_ESCAPES_FLAG"} assert len({t.instr_flags.bitmap(ignore=ignored_flags) for t in targets}) == 1 return PseudoInstruction(pseudo.name, targets, targets[0].instr_flags) diff --git a/Tools/cases_generator/flags.py b/Tools/cases_generator/flags.py index 5241331..42e1763 100644 --- a/Tools/cases_generator/flags.py +++ b/Tools/cases_generator/flags.py @@ -5,6 +5,55 @@ import lexer as lx import parsing from typing import AbstractSet +WHITELIST = ( + "Py_INCREF", + "_PyDictOrValues_IsValues", + "_PyObject_DictOrValuesPointer", + "_PyDictOrValues_GetValues", + "_PyObject_MakeInstanceAttributesFromDict", + "Py_DECREF", + "_Py_DECREF_SPECIALIZED", + "DECREF_INPUTS_AND_REUSE_FLOAT", + "PyUnicode_Append", + "_PyLong_IsZero", + "Py_SIZE", + "Py_TYPE", + "PyList_GET_ITEM", + "PyTuple_GET_ITEM", + "PyList_GET_SIZE", + "PyTuple_GET_SIZE", + "Py_ARRAY_LENGTH", + "Py_Unicode_GET_LENGTH", + "PyUnicode_READ_CHAR", + "_Py_SINGLETON", + "PyUnicode_GET_LENGTH", + "_PyLong_IsCompact", + "_PyLong_IsNonNegativeCompact", + "_PyLong_CompactValue", + "_Py_NewRef", +) + +def makes_escaping_api_call(instr: parsing.Node) -> bool: + tkns = iter(instr.tokens) + for tkn in tkns: + if tkn.kind != lx.IDENTIFIER: + continue + try: + next_tkn = next(tkns) + except StopIteration: + return False + if next_tkn.kind != lx.LPAREN: + continue + if not tkn.text.startswith("Py") and not tkn.text.startswith("_Py"): + continue + if tkn.text.endswith("Check"): + continue + if tkn.text.endswith("CheckExact"): + continue + if tkn.text in WHITELIST: + continue + return True + return False @dataclasses.dataclass class InstructionFlags: @@ -19,6 +68,7 @@ class InstructionFlags: HAS_EVAL_BREAK_FLAG: bool = False HAS_DEOPT_FLAG: bool = False HAS_ERROR_FLAG: bool = False + HAS_ESCAPES_FLAG: bool = False def __post_init__(self) -> None: self.bitmask = {name: (1 << i) for i, name in enumerate(self.names())} @@ -50,6 +100,10 @@ class InstructionFlags: or variable_used(instr, "exception_unwind") or variable_used(instr, "resume_with_error") ), + HAS_ESCAPES_FLAG=( + variable_used(instr, "tstate") + or makes_escaping_api_call(instr) + ), ) @staticmethod |