From d1c3f255fda8b9bf86990b55353ca14fbfe5b257 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Mon, 16 Sep 2024 16:07:25 -0400 Subject: [PATCH] runtime: move getclosureptr to internal/runtime/sys Moving these intrinsics to a base package enables other internal/runtime packages to use them. There is no immediate need for getclosureptr outside of runtime, but it is moved for consistency with the other intrinsics. For #54766. Change-Id: Ia68b16a938c8cb84cb222469db28e3a83861be5d Reviewed-on: https://go-review.googlesource.com/c/go/+/613262 LUCI-TryBot-Result: Go LUCI Reviewed-by: Cherry Mui --- src/cmd/compile/internal/devirtualize/pgo.go | 5 ++-- src/cmd/compile/internal/ssagen/intrinsics.go | 15 +++++----- .../internal/ssagen/intrinsics_test.go | 28 +++++++++---------- src/internal/runtime/sys/intrinsics.go | 21 ++++++++++++++ src/runtime/alg.go | 3 +- src/runtime/stubs.go | 21 -------------- 6 files changed, 47 insertions(+), 46 deletions(-) diff --git a/src/cmd/compile/internal/devirtualize/pgo.go b/src/cmd/compile/internal/devirtualize/pgo.go index 01677d82b6..96c9231be3 100644 --- a/src/cmd/compile/internal/devirtualize/pgo.go +++ b/src/cmd/compile/internal/devirtualize/pgo.go @@ -241,8 +241,9 @@ func maybeDevirtualizeFunctionCall(p *pgoir.Profile, fn *ir.Func, call *ir.CallE return nil, nil, 0 } // runtime.memhash_varlen does not look like a closure, but it uses - // runtime.getclosureptr to access data encoded by callers, which are - // generated by cmd/compile/internal/reflectdata.genhash. + // internal/runtime/sys.GetClosurePtr to access data encoded by + // callers, which are generated by + // cmd/compile/internal/reflectdata.genhash. if callee.Sym().Pkg.Path == "runtime" && callee.Sym().Name == "memhash_varlen" { if base.Debug.PGODebug >= 3 { fmt.Printf("callee %s is a closure (runtime.memhash_varlen), skipping\n", ir.FuncName(callee)) diff --git a/src/cmd/compile/internal/ssagen/intrinsics.go b/src/cmd/compile/internal/ssagen/intrinsics.go index 8de374221b..39a72533df 100644 --- a/src/cmd/compile/internal/ssagen/intrinsics.go +++ b/src/cmd/compile/internal/ssagen/intrinsics.go @@ -156,11 +156,6 @@ func initIntrinsics(cfg *intrinsicBuildConfig) { return nil }, all...) - add("runtime", "getclosureptr", - func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { - return s.newValue0(ssa.OpGetClosurePtr, s.f.Config.Types.Uintptr) - }, - all...) addF("runtime", "publicationBarrier", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { @@ -182,6 +177,12 @@ func initIntrinsics(cfg *intrinsicBuildConfig) { }, all...) + add("internal/runtime/sys", "GetClosurePtr", + func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { + return s.newValue0(ssa.OpGetClosurePtr, s.f.Config.Types.Uintptr) + }, + all...) + brev_arch := []sys.ArchFamily{sys.AMD64, sys.I386, sys.ARM64, sys.ARM, sys.S390X} if cfg.goppc64 >= 10 { // Use only on Power10 as the new byte reverse instructions that Power10 provide @@ -1083,9 +1084,7 @@ func findIntrinsic(sym *types.Sym) intrinsicBuilder { fn := sym.Name if ssa.IntrinsicsDisable { - if pkg == "runtime" && fn == "getclosureptr" { - // These runtime functions don't have definitions, must be intrinsics. - } else if pkg == "internal/runtime/sys" && (fn == "GetCallerPC" || fn == "GrtCallerSP") { + if pkg == "internal/runtime/sys" && (fn == "GetCallerPC" || fn == "GrtCallerSP" || fn == "GetClosurePtr") { // These runtime functions don't have definitions, must be intrinsics. } else { return nil diff --git a/src/cmd/compile/internal/ssagen/intrinsics_test.go b/src/cmd/compile/internal/ssagen/intrinsics_test.go index 22cb2df271..888063cbda 100644 --- a/src/cmd/compile/internal/ssagen/intrinsics_test.go +++ b/src/cmd/compile/internal/ssagen/intrinsics_test.go @@ -28,6 +28,7 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"386", "internal/runtime/sys", "Bswap64"}: struct{}{}, {"386", "internal/runtime/sys", "GetCallerPC"}: struct{}{}, {"386", "internal/runtime/sys", "GetCallerSP"}: struct{}{}, + {"386", "internal/runtime/sys", "GetClosurePtr"}: struct{}{}, {"386", "internal/runtime/sys", "TrailingZeros32"}: struct{}{}, {"386", "internal/runtime/sys", "TrailingZeros64"}: struct{}{}, {"386", "internal/runtime/sys", "TrailingZeros8"}: struct{}{}, @@ -39,7 +40,6 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"386", "math/bits", "TrailingZeros64"}: struct{}{}, {"386", "math/bits", "TrailingZeros8"}: struct{}{}, {"386", "runtime", "KeepAlive"}: struct{}{}, - {"386", "runtime", "getclosureptr"}: struct{}{}, {"386", "runtime", "slicebytetostringtmp"}: struct{}{}, {"amd64", "internal/runtime/atomic", "And"}: struct{}{}, {"amd64", "internal/runtime/atomic", "And32"}: struct{}{}, @@ -94,6 +94,7 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"amd64", "internal/runtime/sys", "Bswap64"}: struct{}{}, {"amd64", "internal/runtime/sys", "GetCallerPC"}: struct{}{}, {"amd64", "internal/runtime/sys", "GetCallerSP"}: struct{}{}, + {"amd64", "internal/runtime/sys", "GetClosurePtr"}: struct{}{}, {"amd64", "internal/runtime/sys", "Len64"}: struct{}{}, {"amd64", "internal/runtime/sys", "Len8"}: struct{}{}, {"amd64", "internal/runtime/sys", "OnesCount64"}: struct{}{}, @@ -138,7 +139,6 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"amd64", "math/bits", "TrailingZeros64"}: struct{}{}, {"amd64", "math/bits", "TrailingZeros8"}: struct{}{}, {"amd64", "runtime", "KeepAlive"}: struct{}{}, - {"amd64", "runtime", "getclosureptr"}: struct{}{}, {"amd64", "runtime", "slicebytetostringtmp"}: struct{}{}, {"amd64", "sync", "runtime_LoadAcquintptr"}: struct{}{}, {"amd64", "sync", "runtime_StoreReluintptr"}: struct{}{}, @@ -182,6 +182,7 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"arm", "internal/runtime/sys", "Bswap64"}: struct{}{}, {"arm", "internal/runtime/sys", "GetCallerPC"}: struct{}{}, {"arm", "internal/runtime/sys", "GetCallerSP"}: struct{}{}, + {"arm", "internal/runtime/sys", "GetClosurePtr"}: struct{}{}, {"arm", "internal/runtime/sys", "Len64"}: struct{}{}, {"arm", "internal/runtime/sys", "Len8"}: struct{}{}, {"arm", "internal/runtime/sys", "TrailingZeros32"}: struct{}{}, @@ -203,7 +204,6 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"arm", "math/bits", "TrailingZeros64"}: struct{}{}, {"arm", "math/bits", "TrailingZeros8"}: struct{}{}, {"arm", "runtime", "KeepAlive"}: struct{}{}, - {"arm", "runtime", "getclosureptr"}: struct{}{}, {"arm", "runtime", "slicebytetostringtmp"}: struct{}{}, {"arm64", "internal/runtime/atomic", "And"}: struct{}{}, {"arm64", "internal/runtime/atomic", "And32"}: struct{}{}, @@ -260,6 +260,7 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"arm64", "internal/runtime/sys", "Bswap64"}: struct{}{}, {"arm64", "internal/runtime/sys", "GetCallerPC"}: struct{}{}, {"arm64", "internal/runtime/sys", "GetCallerSP"}: struct{}{}, + {"arm64", "internal/runtime/sys", "GetClosurePtr"}: struct{}{}, {"arm64", "internal/runtime/sys", "Len64"}: struct{}{}, {"arm64", "internal/runtime/sys", "Len8"}: struct{}{}, {"arm64", "internal/runtime/sys", "OnesCount64"}: struct{}{}, @@ -306,7 +307,6 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"arm64", "math/bits", "TrailingZeros64"}: struct{}{}, {"arm64", "math/bits", "TrailingZeros8"}: struct{}{}, {"arm64", "runtime", "KeepAlive"}: struct{}{}, - {"arm64", "runtime", "getclosureptr"}: struct{}{}, {"arm64", "runtime", "publicationBarrier"}: struct{}{}, {"arm64", "runtime", "slicebytetostringtmp"}: struct{}{}, {"arm64", "sync", "runtime_LoadAcquintptr"}: struct{}{}, @@ -390,6 +390,7 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"loong64", "internal/runtime/math", "MulUintptr"}: struct{}{}, {"loong64", "internal/runtime/sys", "GetCallerPC"}: struct{}{}, {"loong64", "internal/runtime/sys", "GetCallerSP"}: struct{}{}, + {"loong64", "internal/runtime/sys", "GetClosurePtr"}: struct{}{}, {"loong64", "math", "Abs"}: struct{}{}, {"loong64", "math", "Copysign"}: struct{}{}, {"loong64", "math", "sqrt"}: struct{}{}, @@ -404,7 +405,6 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"loong64", "math/bits", "Sub"}: struct{}{}, {"loong64", "math/bits", "Sub64"}: struct{}{}, {"loong64", "runtime", "KeepAlive"}: struct{}{}, - {"loong64", "runtime", "getclosureptr"}: struct{}{}, {"loong64", "runtime", "slicebytetostringtmp"}: struct{}{}, {"loong64", "sync", "runtime_LoadAcquintptr"}: struct{}{}, {"loong64", "sync", "runtime_StoreReluintptr"}: struct{}{}, @@ -466,6 +466,7 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"mips", "internal/runtime/atomic", "Xchguintptr"}: struct{}{}, {"mips", "internal/runtime/sys", "GetCallerPC"}: struct{}{}, {"mips", "internal/runtime/sys", "GetCallerSP"}: struct{}{}, + {"mips", "internal/runtime/sys", "GetClosurePtr"}: struct{}{}, {"mips", "internal/runtime/sys", "Len64"}: struct{}{}, {"mips", "internal/runtime/sys", "Len8"}: struct{}{}, {"mips", "internal/runtime/sys", "TrailingZeros32"}: struct{}{}, @@ -483,7 +484,6 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"mips", "math/bits", "TrailingZeros64"}: struct{}{}, {"mips", "math/bits", "TrailingZeros8"}: struct{}{}, {"mips", "runtime", "KeepAlive"}: struct{}{}, - {"mips", "runtime", "getclosureptr"}: struct{}{}, {"mips", "runtime", "slicebytetostringtmp"}: struct{}{}, {"mips", "sync", "runtime_LoadAcquintptr"}: struct{}{}, {"mips", "sync", "runtime_StoreReluintptr"}: struct{}{}, @@ -550,6 +550,7 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"mips64", "internal/runtime/math", "MulUintptr"}: struct{}{}, {"mips64", "internal/runtime/sys", "GetCallerPC"}: struct{}{}, {"mips64", "internal/runtime/sys", "GetCallerSP"}: struct{}{}, + {"mips64", "internal/runtime/sys", "GetClosurePtr"}: struct{}{}, {"mips64", "math", "Abs"}: struct{}{}, {"mips64", "math", "sqrt"}: struct{}{}, {"mips64", "math/big", "mulWW"}: struct{}{}, @@ -560,7 +561,6 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"mips64", "math/bits", "Sub"}: struct{}{}, {"mips64", "math/bits", "Sub64"}: struct{}{}, {"mips64", "runtime", "KeepAlive"}: struct{}{}, - {"mips64", "runtime", "getclosureptr"}: struct{}{}, {"mips64", "runtime", "slicebytetostringtmp"}: struct{}{}, {"mips64", "sync", "runtime_LoadAcquintptr"}: struct{}{}, {"mips64", "sync", "runtime_StoreReluintptr"}: struct{}{}, @@ -637,6 +637,7 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"mips64le", "internal/runtime/math", "MulUintptr"}: struct{}{}, {"mips64le", "internal/runtime/sys", "GetCallerPC"}: struct{}{}, {"mips64le", "internal/runtime/sys", "GetCallerSP"}: struct{}{}, + {"mips64le", "internal/runtime/sys", "GetClosurePtr"}: struct{}{}, {"mips64le", "math", "Abs"}: struct{}{}, {"mips64le", "math", "sqrt"}: struct{}{}, {"mips64le", "math/big", "mulWW"}: struct{}{}, @@ -647,7 +648,6 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"mips64le", "math/bits", "Sub"}: struct{}{}, {"mips64le", "math/bits", "Sub64"}: struct{}{}, {"mips64le", "runtime", "KeepAlive"}: struct{}{}, - {"mips64le", "runtime", "getclosureptr"}: struct{}{}, {"mips64le", "runtime", "slicebytetostringtmp"}: struct{}{}, {"mips64le", "sync", "runtime_LoadAcquintptr"}: struct{}{}, {"mips64le", "sync", "runtime_StoreReluintptr"}: struct{}{}, @@ -709,6 +709,7 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"mipsle", "internal/runtime/atomic", "Xchguintptr"}: struct{}{}, {"mipsle", "internal/runtime/sys", "GetCallerPC"}: struct{}{}, {"mipsle", "internal/runtime/sys", "GetCallerSP"}: struct{}{}, + {"mipsle", "internal/runtime/sys", "GetClosurePtr"}: struct{}{}, {"mipsle", "internal/runtime/sys", "Len64"}: struct{}{}, {"mipsle", "internal/runtime/sys", "Len8"}: struct{}{}, {"mipsle", "internal/runtime/sys", "TrailingZeros32"}: struct{}{}, @@ -726,7 +727,6 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"mipsle", "math/bits", "TrailingZeros64"}: struct{}{}, {"mipsle", "math/bits", "TrailingZeros8"}: struct{}{}, {"mipsle", "runtime", "KeepAlive"}: struct{}{}, - {"mipsle", "runtime", "getclosureptr"}: struct{}{}, {"mipsle", "runtime", "slicebytetostringtmp"}: struct{}{}, {"mipsle", "sync", "runtime_LoadAcquintptr"}: struct{}{}, {"mipsle", "sync", "runtime_StoreReluintptr"}: struct{}{}, @@ -794,6 +794,7 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"ppc64", "internal/runtime/sys", "Bswap64"}: struct{}{}, {"ppc64", "internal/runtime/sys", "GetCallerPC"}: struct{}{}, {"ppc64", "internal/runtime/sys", "GetCallerSP"}: struct{}{}, + {"ppc64", "internal/runtime/sys", "GetClosurePtr"}: struct{}{}, {"ppc64", "internal/runtime/sys", "Len64"}: struct{}{}, {"ppc64", "internal/runtime/sys", "Len8"}: struct{}{}, {"ppc64", "internal/runtime/sys", "OnesCount64"}: struct{}{}, @@ -835,7 +836,6 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"ppc64", "math/bits", "TrailingZeros32"}: struct{}{}, {"ppc64", "math/bits", "TrailingZeros64"}: struct{}{}, {"ppc64", "runtime", "KeepAlive"}: struct{}{}, - {"ppc64", "runtime", "getclosureptr"}: struct{}{}, {"ppc64", "runtime", "publicationBarrier"}: struct{}{}, {"ppc64", "runtime", "slicebytetostringtmp"}: struct{}{}, {"ppc64", "sync", "runtime_LoadAcquintptr"}: struct{}{}, @@ -914,6 +914,7 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"ppc64le", "internal/runtime/sys", "Bswap64"}: struct{}{}, {"ppc64le", "internal/runtime/sys", "GetCallerPC"}: struct{}{}, {"ppc64le", "internal/runtime/sys", "GetCallerSP"}: struct{}{}, + {"ppc64le", "internal/runtime/sys", "GetClosurePtr"}: struct{}{}, {"ppc64le", "internal/runtime/sys", "Len64"}: struct{}{}, {"ppc64le", "internal/runtime/sys", "Len8"}: struct{}{}, {"ppc64le", "internal/runtime/sys", "OnesCount64"}: struct{}{}, @@ -955,7 +956,6 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"ppc64le", "math/bits", "TrailingZeros32"}: struct{}{}, {"ppc64le", "math/bits", "TrailingZeros64"}: struct{}{}, {"ppc64le", "runtime", "KeepAlive"}: struct{}{}, - {"ppc64le", "runtime", "getclosureptr"}: struct{}{}, {"ppc64le", "runtime", "publicationBarrier"}: struct{}{}, {"ppc64le", "runtime", "slicebytetostringtmp"}: struct{}{}, {"ppc64le", "sync", "runtime_LoadAcquintptr"}: struct{}{}, @@ -1033,6 +1033,7 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"riscv64", "internal/runtime/math", "MulUintptr"}: struct{}{}, {"riscv64", "internal/runtime/sys", "GetCallerPC"}: struct{}{}, {"riscv64", "internal/runtime/sys", "GetCallerSP"}: struct{}{}, + {"riscv64", "internal/runtime/sys", "GetClosurePtr"}: struct{}{}, {"riscv64", "math", "Abs"}: struct{}{}, {"riscv64", "math", "Copysign"}: struct{}{}, {"riscv64", "math", "FMA"}: struct{}{}, @@ -1050,7 +1051,6 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"riscv64", "math/bits", "Sub"}: struct{}{}, {"riscv64", "math/bits", "Sub64"}: struct{}{}, {"riscv64", "runtime", "KeepAlive"}: struct{}{}, - {"riscv64", "runtime", "getclosureptr"}: struct{}{}, {"riscv64", "runtime", "publicationBarrier"}: struct{}{}, {"riscv64", "runtime", "slicebytetostringtmp"}: struct{}{}, {"riscv64", "sync", "runtime_LoadAcquintptr"}: struct{}{}, @@ -1129,6 +1129,7 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"s390x", "internal/runtime/sys", "Bswap64"}: struct{}{}, {"s390x", "internal/runtime/sys", "GetCallerPC"}: struct{}{}, {"s390x", "internal/runtime/sys", "GetCallerSP"}: struct{}{}, + {"s390x", "internal/runtime/sys", "GetClosurePtr"}: struct{}{}, {"s390x", "internal/runtime/sys", "Len64"}: struct{}{}, {"s390x", "internal/runtime/sys", "Len8"}: struct{}{}, {"s390x", "internal/runtime/sys", "OnesCount64"}: struct{}{}, @@ -1168,7 +1169,6 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"s390x", "math/bits", "TrailingZeros64"}: struct{}{}, {"s390x", "math/bits", "TrailingZeros8"}: struct{}{}, {"s390x", "runtime", "KeepAlive"}: struct{}{}, - {"s390x", "runtime", "getclosureptr"}: struct{}{}, {"s390x", "runtime", "slicebytetostringtmp"}: struct{}{}, {"s390x", "sync", "runtime_LoadAcquintptr"}: struct{}{}, {"s390x", "sync", "runtime_StoreReluintptr"}: struct{}{}, @@ -1200,6 +1200,7 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"s390x", "sync/atomic", "SwapUintptr"}: struct{}{}, {"wasm", "internal/runtime/sys", "GetCallerPC"}: struct{}{}, {"wasm", "internal/runtime/sys", "GetCallerSP"}: struct{}{}, + {"wasm", "internal/runtime/sys", "GetClosurePtr"}: struct{}{}, {"wasm", "internal/runtime/sys", "Len64"}: struct{}{}, {"wasm", "internal/runtime/sys", "Len8"}: struct{}{}, {"wasm", "internal/runtime/sys", "OnesCount64"}: struct{}{}, @@ -1230,7 +1231,6 @@ var wantIntrinsics = map[testIntrinsicKey]struct{}{ {"wasm", "math/bits", "TrailingZeros64"}: struct{}{}, {"wasm", "math/bits", "TrailingZeros8"}: struct{}{}, {"wasm", "runtime", "KeepAlive"}: struct{}{}, - {"wasm", "runtime", "getclosureptr"}: struct{}{}, {"wasm", "runtime", "slicebytetostringtmp"}: struct{}{}, } diff --git a/src/internal/runtime/sys/intrinsics.go b/src/internal/runtime/sys/intrinsics.go index 8a431d0b36..147d5581f2 100644 --- a/src/internal/runtime/sys/intrinsics.go +++ b/src/internal/runtime/sys/intrinsics.go @@ -233,3 +233,24 @@ func PrefetchStreamed(addr uintptr) {} func GetCallerPC() uintptr func GetCallerSP() uintptr + +// GetClosurePtr returns the pointer to the current closure. +// GetClosurePtr can only be used in an assignment statement +// at the entry of a function. Moreover, go:nosplit directive +// must be specified at the declaration of caller function, +// so that the function prolog does not clobber the closure register. +// for example: +// +// //go:nosplit +// func f(arg1, arg2, arg3 int) { +// dx := GetClosurePtr() +// } +// +// The compiler rewrites calls to this function into instructions that fetch the +// pointer from a well-known register (DX on x86 architecture, etc.) directly. +// +// WARNING: PGO-based devirtualization cannot detect that caller of +// GetClosurePtr requires closure context, and thus must maintain a list of +// these functions, which is in +// cmd/compile/internal/devirtualize/pgo.maybeDevirtualizeFunctionCall. +func GetClosurePtr() uintptr diff --git a/src/runtime/alg.go b/src/runtime/alg.go index 1c373b7f25..e183452fbe 100644 --- a/src/runtime/alg.go +++ b/src/runtime/alg.go @@ -8,6 +8,7 @@ import ( "internal/abi" "internal/cpu" "internal/goarch" + "internal/runtime/sys" "unsafe" ) @@ -34,7 +35,7 @@ func memhash128(p unsafe.Pointer, h uintptr) uintptr { //go:nosplit func memhash_varlen(p unsafe.Pointer, h uintptr) uintptr { - ptr := getclosureptr() + ptr := sys.GetClosurePtr() size := *(*uintptr)(unsafe.Pointer(ptr + unsafe.Sizeof(h))) return memhash(p, h, size) } diff --git a/src/runtime/stubs.go b/src/runtime/stubs.go index 84f478db07..d334190976 100644 --- a/src/runtime/stubs.go +++ b/src/runtime/stubs.go @@ -307,27 +307,6 @@ func goexit(neverCallThisFunction) // data dependency ordering. func publicationBarrier() -// getclosureptr returns the pointer to the current closure. -// getclosureptr can only be used in an assignment statement -// at the entry of a function. Moreover, go:nosplit directive -// must be specified at the declaration of caller function, -// so that the function prolog does not clobber the closure register. -// for example: -// -// //go:nosplit -// func f(arg1, arg2, arg3 int) { -// dx := getclosureptr() -// } -// -// The compiler rewrites calls to this function into instructions that fetch the -// pointer from a well-known register (DX on x86 architecture, etc.) directly. -// -// WARNING: PGO-based devirtualization cannot detect that caller of -// getclosureptr require closure context, and thus must maintain a list of -// these functions, which is in -// cmd/compile/internal/devirtualize/pgo.maybeDevirtualizeFunctionCall. -func getclosureptr() uintptr - //go:noescape func asmcgocall(fn, arg unsafe.Pointer) int32 -- 2.48.1