Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-118926: Spill deferred references to stack in cases generator #122748

Merged
merged 5 commits into from
Aug 7, 2024

Conversation

colesbury
Copy link
Contributor

@colesbury colesbury commented Aug 6, 2024

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.

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>
@colesbury
Copy link
Contributor Author

@markshannon, this is the spilling logic split out from:

I've updated it to handle the changes to the stack from #122286. This required tracking output local variables in the stack before emitting tokens for a uop.

I've also moved the analysis to analyzer.py.

Copy link
Member

@markshannon markshannon left a comment

Choose a reason for hiding this comment

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

The stack shouldn't have "outputs" (or inputs) as it should model the state of the stack only.
The outputs (or inputs) are properties of the uops and instructions.

That can be fixed by passing the output variables to flush_single_var instead of caching them on the stack.

Note:
I think the correct long term approach to handling stack spilling is to lazily spill when code escapes. But that involves considerably deeper analysis.
Although this PR doesn't do that, it doesn't prevent us from doing in future. So I am happy to merge it once the above issue is fixed.

if tkn.kind != "IDENTIFIER" or tkn.text != "PyStackRef_FromPyObjectNew":
continue

if node.block.tokens[idx-1].kind != "EQUALS":
Copy link
Member

@markshannon markshannon Aug 7, 2024

Choose a reason for hiding this comment

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

I think this is OK, as the first token should be the opening brace. Could you add a comment as to why this is safe.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think that's right, but I'll add condition to ensure that idx != 0 to make it explicit.

@@ -169,6 +169,7 @@ def __init__(self) -> None:
self.top_offset = StackOffset.empty()
self.base_offset = StackOffset.empty()
self.variables: list[Local] = []
self.outputs: list[Local] = []
Copy link
Member

Choose a reason for hiding this comment

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

The stack shouldn't have "outputs" (or inputs) as it should model the state of the stack.
The outputs (or inputs) are properties of the uops and instructions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've removed this

@@ -290,6 +302,22 @@ def flush(self, out: CWriter, cast_type: str = "uintptr_t", extract_bits: bool =
self.base_offset.clear()
self.top_offset.clear()

def flush_single_var(self, out: CWriter, var_name: str, cast_type: str = "uintptr_t", extract_bits: bool = False) -> None:
Copy link
Member

Choose a reason for hiding this comment

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

Rather than caching outputs on the stack, can you pass outputs as a list[StackItem] argument?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added outputs as a list[StackItem]

@@ -112,7 +112,14 @@ def write_uop(
out.emit(code)
if local.defined:
locals[local.name] = local
out.emit(stack.define_output_arrays(prototype.stack.outputs))
outputs: list[Local] = []
Copy link
Member

Choose a reason for hiding this comment

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

The optimizer generator doesn't need to track the state of locals, nor is the GC involved, so shouldn't change.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've reverted the changes to optimizer_generator.py

@bedevere-app
Copy link

bedevere-app bot commented Aug 7, 2024

When you're done making the requested changes, leave the comment: I have made the requested changes; please review again.

And if you don't make the requested changes, you will be poked with soft cushions!

@colesbury
Copy link
Contributor Author

@markshannon, would you please take another look at it.

I have made the requested changes; please review again

@bedevere-app
Copy link

bedevere-app bot commented Aug 7, 2024

Thanks for making the requested changes!

@markshannon: please review the changes made to this pull request.

@bedevere-app bedevere-app bot requested a review from markshannon August 7, 2024 15:01
Copy link
Member

@markshannon markshannon left a comment

Choose a reason for hiding this comment

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

Thanks for bearing with me on this one.

@colesbury colesbury added the 🔨 test-with-refleak-buildbots Test PR w/ refleak buildbots; report in status section label Aug 7, 2024
@bedevere-bot
Copy link

🤖 New build scheduled with the buildbot fleet by @colesbury for commit ae1c018 🤖

If you want to schedule another build, you need to add the 🔨 test-with-refleak-buildbots label again.

@bedevere-bot bedevere-bot removed the 🔨 test-with-refleak-buildbots Test PR w/ refleak buildbots; report in status section label Aug 7, 2024
@colesbury colesbury merged commit 3e753c6 into python:main Aug 7, 2024
70 of 74 checks passed
@colesbury colesbury deleted the gh-118926-flush-v2 branch August 7, 2024 17:23
blhsing pushed a commit to blhsing/cpython that referenced this pull request Aug 22, 2024
python#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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants