Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -4074,9 +4074,10 @@ dummy_func(
assert(oparg == 1);
STAT_INC(CALL, hit);
PyObject *res_o = PySequence_Tuple(arg_o);
DEAD(null);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
DEAD(null);

No need to declare null dead here as it will be handled by INPUTS_DEAD below.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is required so that ERROR_IF doesn't emit a useless close for it.

ERROR_IF(res_o == NULL);
a = arg;
INPUTS_DEAD();
ERROR_IF(res_o == NULL);
res = PyStackRef_FromPyObjectSteal(res_o);
}

Expand Down
16 changes: 14 additions & 2 deletions Python/executor_cases.c.h

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

12 changes: 11 additions & 1 deletion Python/generated_cases.c.h

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

2 changes: 1 addition & 1 deletion Tools/cases_generator/generators_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ def error_if(
emit_to(self.out, tkn_iter, "RPAREN")
self.out.emit(") {\n")
next(tkn_iter) # Semi colon
storage.clear_inputs("at ERROR_IF")
storage.clear_inputs_and_close_live_ones(self.out)

c_offset = storage.stack.sp_offset()
try:
Expand Down
87 changes: 49 additions & 38 deletions Tools/cases_generator/stack.py
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,7 @@ class Storage:
peeks: int
check_liveness: bool
spilled: int = 0
tmp_defined: bool = False

@staticmethod
def needs_defining(var: Local) -> bool:
Expand Down Expand Up @@ -474,6 +475,16 @@ def clear_inputs(self, reason:str) -> None:
)
self.stack.drop(tos.item, self.check_liveness)

def clear_inputs_and_close_live_ones(self, out: CWriter) -> None:
while len(self.inputs) > self.peeks:
tos = self.inputs.pop()
if self.is_live(tos):
self.close_variable(out, tos, "PyStackRef_NULL")
tos.kill()
out.start_line()
self.stack.drop(tos.item, self.check_liveness)


def clear_dead_inputs(self) -> None:
live = ""
while len(self.inputs) > self.peeks:
Expand Down Expand Up @@ -655,43 +666,43 @@ def _print(self, out: CWriter) -> None:
if PRINT_STACKS:
out.emit(self.as_comment() + "\n")

def close_named(self, out: CWriter, close: str, name: str, overwrite: str) -> None:
if overwrite:
if not self.tmp_defined:
out.emit("_PyStackRef ")
self.tmp_defined = True
out.emit(f"tmp = {name};\n")
out.emit(f"{name} = {overwrite};\n")
self.stack.save_variables(out)
out.emit(f"{close}(tmp);\n")
else:
out.emit(f"{close}({name});\n")

def close_variable(self, out: CWriter, var: Local, overwrite: str) -> None:
close = "PyStackRef_CLOSE"
if "null" in var.name:
close = "PyStackRef_XCLOSE"
var.memory_offset = None
self.save(out)
out.start_line()
if var.size:
if var.size == "1":
self.close_named(out, close, f"{var.name}[0]", overwrite)
else:
if overwrite and not self.tmp_defined:
out.emit("_PyStackRef tmp;\n")
self.tmp_defined = True
out.emit(f"for (int _i = {var.size}; --_i >= 0;) {{\n")
self.close_named(out, close, f"{var.name}[_i]", overwrite)
out.emit("}\n")
else:
self.close_named(out, close, var.name, overwrite)
self.reload(out)


def close_inputs(self, out: CWriter) -> None:

tmp_defined = False
def close_named(close: str, name: str, overwrite: str) -> None:
nonlocal tmp_defined
if overwrite:
if not tmp_defined:
out.emit("_PyStackRef ")
tmp_defined = True
out.emit(f"tmp = {name};\n")
out.emit(f"{name} = {overwrite};\n")
self.stack.save_variables(out)
out.emit(f"{close}(tmp);\n")
else:
out.emit(f"{close}({name});\n")

def close_variable(var: Local, overwrite: str) -> None:
nonlocal tmp_defined
close = "PyStackRef_CLOSE"
if "null" in var.name:
close = "PyStackRef_XCLOSE"
var.memory_offset = None
self.save(out)
out.start_line()
if var.size:
if var.size == "1":
close_named(close, f"{var.name}[0]", overwrite)
else:
if overwrite and not tmp_defined:
out.emit("_PyStackRef tmp;\n")
tmp_defined = True
out.emit(f"for (int _i = {var.size}; --_i >= 0;) {{\n")
close_named(close, f"{var.name}[_i]", overwrite)
out.emit("}\n")
else:
close_named(close, var.name, overwrite)
self.reload(out)

self.clear_dead_inputs()
if not self.inputs:
Expand All @@ -713,20 +724,20 @@ def close_variable(var: Local, overwrite: str) -> None:
self.stack.drop(self.inputs[0].item, False)
self.stack.push(output)
self.stack.flush(out)
close_variable(self.inputs[0], "")
self.close_variable(out, self.inputs[0], "")
self.stack.drop(output.item, self.check_liveness)
self.inputs = []
return
if var_size(lowest.item) != var_size(output.item):
raise StackError("Cannot call DECREF_INPUTS with live output not matching first input size")
self.stack.flush(out)
lowest.in_local = True
close_variable(lowest, output.name)
self.close_variable(out, lowest, output.name)
assert lowest.memory_offset is not None
for input in reversed(self.inputs[1:]):
close_variable(input, "PyStackRef_NULL")
self.close_variable(out, input, "PyStackRef_NULL")
if output is None:
close_variable(self.inputs[0], "PyStackRef_NULL")
self.close_variable(out, self.inputs[0], "PyStackRef_NULL")
for input in reversed(self.inputs[1:]):
input.kill()
self.stack.drop(input.item, self.check_liveness)
Expand Down
Loading