Skip to content

Conversation

@colesbury
Copy link
Contributor

@colesburycolesbury 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
ContributorAuthor

@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

@markshannonmarkshannon 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.

iftkn.kind!="IDENTIFIER"ortkn.text!="PyStackRef_FromPyObjectNew":
continue

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

@markshannonmarkshannonAug 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
ContributorAuthor

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.

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
ContributorAuthor

Choose a reason for hiding this comment

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

I've removed this

self.base_offset.clear()
self.top_offset.clear()

defflush_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
ContributorAuthor

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]

iflocal.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
ContributorAuthor

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

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
ContributorAuthor

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

I have made the requested changes; please review again

@bedevere-app
Copy link

Thanks for making the requested changes!

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

Copy link
Member

@markshannonmarkshannon 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.

@colesburycolesbury 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-botbedevere-bot removed the 🔨 test-with-refleak-buildbots Test PR w/ refleak buildbots; report in status section label Aug 7, 2024
@colesburycolesbury merged commit 3e753c6 into python:mainAug 7, 2024
@colesburycolesbury 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 freeto 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

@colesbury@bedevere-bot@markshannon