summaryrefslogtreecommitdiffstats
path: root/Tools/cases_generator
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2023-11-09 11:19:51 (GMT)
committerGitHub <noreply@github.com>2023-11-09 11:19:51 (GMT)
commit25c49564880e6868e4c76602f9f1650f0bc71c75 (patch)
tree4708ad2263b88f3a37cf5f057976aaf5d06f9b43 /Tools/cases_generator
parent6046aec377311efb89c4438f7cf412e2c6568ba1 (diff)
downloadcpython-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.py2
-rw-r--r--Tools/cases_generator/flags.py54
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