Commit e3f1c66f authored by Keith Randall's avatar Keith Randall

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: default avatarDavid Chase <drchase@google.com>
parent 1bdf1c30
......@@ -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
......
// 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)
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment