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
// 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.
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)
//
//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()
--- /dev/null
+// 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
--- /dev/null
+// 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