diff options
author | Than McIntosh <thanm@google.com> | 2021-02-24 12:55:52 -0500 |
---|---|---|
committer | Than McIntosh <thanm@google.com> | 2021-03-23 23:08:19 +0000 |
commit | 769d4b68ef72125de068a060220c3dbd9ba65c43 (patch) | |
tree | 9a54b697bcc1a1fb24c81bc06376e255c000693b /src/runtime/export_test.go | |
parent | 4e27aa6cd2c3f579328e3b490780664ade34053d (diff) | |
download | go-769d4b68ef72125de068a060220c3dbd9ba65c43.tar.gz go-769d4b68ef72125de068a060220c3dbd9ba65c43.zip |
cmd/compile: wrap/desugar defer calls for register abi
Adds code to the compiler's "order" phase to rewrite go and defer
statements to always be argument-less. E.g.
defer f(x,y) => x1, y1 := x, y
defer func() { f(x1, y1) }
This transformation is not beneficial on its own, but it helps
simplify runtime defer handling for the new register ABI (when
invoking deferred functions on the panic path, the runtime doesn't
need to manage the complexity of determining which args to pass in
register vs memory).
This feature is currently enabled by default if GOEXPERIMENT=regabi or
GOEXPERIMENT=regabidefer is in effect.
Included in this CL are some workarounds in the runtime to insure that
"go" statement targets in the runtime are argument-less already (since
wrapping them can potentially introduce heap-allocated closures, which
are currently not allowed). The expectation is that these workarounds
will be temporary, and can go away once we either A) change the rules
about heap-allocated closures, or B) implement some other scheme for
handling go statements.
Change-Id: I01060d79a6b140c6f0838d6e6813f807ccdca319
Reviewed-on: https://go-review.googlesource.com/c/go/+/298669
Trust: Than McIntosh <thanm@google.com>
Run-TryBot: Than McIntosh <thanm@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: David Chase <drchase@google.com>
Diffstat (limited to 'src/runtime/export_test.go')
-rw-r--r-- | src/runtime/export_test.go | 20 |
1 files changed, 16 insertions, 4 deletions
diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index c03cf136f2..1650541fda 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -147,28 +147,40 @@ func RunSchedLocalQueueStealTest() { } } +// Temporary to enable register ABI bringup. +// TODO(register args): convert back to local variables in RunSchedLocalQueueEmptyTest that +// get passed to the "go" stmts there. +var RunSchedLocalQueueEmptyState struct { + done chan bool + ready *uint32 + p *p +} + func RunSchedLocalQueueEmptyTest(iters int) { // Test that runq is not spuriously reported as empty. // Runq emptiness affects scheduling decisions and spurious emptiness // can lead to underutilization (both runnable Gs and idle Ps coexist // for arbitrary long time). done := make(chan bool, 1) + RunSchedLocalQueueEmptyState.done = done p := new(p) + RunSchedLocalQueueEmptyState.p = p gs := make([]g, 2) ready := new(uint32) + RunSchedLocalQueueEmptyState.ready = ready for i := 0; i < iters; i++ { *ready = 0 next0 := (i & 1) == 0 next1 := (i & 2) == 0 runqput(p, &gs[0], next0) go func() { - for atomic.Xadd(ready, 1); atomic.Load(ready) != 2; { + for atomic.Xadd(RunSchedLocalQueueEmptyState.ready, 1); atomic.Load(RunSchedLocalQueueEmptyState.ready) != 2; { } - if runqempty(p) { - println("next:", next0, next1) + if runqempty(RunSchedLocalQueueEmptyState.p) { + //println("next:", next0, next1) throw("queue is empty") } - done <- true + RunSchedLocalQueueEmptyState.done <- true }() for atomic.Xadd(ready, 1); atomic.Load(ready) != 2; { } |