cmd/compile: for tail calls in stubs, ensure args are alive

The generated code for interface stubs sometimes just messes
with a few of the args and then tail-calls to the target routine.
The args that aren't explicitly modified appear to not be used.
But they are used, by the thing we're tail calling.

Fixes #16016

Change-Id: Ib9b3a8311bb714a201daee002885fcb59e0463fa
Reviewed-on: https://go-review.googlesource.com/23960
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
Keith Randall 2016-06-09 11:07:36 -07:00
parent 1bdf1c3024
commit e3f1c66f31
2 changed files with 44 additions and 0 deletions

View file

@ -577,6 +577,15 @@ func progeffects(prog *obj.Prog, vars []*Node, uevar bvec, varkill bvec, avarini
return
}
if prog.As == obj.AJMP && prog.To.Type == obj.TYPE_MEM && prog.To.Name == obj.NAME_EXTERN {
// This is a tail call. Ensure the arguments are still alive.
// See issue 16016.
for i, node := range vars {
if node.Class == PPARAM {
bvset(uevar, int32(i))
}
}
}
if prog.As == obj.ATEXT {
// A text instruction marks the entry point to a function and

View file

@ -0,0 +1,35 @@
// run
// 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 "time"
type T struct{}
func (*T) Foo(vals []interface{}) {
switch v := vals[0].(type) {
case string:
_ = v
}
}
type R struct{ *T }
type Q interface {
Foo([]interface{})
}
func main() {
var q Q = &R{&T{}}
for i := 0; i < 10000; i++ {
go func() {
defer q.Foo([]interface{}{"meow"})
time.Sleep(100 * time.Millisecond)
}()
}
time.Sleep(1 * time.Second)
}