mirror of
https://github.com/golang/go
synced 2024-10-14 11:53:56 +00:00
cmd/gc: fix escape analysis of method values
R=ken2 CC=golang-dev https://golang.org/cl/7518050
This commit is contained in:
parent
0ad265d48f
commit
38e9b0773d
|
@ -270,8 +270,9 @@ typecheckpartialcall(Node *fn, Node *sym)
|
|||
|
||||
// Create top-level function.
|
||||
fn->nname = makepartialcall(fn, fn->type, sym);
|
||||
fn->right = sym;
|
||||
fn->op = OCALLPART;
|
||||
fn->type = fn->right->type;
|
||||
fn->type = fn->nname->type;
|
||||
}
|
||||
|
||||
static Node*
|
||||
|
|
|
@ -596,6 +596,14 @@ esc(EscState *e, Node *n)
|
|||
// Contents make it to memory, lose track.
|
||||
escassign(e, &e->theSink, n->left);
|
||||
break;
|
||||
|
||||
case OCALLPART:
|
||||
n->esc = EscNone; // until proven otherwise
|
||||
e->noesc = list(e->noesc, n);
|
||||
n->escloopdepth = e->loopdepth;
|
||||
// Contents make it to memory, lose track.
|
||||
escassign(e, &e->theSink, n->left);
|
||||
break;
|
||||
|
||||
case OMAPLIT:
|
||||
n->esc = EscNone; // until proven otherwise
|
||||
|
@ -667,6 +675,7 @@ escassign(EscState *e, Node *dst, Node *src)
|
|||
case OCONVNOP:
|
||||
case OMAPLIT:
|
||||
case OSTRUCTLIT:
|
||||
case OCALLPART:
|
||||
break;
|
||||
|
||||
case ONAME:
|
||||
|
@ -713,6 +722,7 @@ escassign(EscState *e, Node *dst, Node *src)
|
|||
case OMAKESLICE:
|
||||
case ONEW:
|
||||
case OCLOSURE:
|
||||
case OCALLPART:
|
||||
escflows(e, dst, src);
|
||||
break;
|
||||
|
||||
|
@ -1073,6 +1083,7 @@ escwalk(EscState *e, int level, Node *dst, Node *src)
|
|||
case OMAPLIT:
|
||||
case ONEW:
|
||||
case OCLOSURE:
|
||||
case OCALLPART:
|
||||
if(leaks) {
|
||||
src->esc = EscHeap;
|
||||
if(debug['m'])
|
||||
|
|
|
@ -1022,6 +1022,7 @@ static int opprec[] = {
|
|||
[ODOTTYPE] = 8,
|
||||
[ODOT] = 8,
|
||||
[OXDOT] = 8,
|
||||
[OCALLPART] = 8,
|
||||
|
||||
[OPLUS] = 7,
|
||||
[ONOT] = 7,
|
||||
|
@ -1269,9 +1270,10 @@ exprfmt(Fmt *f, Node *n, int prec)
|
|||
case ODOTPTR:
|
||||
case ODOTINTER:
|
||||
case ODOTMETH:
|
||||
case OCALLPART:
|
||||
exprfmt(f, n->left, nprec);
|
||||
if(n->right == N || n->right->sym == S)
|
||||
fmtstrcpy(f, ".<nil>");
|
||||
return fmtstrcpy(f, ".<nil>");
|
||||
return fmtprint(f, ".%hhS", n->right->sym);
|
||||
|
||||
case ODOTTYPE:
|
||||
|
|
|
@ -1303,3 +1303,25 @@ func G() {
|
|||
var buf4 [10]byte // ERROR "moved to heap: buf4"
|
||||
F4(buf4[:]) // ERROR "buf4 escapes to heap"
|
||||
}
|
||||
|
||||
type Tm struct {
|
||||
x int
|
||||
}
|
||||
|
||||
func (t *Tm) M() { // ERROR "t does not escape"
|
||||
}
|
||||
|
||||
func foo141() {
|
||||
var f func()
|
||||
|
||||
t := new(Tm) // ERROR "escapes to heap"
|
||||
f = t.M // ERROR "t.M does not escape"
|
||||
_ = f
|
||||
}
|
||||
|
||||
var gf func()
|
||||
|
||||
func foo142() {
|
||||
t := new(Tm) // ERROR "escapes to heap"
|
||||
gf = t.M // ERROR "t.M escapes to heap"
|
||||
}
|
||||
|
|
29
test/fixedbugs/bug474.go
Normal file
29
test/fixedbugs/bug474.go
Normal file
|
@ -0,0 +1,29 @@
|
|||
// run
|
||||
|
||||
// Copyright 2013 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.
|
||||
|
||||
// Bug in method values: escape analysis was off.
|
||||
|
||||
package main
|
||||
|
||||
import "sync"
|
||||
|
||||
var called = false
|
||||
|
||||
type T struct {
|
||||
once sync.Once
|
||||
}
|
||||
|
||||
func (t *T) M() {
|
||||
called = true
|
||||
}
|
||||
|
||||
func main() {
|
||||
var t T
|
||||
t.once.Do(t.M)
|
||||
if !called {
|
||||
panic("not called")
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue