Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Track locals as well as stack on differing paths
  • Loading branch information
markshannon committed Aug 9, 2024
commit 9838a05a681f1ce8700e5444a0dda93a8cc4acbf
2 changes: 2 additions & 0 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -1991,6 +1991,8 @@ dummy_func(
attr_o = PyObject_GetAttr(PyStackRef_AsPyObjectBorrow(owner), name);
DECREF_INPUTS();
ERROR_IF(attr_o == NULL, error);
/* We need to define self_or_null on all paths */
self_or_null = PyStackRef_NULL;
}
attr = PyStackRef_FromPyObjectSteal(attr_o);
}
Expand Down
2 changes: 2 additions & 0 deletions Python/executor_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Python/generated_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 18 additions & 7 deletions Python/optimizer_bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,9 @@ dummy_func(void) {
res = sym_new_type(ctx, &PyFloat_Type);
}
}
res = sym_new_unknown(ctx);
else {
res = sym_new_unknown(ctx);
}
}

op(_BINARY_OP_ADD_INT, (left, right -- res)) {
Expand Down Expand Up @@ -330,41 +332,47 @@ dummy_func(void) {
}

op(_TO_BOOL, (value -- res)) {
if (!optimize_to_bool(this_instr, ctx, value, &res)) {
int opt = optimize_to_bool(this_instr, ctx, value, &res);
if (!opt) {
res = sym_new_type(ctx, &PyBool_Type);
}
}

op(_TO_BOOL_BOOL, (value -- res)) {
if (!optimize_to_bool(this_instr, ctx, value, &res)) {
int opt = optimize_to_bool(this_instr, ctx, value, &res);
if (!opt) {
sym_set_type(value, &PyBool_Type);
res = value;
}
}

op(_TO_BOOL_INT, (value -- res)) {
if (!optimize_to_bool(this_instr, ctx, value, &res)) {
int opt = optimize_to_bool(this_instr, ctx, value, &res);
if (!opt) {
sym_set_type(value, &PyLong_Type);
res = sym_new_type(ctx, &PyBool_Type);
}
}

op(_TO_BOOL_LIST, (value -- res)) {
if (!optimize_to_bool(this_instr, ctx, value, &res)) {
int opt = optimize_to_bool(this_instr, ctx, value, &res);
if (!opt) {
sym_set_type(value, &PyList_Type);
res = sym_new_type(ctx, &PyBool_Type);
}
}

op(_TO_BOOL_NONE, (value -- res)) {
if (!optimize_to_bool(this_instr, ctx, value, &res)) {
int opt = optimize_to_bool(this_instr, ctx, value, &res);
if (!opt) {
sym_set_const(value, Py_None);
res = sym_new_const(ctx, Py_False);
}
}

op(_TO_BOOL_STR, (value -- res)) {
if (!optimize_to_bool(this_instr, ctx, value, &res)) {
int opt = optimize_to_bool(this_instr, ctx, value, &res);
if (!opt) {
res = sym_new_type(ctx, &PyBool_Type);
sym_set_type(value, &PyUnicode_Type);
}
Expand Down Expand Up @@ -475,6 +483,9 @@ dummy_func(void) {
if (oparg & 1) {
self_or_null = sym_new_unknown(ctx);
}
else {
self_or_null = NULL;
}
}

op(_LOAD_ATTR_MODULE, (index/1, owner -- attr, null if (oparg & 1))) {
Expand Down
25 changes: 18 additions & 7 deletions Python/optimizer_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions Tools/cases_generator/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,10 +374,16 @@ def find_stores_outputs(node: parser.InstDef) -> list[lexer.Token]:
res: list[lexer.Token] = []
outnames = [ out.name for out in node.outputs ]
for idx, tkn in enumerate(node.block.tokens):
if tkn.kind == "AND":
name = node.block.tokens[idx+1]
if name.text in outnames:
res.append(name)
if tkn.kind != "EQUALS":
continue
lhs = find_assignment_target(node, idx)
assert lhs
while lhs and lhs[0].kind == "COMMENT":
lhs = lhs[1:]
if len(lhs) != 1 or lhs[0].kind != "IDENTIFIER":
continue
name = lhs[0]
Expand Down
35 changes: 22 additions & 13 deletions Tools/cases_generator/generators_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,21 @@ def __init__(self, out: CWriter):
"CHECK_EVAL_BREAKER": self.check_eval_breaker,
"SYNC_SP": self.sync_sp,
"PyStackRef_FromPyObjectNew": self.py_stack_ref_from_py_object_new,
"DISPATCH": self.dispatch
}
self.out = out

def dispatch(
self,
tkn: Token,
tkn_iter: TokenIterator,
uop: Uop,
storage: Storage,
inst: Instruction | None,
) -> bool:
self.emit(tkn)
return False

def deopt_if(
self,
tkn: Token,
Expand Down Expand Up @@ -298,16 +310,14 @@ def _emit_if(
uop: Uop,
storage: Storage,
inst: Instruction | None,
) -> tuple[bool, Token, Stack]:
) -> tuple[bool, Token, Storage]:
""" Returns (reachable?, closing '}', stack)."""
tkn = next(tkn_iter)
assert (tkn.kind == "LPAREN")
self.out.emit(tkn)
rparen = emit_to(self.out, tkn_iter, "RPAREN")
self.emit(rparen)
stack = storage.stack
if_stack = stack.copy()
if_storage = Storage(if_stack, storage.outputs)
if_storage = storage.copy()
reachable, rbrace, if_stack = self._emit_block(tkn_iter, uop, if_storage, inst, True)
maybe_else = tkn_iter.peek()
if maybe_else and maybe_else.kind == "ELSE":
Expand All @@ -320,20 +330,20 @@ def _emit_if(
else:
else_reachable, rbrace, stack = self._emit_block(tkn_iter, uop, storage, inst, True)
if not reachable:
# Discard the if stack
# Discard the if storage
reachable = else_reachable
elif not else_reachable:
# Discard the else stack
stack = if_stack
# Discard the else storage
storage = if_storage
else:
stack = stack.merge(if_stack)
storage = storage.merge(if_storage, self.out)
else:
if reachable:
stack = stack.merge(if_stack)
storage = storage.merge(if_storage, self.out)
else:
# Discard the if stack
reachable = True
return reachable, rbrace, stack
return reachable, rbrace, storage

def _emit_block(
self,
Expand All @@ -342,12 +352,11 @@ def _emit_block(
storage: Storage,
inst: Instruction | None,
emit_first_brace: bool
) -> tuple[bool, Token, Stack]:
) -> tuple[bool, Token, Storage]:
""" Returns (reachable?, closing '}', stack)."""
braces = 1
out_stores = set(uop.output_stores)
tkn = next(tkn_iter)
stack = storage.stack
reachable = True
if tkn.kind != "LBRACE":
raise analysis_error(f"Expected '{{' found {tkn.text}", tkn)
Expand All @@ -360,7 +369,7 @@ def _emit_block(
elif tkn.kind == "RBRACE":
braces -= 1
if braces == 0:
return reachable, tkn, stack
return reachable, tkn, storage
self.out.emit(tkn)
elif tkn.kind == "GOTO":
reachable = False;
Expand Down
6 changes: 3 additions & 3 deletions Tools/cases_generator/optimizer_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ def write_uop(
skip_inputs: bool,
) -> None:
locals: dict[str, Local] = {}
prototype = override if override else uop
is_override = override is not None
try:
prototype = override if override else uop
is_override = override is not None
out.start_line()
for var in reversed(prototype.stack.inputs):
code, local = stack.pop(var, extract_bits=True)
Expand Down Expand Up @@ -144,7 +144,7 @@ def write_uop(
out.start_line()
stack.flush(out, cast_type="_Py_UopsSymbol *", extract_bits=True)
except StackError as ex:
raise analysis_error(ex.args[0], uop.body[0])
raise analysis_error(ex.args[0], prototype.body[0])


SKIPS = ("_EXTENDED_ARG",)
Expand Down
14 changes: 14 additions & 0 deletions Tools/cases_generator/stack.py
Original file line number Diff line number Diff line change
Expand Up @@ -448,3 +448,17 @@ def for_uop(stack: Stack, uop: Uop, locals: dict[str, Local]) -> "Storage":
local = Local.undefined(var)
outputs.append(local)
return Storage(stack, outputs)

def copy(self) -> "Storage":
return Storage(self.stack.copy(), [ l.copy() for l in self.outputs])

def merge(self, other: "Storage", out: CWriter) -> "Storage":
self.stack.merge(other.stack)
if self.outputs != other.outputs:
raise StackError("unequal locals")
return self

def as_comment(self) -> str:
stack_comment = self.stack.as_comment()
return stack_comment[:-2] + str(self.outputs) + " */"