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.
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.
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?
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?