mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
runtime: check that defer/go frames are empty
With GOEXPERIMENT=regabidefer, these frames should always be empty. Check that. For #40724. Change-Id: Id8e418a9e06b4f94543cb16b868a7e10e013c2d9 Reviewed-on: https://go-review.googlesource.com/c/go/+/306009 Trust: Austin Clements <austin@google.com> Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Than McIntosh <thanm@google.com> Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
parent
1318fb4a32
commit
e0ce0af6ef
4 changed files with 37 additions and 0 deletions
|
|
@ -228,6 +228,11 @@ func deferproc(siz int32, fn *funcval) { // arguments of fn follow fn
|
|||
throw("defer on system stack")
|
||||
}
|
||||
|
||||
if experimentRegabiDefer && siz != 0 {
|
||||
// TODO: Make deferproc just take a func().
|
||||
throw("defer with non-empty frame")
|
||||
}
|
||||
|
||||
// the arguments of fn are in a perilous state. The stack map
|
||||
// for deferproc does not describe them. So we can't let garbage
|
||||
// collection or stack copying trigger until we've copied them out
|
||||
|
|
@ -280,6 +285,9 @@ func deferprocStack(d *_defer) {
|
|||
// go code on the system stack can't defer
|
||||
throw("defer on system stack")
|
||||
}
|
||||
if experimentRegabiDefer && d.siz != 0 {
|
||||
throw("defer with non-empty frame")
|
||||
}
|
||||
// siz and fn are already set.
|
||||
// The other fields are junk on entry to deferprocStack and
|
||||
// are initialized here.
|
||||
|
|
@ -824,6 +832,9 @@ func runOpenDeferFrame(gp *g, d *_defer) bool {
|
|||
argWidth, fd = readvarintUnsafe(fd)
|
||||
closureOffset, fd = readvarintUnsafe(fd)
|
||||
nArgs, fd = readvarintUnsafe(fd)
|
||||
if experimentRegabiDefer && argWidth != 0 {
|
||||
throw("defer with non-empty frame")
|
||||
}
|
||||
if deferBits&(1<<i) == 0 {
|
||||
for j := uint32(0); j < nArgs; j++ {
|
||||
_, fd = readvarintUnsafe(fd)
|
||||
|
|
|
|||
|
|
@ -4019,6 +4019,12 @@ func malg(stacksize int32) *g {
|
|||
//
|
||||
//go:nosplit
|
||||
func newproc(siz int32, fn *funcval) {
|
||||
if experimentRegabiDefer && siz != 0 {
|
||||
// TODO: When we commit to experimentRegabiDefer,
|
||||
// rewrite newproc's comment, since it will no longer
|
||||
// have a funny stack layout or need to be nosplit.
|
||||
throw("go with non-empty frame")
|
||||
}
|
||||
argp := add(unsafe.Pointer(&fn), sys.PtrSize)
|
||||
gp := getg()
|
||||
pc := getcallerpc()
|
||||
|
|
|
|||
10
src/runtime/regabidefer_off.go
Normal file
10
src/runtime/regabidefer_off.go
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !goexperiment.regabidefer
|
||||
// +build !goexperiment.regabidefer
|
||||
|
||||
package runtime
|
||||
|
||||
const experimentRegabiDefer = false
|
||||
10
src/runtime/regabidefer_on.go
Normal file
10
src/runtime/regabidefer_on.go
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build goexperiment.regabidefer
|
||||
// +build goexperiment.regabidefer
|
||||
|
||||
package runtime
|
||||
|
||||
const experimentRegabiDefer = true
|
||||
Loading…
Add table
Add a link
Reference in a new issue