mirror of
https://github.com/golang/go.git
synced 2025-05-23 00:11:26 +00: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:
parent
cf630586ca
commit
23bf6af996
@ -212,6 +212,8 @@ var tags [1 << (bitsPerOutputInTag + EscReturnBits)]string
|
|||||||
// mktag returns the string representation for an escape analysis tag.
|
// mktag returns the string representation for an escape analysis tag.
|
||||||
func mktag(mask int) string {
|
func mktag(mask int) string {
|
||||||
switch mask & EscMask {
|
switch mask & EscMask {
|
||||||
|
case EscHeap:
|
||||||
|
return ""
|
||||||
case EscNone, EscReturn:
|
case EscNone, EscReturn:
|
||||||
default:
|
default:
|
||||||
Fatalf("escape mktag")
|
Fatalf("escape mktag")
|
||||||
@ -406,88 +408,74 @@ const uintptrEscapesTag = "uintptr-escapes"
|
|||||||
func esctag(fn *Node) {
|
func esctag(fn *Node) {
|
||||||
fn.Esc = EscFuncTagged
|
fn.Esc = EscFuncTagged
|
||||||
|
|
||||||
name := func(s *types.Sym, narg int) string {
|
narg := 0
|
||||||
if s != nil {
|
for _, fs := range types.RecvsParams {
|
||||||
return s.Name
|
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)
|
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.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.
|
// Assume that uintptr arguments must be held live across the call.
|
||||||
// This is most important for syscall.Syscall.
|
// This is most important for syscall.Syscall.
|
||||||
// See golang.org/issue/13372.
|
// See golang.org/issue/13372.
|
||||||
// This really doesn't have much to do with escape analysis per se,
|
// This really doesn't have much to do with escape analysis per se,
|
||||||
// but we are reusing the ability to annotate an individual function
|
// but we are reusing the ability to annotate an individual function
|
||||||
// argument and pass those annotations along to importing code.
|
// argument and pass those annotations along to importing code.
|
||||||
narg := 0
|
if f.Type.Etype == TUINTPTR {
|
||||||
for _, f := range fn.Type.Params().Fields().Slice() {
|
if Debug['m'] != 0 {
|
||||||
narg++
|
Warnl(fn.Pos, "%v assuming %v is unsafe uintptr", funcSym(fn), name())
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
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 {
|
if fn.Func.Pragma&UintptrEscapes != 0 {
|
||||||
narg := 0
|
if f.Type.Etype == TUINTPTR {
|
||||||
for _, f := range fn.Type.Params().Fields().Slice() {
|
if Debug['m'] != 0 {
|
||||||
narg++
|
Warnl(fn.Pos, "%v marking %v as escaping uintptr", funcSym(fn), name())
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
return uintptrEscapesTag
|
||||||
if f.IsDDD() && f.Type.Elem().Etype == TUINTPTR {
|
}
|
||||||
// final argument is ...uintptr.
|
if f.IsDDD() && f.Type.Elem().Etype == TUINTPTR {
|
||||||
if Debug['m'] != 0 {
|
// final argument is ...uintptr.
|
||||||
Warnl(fn.Pos, "%v marking %v as escaping ...uintptr", funcSym(fn), name(f.Sym, narg))
|
if Debug['m'] != 0 {
|
||||||
}
|
Warnl(fn.Pos, "%v marking %v as escaping ...uintptr", funcSym(fn), name())
|
||||||
f.Note = uintptrEscapesTag
|
|
||||||
}
|
}
|
||||||
|
return uintptrEscapesTag
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, fs := range types.RecvsParams {
|
if !types.Haspointers(f.Type) { // don't bother tagging for scalars
|
||||||
for _, f := range fs(fn.Type).Fields().Slice() {
|
return ""
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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))
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user