mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
gh-118926: Spill deferred references to stack in cases generator (#122748)
This automatically spills the results from `_PyStackRef_FromPyObjectNew` to the in-memory stack so that the deferred references are visible to the GC before we make any possibly escaping call. Co-authored-by: Ken Jin <kenjin@python.org>
This commit is contained in:
parent
967a4f1d18
commit
3e753c689a
9 changed files with 176 additions and 63 deletions
|
@ -256,21 +256,26 @@ class Stack:
|
|||
top_offset.push(var)
|
||||
return "\n".join(res)
|
||||
|
||||
@staticmethod
|
||||
def _do_emit(out: CWriter, var: StackItem, base_offset: StackOffset,
|
||||
cast_type: str = "uintptr_t", extract_bits: bool = False) -> None:
|
||||
cast = f"({cast_type})" if var.type else ""
|
||||
bits = ".bits" if cast and not extract_bits else ""
|
||||
if var.condition == "0":
|
||||
return
|
||||
if var.condition and var.condition != "1":
|
||||
out.emit(f"if ({var.condition}) ")
|
||||
out.emit(
|
||||
f"stack_pointer[{base_offset.to_c()}]{bits} = {cast}{var.name};\n"
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _do_flush(out: CWriter, variables: list[Local], base_offset: StackOffset, top_offset: StackOffset,
|
||||
cast_type: str = "uintptr_t", extract_bits: bool = False) -> None:
|
||||
out.start_line()
|
||||
for var in variables:
|
||||
if var.cached and not var.in_memory and not var.item.peek and not var.name in UNUSED:
|
||||
cast = f"({cast_type})" if var.item.type else ""
|
||||
bits = ".bits" if cast and not extract_bits else ""
|
||||
if var.condition == "0":
|
||||
continue
|
||||
if var.condition and var.condition != "1":
|
||||
out.emit(f"if ({var.condition}) ")
|
||||
out.emit(
|
||||
f"stack_pointer[{base_offset.to_c()}]{bits} = {cast}{var.name};\n"
|
||||
)
|
||||
Stack._do_emit(out, var.item, base_offset, cast_type, extract_bits)
|
||||
base_offset.push(var.item)
|
||||
if base_offset.to_c() != top_offset.to_c():
|
||||
print("base", base_offset, "top", top_offset)
|
||||
|
@ -290,6 +295,26 @@ class Stack:
|
|||
self.base_offset.clear()
|
||||
self.top_offset.clear()
|
||||
|
||||
def flush_single_var(self, out: CWriter, var_name: str, outputs: list[StackItem],
|
||||
cast_type: str = "uintptr_t", extract_bits: bool = False) -> None:
|
||||
assert any(var.name == var_name for var in outputs)
|
||||
base_offset = self.base_offset.copy()
|
||||
top_offset = self.top_offset.copy()
|
||||
for var in self.variables:
|
||||
base_offset.push(var.item)
|
||||
for var in outputs:
|
||||
if any(var == v.item for v in self.variables):
|
||||
# The variable is already on the stack, such as a peeked value
|
||||
# in the tier1 generator
|
||||
continue
|
||||
if var.name == var_name:
|
||||
Stack._do_emit(out, var, base_offset, cast_type, extract_bits)
|
||||
base_offset.push(var)
|
||||
top_offset.push(var)
|
||||
if base_offset.to_c() != top_offset.to_c():
|
||||
print("base", base_offset, "top", top_offset)
|
||||
assert False
|
||||
|
||||
def peek_offset(self) -> str:
|
||||
return self.top_offset.to_c()
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue