Skip to content

sync: sync.Mutex.* escape m *Mutex argument #57910

@Jorropo

Description

@Jorropo

What version of Go are you using (go version)?

$ go version
go version go1.19.5 linux/amd64

Does this issue reproduce with the latest release?

Yes as well as current master (2e792a8).

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/hugo/.cache/go-build"
GOENV="/home/hugo/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/hugo/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/hugo/go"
GOPRIVATE=""
GOPROXY="direct"
GOROOT="/home/hugo/Documents/Scripts/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/hugo/Documents/Scripts/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.19.5"
GCCGO="gccgo"
GOAMD64="v3"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
GOWORK=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build3304808272=/tmp/go-build -gno-record-gcc-switches"

What did you do?

I have some type that do lazy initialization of some state, for that I use sync.Once, however that force my object to leak and prevents stack allocations where I use this object in a non leaky way:
Here is some minimal repro go build -gcflags="-m" a.go:

package a

import (
	"sync"
	"fmt"
)

type A struct {
	o sync.Once
	v int
}

func (a *A) init() {
	a.o.Do(func() {
		a.v = 42
	})
}

func (a *A) Print() {
	a.init()
	fmt.Println(a.v)
}

func main() {
	var a A
	a.Print()
}

What did you expect to see?

# command-line-arguments
./a.go:14:8: inlining call to sync.(*Once).Do
./a.go:14:9: can inline (*A).init.func1
./a.go:21:13: inlining call to fmt.Println
./a.go:24:6: can inline main
./a.go:13:7: leaking param: a
./a.go:14:9: func literal does not escape
./a.go:19:7: leaking param: a
./a.go:21:13: ... argument does not escape
./a.go:21:15: a.v escapes to heap
./a.go:25:6: moved to heap: a

What did you see instead?

# command-line-arguments
./a.go:14:8: inlining call to sync.(*Once).Do
./a.go:14:9: can inline (*A).init.func1
./a.go:21:13: inlining call to fmt.Println
./a.go:24:6: can inline main
./a.go:13:7: a does not escape
./a.go:14:9: func literal does not escape
./a.go:19:7: a does not escape
./a.go:21:13: ... argument does not escape
./a.go:21:15: a.v escapes to heap

Depends on #16241 (note that fixing #16241 wont fully fix the problem here but is required).

Metadata

Metadata

Assignees

Labels

NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.Performancecompiler/runtimeIssues related to the Go compiler and/or runtime.

Type

No type

Projects

Status

Todo

Relationships

None yet

Development

No branches or pull requests

Issue actions