diff options
| author | zuojunwei.1024 <zuojunwei.1024@bytedance.com> | 2025-12-23 16:12:04 +0800 |
|---|---|---|
| committer | Cherry Mui <cherryyz@google.com> | 2025-12-30 07:26:35 -0800 |
| commit | cd668d744f77da06ca9565f41c63c3a5251469ee (patch) | |
| tree | 30077015dd0352f661f313d5b262ffd2bd801957 | |
| parent | 06eff0f7c3027a78088d45efdaec8ac3ed636481 (diff) | |
| download | go-cd668d744f77da06ca9565f41c63c3a5251469ee.tar.xz | |
cmd/compile: disable inlining for functions using runtime.deferrangefunc
The rangefunc rewrite pass implements defer using deferrangefunc and
deferproccat. The loop body is rewritten into a closure, it cannot be
inlined due to defer call. But the outer function may still be inlined
in certain scenarios (e.g., with PGO), leading to the defer executing
at the wrong time.
Fixes #77033
Change-Id: I4649fad5cd1b65891832523522002d9352711123
Reviewed-on: https://go-review.googlesource.com/c/go/+/732140
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
| -rw-r--r-- | src/cmd/compile/internal/inline/inl.go | 3 | ||||
| -rw-r--r-- | src/cmd/compile/testdata/script/issue77033.txt | 40 |
2 files changed, 43 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index 33f9c325c3..4fa9cf07fb 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -516,6 +516,9 @@ opSwitch: break opSwitch case "panicrangestate": cheap = true + case "deferrangefunc": + v.reason = "defer call in range func" + return true } } } diff --git a/src/cmd/compile/testdata/script/issue77033.txt b/src/cmd/compile/testdata/script/issue77033.txt new file mode 100644 index 0000000000..3b977e5440 --- /dev/null +++ b/src/cmd/compile/testdata/script/issue77033.txt @@ -0,0 +1,40 @@ +go test -bench=Foo -cpuprofile=default.pgo +go test -bench=Foo -pgo=default.pgo +! stdout 'FAIL' + +-- main_test.go -- +package main + +import ( + "testing" +) + +var a int + +func save(x int) { + a = x +} + +func foo() { + for i := range yield1 { + defer save(i) + } +} + +func yield1(yield func(int) bool) { + yield(1) +} + +func BenchmarkFoo(b *testing.B) { + for i := 0; i < b.N; i++ { + foo() + } + if a != 1 { + b.Fatalf("a = %d; want 1", a) + } +} + +-- go.mod -- +module demo + +go 1.24 |
