cmd/compile: On a runtime.KeepAlive call, keep whole variable alive

We generate an OpKeepAlive for the idata portion of the interface
for a runtime.KeepAlive call.  But given such an op, we need to keep
the entire containing variable alive, not just the range that was
passed to the OpKeepAlive operation.

Fixes #17710

Change-Id: I90de66ec8065e22fb09bcf9722999ddda289ae6e
Reviewed-on: https://go-review.googlesource.com/32477
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
This commit is contained in:
Keith Randall 2016-10-31 21:18:00 -07:00
parent 09bb6434f9
commit 761443edd5
2 changed files with 18 additions and 4 deletions

View file

@ -4399,13 +4399,14 @@ func KeepAlive(v *ssa.Value) {
if !v.Args[0].Type.IsPtrShaped() {
v.Fatalf("keeping non-pointer alive %v", v.Args[0])
}
n, off := AutoVar(v.Args[0])
n, _ := AutoVar(v.Args[0])
if n == nil {
v.Fatalf("KeepAlive with non-spilled value %s %s", v, v.Args[0])
}
if off != 0 {
v.Fatalf("KeepAlive with non-zero offset spill location %v:%d", n, off)
}
// Note: KeepAlive arg may be a small part of a larger variable n. We keep the
// whole variable n alive at this point. (Typically, this happens when
// we are requested to keep the idata portion of an interface{} alive, and
// we end up keeping the whole interface{} alive. That's ok.)
Gvarlive(n)
}

View file

@ -0,0 +1,13 @@
// compile
// Copyright 2016 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.
package main
import "runtime"
func f(x interface{}) {
runtime.KeepAlive(x)
}