-
Notifications
You must be signed in to change notification settings - Fork 18k
cmd/compile: allocate some defers in stack frames #6980
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
Comments
I sketched this during gophercon. The 6g-only CL is in https://golang.org/cl/100300043 although it also has an unrelated ... fix for escape analysis mixed in. It made basically no difference for things that hit Dmitriy's latest defer cache. For strangely-sized defers it might help and be worth doing. |
The code in stack.c suggests the opposite: for(dp = &gp->defer, d = *dp; d != nil; dp = &d->link, d = *dp) { if(adjinfo->old.lo <= (uintptr)d && (uintptr)d < adjinfo->old.hi) { // The Defer record is on the stack. Its fields will // get adjusted appropriately. // This only happens for runtime.main and runtime.gopanic now, // but a compiler optimization could do more of this. // If such an optimization were introduced, Defer.argp should // change to have pointer type so that it will be updated by // the stack copying. Today both of those on-stack defers // set argp = NoArgs, so no adjustment is necessary. *dp = (Defer*)((byte*)d + adjinfo->delta); continue; } Labels changed: added release-go1.5, removed release-none. Status changed to Accepted. |
Russ is a bit ahead of himself - this will be the case when https://golang.org/cl/141490043/ is in. |
It is probably possible to make work. However, I benchmarked it (patch in the CL above) and it just doesn't matter. The defer cache takes care of nearly all the win. It is not worth it. I will leave this open but it is not targeted to a release. Labels changed: added release-none, removed release-go1.5. |
The compiler also needs to *fill* in the struct and link it into g->defer, and on successful return unlink from g->defer inline. That would provide the speedup. Today the single defer in net.Conn.Read/Write consumes 2.5% of time in the end-to-end HTTP benchmark: http://build.golang.org/log/33d55778f33682e4e1d45e7c825a73d2ea500de7 Defer is not something that must be visible in a profile of such program. We don't want to wipe defers from std lib due to performance, right? I guess there are Go users who already do this with their libraries. |
Okay, well that might work. Defers will need more care in the stack copier if they get stack-allocated, because the Defer chain will weave between allocated memory and the stack, but I think it is possible to make it work. (In contrast it was fundamentally not possible to make stack-allocated Panics work when they were also used during traceback, because a Panic near the bottom of the stack wasn't actually needed until later up the stack, and by then it had been rewritten. The CL 141490043 fixed this by not using Panics during traceback anymore.) |
Punting to unplanned, too late for anything major in 1.12. |
Change https://golang.org/cl/171758 mentions this issue: |
Change https://golang.org/cl/181258 mentions this issue: |
The logic for detecting deferreturn calls is wrong. We used to look for a relocation whose symbol is runtime.deferreturn and has an offset of 0. But on some architectures, the relocation offset is not zero. These include arm (the offset is 0xebfffffe) and s390x (the offset is 6). This ends up setting the deferreturn offset at 0, so we end up using the entry point live map instead of the deferreturn live map in a frame which defers and then segfaults. Instead, use the IsDirectCall helper to find calls. Fixes #32477 Update #6980 Change-Id: Iecb530a7cf6eabd7233be7d0731ffa78873f3a54 Reviewed-on: https://go-review.googlesource.com/c/go/+/181258 Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
Yes, this is done and should be closed. |
The text was updated successfully, but these errors were encountered: