1
0
mirror of https://github.com/golang/go synced 2024-11-18 16:14:46 -07:00

cmd/compile: refactor escape analysis parameter tagging

No behavior change; just inverting the loop ordering so the
per-parameter behavior is a bit clearer.

Passes toolstash-check.

Updates #33981.

Change-Id: I9bfcd7d0a4aff65a27ced157767ca2ba8038319a
Reviewed-on: https://go-review.googlesource.com/c/go/+/193177
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
Matthew Dempsky 2019-09-04 15:12:08 -07:00
parent cf630586ca
commit 23bf6af996

View File

@ -212,6 +212,8 @@ var tags [1 << (bitsPerOutputInTag + EscReturnBits)]string
// mktag returns the string representation for an escape analysis tag.
func mktag(mask int) string {
switch mask & EscMask {
case EscHeap:
return ""
case EscNone, EscReturn:
default:
Fatalf("escape mktag")
@ -406,88 +408,74 @@ const uintptrEscapesTag = "uintptr-escapes"
func esctag(fn *Node) {
fn.Esc = EscFuncTagged
name := func(s *types.Sym, narg int) string {
if s != nil {
return s.Name
narg := 0
for _, fs := range types.RecvsParams {
for _, f := range fs(fn.Type).Fields().Slice() {
narg++
f.Note = escparamtag(fn, narg, f)
}
}
}
func escparamtag(fn *Node, narg int, f *types.Field) string {
name := func() string {
if f.Sym != nil {
return f.Sym.Name
}
return fmt.Sprintf("arg#%d", narg)
}
// External functions are assumed unsafe,
// unless //go:noescape is given before the declaration.
if fn.Nbody.Len() == 0 {
if fn.Noescape() {
for _, f := range fn.Type.Params().Fields().Slice() {
if types.Haspointers(f.Type) {
f.Note = mktag(EscNone)
}
}
}
// Assume that uintptr arguments must be held live across the call.
// This is most important for syscall.Syscall.
// See golang.org/issue/13372.
// This really doesn't have much to do with escape analysis per se,
// but we are reusing the ability to annotate an individual function
// argument and pass those annotations along to importing code.
narg := 0
for _, f := range fn.Type.Params().Fields().Slice() {
narg++
if f.Type.Etype == TUINTPTR {
if Debug['m'] != 0 {
Warnl(fn.Pos, "%v assuming %v is unsafe uintptr", funcSym(fn), name(f.Sym, narg))
}
f.Note = unsafeUintptrTag
if f.Type.Etype == TUINTPTR {
if Debug['m'] != 0 {
Warnl(fn.Pos, "%v assuming %v is unsafe uintptr", funcSym(fn), name())
}
return unsafeUintptrTag
}
return
if !types.Haspointers(f.Type) { // don't bother tagging for scalars
return ""
}
// External functions are assumed unsafe, unless
// //go:noescape is given before the declaration.
if fn.Noescape() {
return mktag(EscNone)
}
return mktag(EscHeap)
}
if fn.Func.Pragma&UintptrEscapes != 0 {
narg := 0
for _, f := range fn.Type.Params().Fields().Slice() {
narg++
if f.Type.Etype == TUINTPTR {
if Debug['m'] != 0 {
Warnl(fn.Pos, "%v marking %v as escaping uintptr", funcSym(fn), name(f.Sym, narg))
}
f.Note = uintptrEscapesTag
if f.Type.Etype == TUINTPTR {
if Debug['m'] != 0 {
Warnl(fn.Pos, "%v marking %v as escaping uintptr", funcSym(fn), name())
}
if f.IsDDD() && f.Type.Elem().Etype == TUINTPTR {
// final argument is ...uintptr.
if Debug['m'] != 0 {
Warnl(fn.Pos, "%v marking %v as escaping ...uintptr", funcSym(fn), name(f.Sym, narg))
}
f.Note = uintptrEscapesTag
return uintptrEscapesTag
}
if f.IsDDD() && f.Type.Elem().Etype == TUINTPTR {
// final argument is ...uintptr.
if Debug['m'] != 0 {
Warnl(fn.Pos, "%v marking %v as escaping ...uintptr", funcSym(fn), name())
}
return uintptrEscapesTag
}
}
for _, fs := range types.RecvsParams {
for _, f := range fs(fn.Type).Fields().Slice() {
if !types.Haspointers(f.Type) { // don't bother tagging for scalars
continue
}
if f.Note == uintptrEscapesTag {
// Note is already set in the loop above.
continue
}
// Unnamed parameters are unused and therefore do not escape.
if f.Sym == nil || f.Sym.IsBlank() {
f.Note = mktag(EscNone)
continue
}
switch esc := asNode(f.Nname).Esc; esc & EscMask {
case EscNone, // not touched by escflood
EscReturn:
f.Note = mktag(int(esc))
case EscHeap: // touched by escflood, moved to heap
}
}
if !types.Haspointers(f.Type) { // don't bother tagging for scalars
return ""
}
// Unnamed parameters are unused and therefore do not escape.
if f.Sym == nil || f.Sym.IsBlank() {
return mktag(EscNone)
}
n := asNode(f.Nname)
return mktag(int(n.Esc))
}