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

cmd/compile: open-coded defers keep pointer arguments alive past the deferred call #44623

Open
mdempsky opened this issue Feb 25, 2021 · 4 comments
Open
Assignees
Labels

Comments

@mdempsky
Copy link
Member

@mdempsky mdempsky commented Feb 25, 2021

It looks like open-coded defers are keeping their arguments alive past the deferred call:

Failing test case using open-coded defer: https://play.golang.org/p/9SEiOeaLmCS

Passing test case using heap-allocated defer: https://play.golang.org/p/BWEQuC5EowK

In these tests, there are two deferred function calls. The first call needs p kept alive, but the second does not. We should be able to collect p (and run its finalizer) as soon as the first deferred function call returns. The heap-allocated defer does this, but the open-coded one does not.

/cc @danscales

@danscales
Copy link

@danscales danscales commented Mar 10, 2021

Yes, we now keep all open-defer arg slots live throughout the whole function. This is to deal with all the unusual cases where a function may never exit (at all or when it reaches certain points in the function). This makes it very hard to use liveness analysis to determine if a defer arg is no longer alive. At these points where the function can't exit, it looks like the defer args shouldn't be live, but of course the function may panic at almost any point, so they actually must be kept live. Keith and I decided we didn't want to make the compiler more complex, just to adjust the liveness properties of variables that people shouldn't really be depending on.

But I will ponder a bit and see if there is any relatively easy approach that we are still missing.

@randall77
Copy link
Contributor

@randall77 randall77 commented Mar 10, 2021

In order to not scan the arguments, we'd have to make the pointer bitmap dependent on more than just the PC. It would also have to depend on the bitmask of defers.

Could we zero the (pointer-containing) argument slots in the frame just before we call the deferred function? It could be tricky to do the zeroing while assembling the arguments, but may be possible.

@danscales
Copy link

@danscales danscales commented Mar 11, 2021

We already zero out all defer arg slots that have pointers in them at the beginning of the function. Those will still be zero if the defer was not actually activated. So, I don't think you have to depend on the defer bitmask, right?

@randall77
Copy link
Contributor

@randall77 randall77 commented Mar 11, 2021

We already zero out all defer arg slots that have pointers in them at the beginning of the function. Those will still be zero if the defer was not actually activated.

Right, but I don't think that's the issue here.

The issue is if the defer is activated, and then at the end of the function we run it, it returns, some other defer is then run, and at that point we do a GC scan of the stack. Are the arguments for the defer that already completed still alive?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants