mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: ensure bloop only kept alive addressable nodes
Fixes #76636 Change-Id: I881f88dbf62a901452c1d77e6ffca651451c7790 Reviewed-on: https://go-review.googlesource.com/c/go/+/725420 Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Junyang Shao <shaojunyang@google.com> Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Keith Randall <khr@google.com>
This commit is contained in:
parent
7cab1b1b26
commit
509ddf3868
2 changed files with 24 additions and 5 deletions
|
|
@ -73,6 +73,14 @@ func getNameFromNode(n ir.Node) *ir.Name {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getAddressableNameFromNode is like getNameFromNode but returns nil if the node is not addressable.
|
||||||
|
func getAddressableNameFromNode(n ir.Node) *ir.Name {
|
||||||
|
if name := getNameFromNode(n); name != nil && ir.IsAddressable(name) {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// keepAliveAt returns a statement that is either curNode, or a
|
// keepAliveAt returns a statement that is either curNode, or a
|
||||||
// block containing curNode followed by a call to runtime.KeepAlive for each
|
// block containing curNode followed by a call to runtime.KeepAlive for each
|
||||||
// node in ns. These calls ensure that nodes in ns will be live until
|
// node in ns. These calls ensure that nodes in ns will be live until
|
||||||
|
|
@ -94,6 +102,9 @@ func keepAliveAt(ns []ir.Node, curNode ir.Node) ir.Node {
|
||||||
if n.Sym().IsBlank() {
|
if n.Sym().IsBlank() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if !ir.IsAddressable(n) {
|
||||||
|
base.FatalfAt(n.Pos(), "keepAliveAt: node %v is not addressable", n)
|
||||||
|
}
|
||||||
arg := ir.NewConvExpr(pos, ir.OCONV, types.Types[types.TUNSAFEPTR], typecheck.NodAddr(n))
|
arg := ir.NewConvExpr(pos, ir.OCONV, types.Types[types.TUNSAFEPTR], typecheck.NodAddr(n))
|
||||||
if !n.Type().IsInterface() {
|
if !n.Type().IsInterface() {
|
||||||
srcRType0 := reflectdata.TypePtrAt(pos, n.Type())
|
srcRType0 := reflectdata.TypePtrAt(pos, n.Type())
|
||||||
|
|
@ -129,7 +140,7 @@ func preserveStmt(curFn *ir.Func, stmt ir.Node) (ret ir.Node) {
|
||||||
switch n := stmt.(type) {
|
switch n := stmt.(type) {
|
||||||
case *ir.AssignStmt:
|
case *ir.AssignStmt:
|
||||||
// Peel down struct and slice indexing to get the names
|
// Peel down struct and slice indexing to get the names
|
||||||
name := getNameFromNode(n.X)
|
name := getAddressableNameFromNode(n.X)
|
||||||
if name != nil {
|
if name != nil {
|
||||||
debugName(name, n.Pos())
|
debugName(name, n.Pos())
|
||||||
ret = keepAliveAt([]ir.Node{name}, n)
|
ret = keepAliveAt([]ir.Node{name}, n)
|
||||||
|
|
@ -144,7 +155,7 @@ func preserveStmt(curFn *ir.Func, stmt ir.Node) (ret ir.Node) {
|
||||||
case *ir.AssignListStmt:
|
case *ir.AssignListStmt:
|
||||||
ns := []ir.Node{}
|
ns := []ir.Node{}
|
||||||
for _, lhs := range n.Lhs {
|
for _, lhs := range n.Lhs {
|
||||||
name := getNameFromNode(lhs)
|
name := getAddressableNameFromNode(lhs)
|
||||||
if name != nil {
|
if name != nil {
|
||||||
debugName(name, n.Pos())
|
debugName(name, n.Pos())
|
||||||
ns = append(ns, name)
|
ns = append(ns, name)
|
||||||
|
|
@ -159,7 +170,7 @@ func preserveStmt(curFn *ir.Func, stmt ir.Node) (ret ir.Node) {
|
||||||
}
|
}
|
||||||
ret = keepAliveAt(ns, n)
|
ret = keepAliveAt(ns, n)
|
||||||
case *ir.AssignOpStmt:
|
case *ir.AssignOpStmt:
|
||||||
name := getNameFromNode(n.X)
|
name := getAddressableNameFromNode(n.X)
|
||||||
if name != nil {
|
if name != nil {
|
||||||
debugName(name, n.Pos())
|
debugName(name, n.Pos())
|
||||||
ret = keepAliveAt([]ir.Node{name}, n)
|
ret = keepAliveAt([]ir.Node{name}, n)
|
||||||
|
|
@ -206,7 +217,7 @@ func preserveStmt(curFn *ir.Func, stmt ir.Node) (ret ir.Node) {
|
||||||
argTmps := []ir.Node{}
|
argTmps := []ir.Node{}
|
||||||
names := []ir.Node{}
|
names := []ir.Node{}
|
||||||
for i, a := range n.Args {
|
for i, a := range n.Args {
|
||||||
if name := getNameFromNode(a); name != nil {
|
if name := getAddressableNameFromNode(a); name != nil {
|
||||||
// If they are name, keep them alive directly.
|
// If they are name, keep them alive directly.
|
||||||
debugName(name, n.Pos())
|
debugName(name, n.Pos())
|
||||||
names = append(names, name)
|
names = append(names, name)
|
||||||
|
|
@ -215,7 +226,7 @@ func preserveStmt(curFn *ir.Func, stmt ir.Node) (ret ir.Node) {
|
||||||
s := a.(*ir.CompLitExpr)
|
s := a.(*ir.CompLitExpr)
|
||||||
ns := []ir.Node{}
|
ns := []ir.Node{}
|
||||||
for i, elem := range s.List {
|
for i, elem := range s.List {
|
||||||
if name := getNameFromNode(elem); name != nil {
|
if name := getAddressableNameFromNode(elem); name != nil {
|
||||||
debugName(name, n.Pos())
|
debugName(name, n.Pos())
|
||||||
ns = append(ns, name)
|
ns = append(ns, name)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,12 @@ func caninlineVariadic(x ...int) { // ERROR "can inline caninlineVariadic" "x do
|
||||||
something = x[0]
|
something = x[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func receiver(f func()) { // ERROR "can inline receiver" "f does not escape"
|
||||||
|
f()
|
||||||
|
}
|
||||||
|
|
||||||
|
func argument() {} // ERROR "can inline argument"
|
||||||
|
|
||||||
func test(b *testing.B, localsink, cond int) { // ERROR ".*"
|
func test(b *testing.B, localsink, cond int) { // ERROR ".*"
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
caninline(1) // ERROR "inlining call to caninline"
|
caninline(1) // ERROR "inlining call to caninline"
|
||||||
|
|
@ -49,5 +55,7 @@ func test(b *testing.B, localsink, cond int) { // ERROR ".*"
|
||||||
{
|
{
|
||||||
caninline(1) // ERROR "inlining call to caninline" "function result will be kept alive"
|
caninline(1) // ERROR "inlining call to caninline" "function result will be kept alive"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
receiver(argument) // ERROR inlining call to receiver" "function arg will be kept alive"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue