escape

Imports

Imports #

"cmd/compile/internal/base"
"math"
"strings"
"cmd/compile/internal/base"
"cmd/compile/internal/ir"
"fmt"
"cmd/compile/internal/base"
"cmd/compile/internal/ir"
"cmd/compile/internal/base"
"cmd/compile/internal/ir"
"cmd/compile/internal/typecheck"
"cmd/compile/internal/types"
"cmd/internal/src"
"strings"
"cmd/compile/internal/base"
"cmd/compile/internal/ir"
"cmd/compile/internal/types"
"cmd/compile/internal/base"
"cmd/compile/internal/ir"
"cmd/compile/internal/logopt"
"cmd/compile/internal/types"
"fmt"
"cmd/compile/internal/base"
"cmd/compile/internal/ir"
"cmd/compile/internal/logopt"
"cmd/internal/src"
"fmt"
"strings"
"cmd/compile/internal/ir"
"cmd/compile/internal/typecheck"
"cmd/compile/internal/types"
"fmt"
"cmd/compile/internal/base"
"cmd/compile/internal/ir"
"cmd/compile/internal/logopt"
"cmd/compile/internal/typecheck"
"cmd/compile/internal/types"
"cmd/internal/src"

Constants & Variables

attrCalls const #

attrCalls indicates whether closures that are reachable from this location may be called without tracking their results. This is used to better optimize indirect closure calls.

const attrCalls

attrEscapes const #

attrEscapes indicates whether the represented variable's address escapes; that is, whether the variable must be heap allocated.

const attrEscapes locAttr = *ast.BinaryExpr

attrMutates const #

attrMutates indicates whether pointers that are reachable from this location may have their addressed memory mutated. This is used to detect string->[]byte conversions that can be safely optimized away.

const attrMutates

attrPersists const #

attrPersists indicates whether the represented expression's address outlives the statement; that is, whether its storage cannot be immediately reused.

const attrPersists

escFuncPlanned const #

const escFuncPlanned

escFuncStarted const #

const escFuncStarted

escFuncTagged const #

const escFuncTagged

escFuncUnknown const #

const escFuncUnknown = *ast.BinaryExpr

leakCallee const #

const leakCallee

leakHeap const #

const leakHeap = iota

leakMutator const #

const leakMutator

leakResult0 const #

const leakResult0

leakTagCache var #

var leakTagCache = map[leaks]string{...}

looping const #

const looping labelState = *ast.BinaryExpr

nonlooping const #

const nonlooping

numEscResults const #

const numEscResults = *ast.BinaryExpr

Type Aliases

labelState type #

Mark labels that have no backjumps to them as not increasing e.loopdepth.

type labelState int

leaks type #

A leaks represents a set of assignment flows from a parameter to the heap, mutator, callee, or to any of its function's (first numEscResults) result parameters.

type leaks [8]uint8

locAttr type #

type locAttr uint8

Structs

batch struct #

A batch holds escape analysis state that's shared across an entire batch of functions being analyzed at once.

type batch struct {
allLocs []*location
closures []closure
heapLoc location
mutatorLoc location
calleeLoc location
blankLoc location
}

closure struct #

A closure holds a closure expression and its spill hole (i.e., where the hole representing storing into its closure record).

type closure struct {
k hole
clo *ir.ClosureExpr
}

edge struct #

An edge represents an assignment edge between two Go variables.

type edge struct {
src *location
derefs int
notes *note
}

escape struct #

An escape holds state specific to a single function being analyzed within a batch.

type escape struct {
*batch
curfn *ir.Func
labels map[*types.Sym]labelState
loopDepth int
}

hole struct #

A hole represents a context for evaluation of a Go expression. E.g., when evaluating p in "x = **p", we'd have a hole with dst==x and derefs==2.

type hole struct {
dst *location
derefs int
notes *note
addrtaken bool
}

location struct #

A location represents an abstract location that stores a Go variable.

type location struct {
n ir.Node
curfn *ir.Func
edges []edge
loopDepth int
resultIndex int
derefs int
walkgen uint32
dst *location
dstEdgeIdx int
queued bool
attrs locAttr
paramEsc leaks
captured bool
reassigned bool
addrtaken bool
}

note struct #

type note struct {
next *note
where ir.Node
why string
}

Functions

AddCallee method #

AddCallee adds an assignment flow from l to the callee operand of a call expression.

func (l *leaks) AddCallee(derefs int)

AddHeap method #

AddHeap adds an assignment flow from l to the heap.

func (l *leaks) AddHeap(derefs int)

AddMutator method #

AddMutator adds a flow from l to the mutator (i.e., a pointer operand of an indirect assignment statement).

func (l *leaks) AddMutator(derefs int)

AddResult method #

AddResult adds an assignment flow from l to its function's i'th result parameter.

func (l *leaks) AddResult(i int, derefs int)

Batch function #

Batch performs escape analysis on a minimal batch of functions.

func Batch(fns []*ir.Func, recursive bool)

Callee method #

Callee returns the minimum deref count of any assignment flow from l to the callee operand of call expression. If no such flows exist, Callee returns -1.

func (l leaks) Callee() int

Encode method #

Encode converts l into a binary string for export data.

func (l leaks) Encode() string

Fmt function #

Fmt is called from node printing to print information about escape analysis results.

func Fmt(n ir.Node) string

Funcs function #

func Funcs(all []*ir.Func)

Heap method #

Heap returns the minimum deref count of any assignment flow from l to the heap. If no such flows exist, Heap returns -1.

func (l leaks) Heap() int

HeapAllocReason function #

HeapAllocReason returns the reason the given Node must be heap allocated, or the empty string if it doesn't.

func HeapAllocReason(n ir.Node) string

Mutator method #

Mutator returns the minimum deref count of any assignment flow from l to the pointer operand of an indirect assignment statement. If no such flows exist, Mutator returns -1.

func (l leaks) Mutator() int

Optimize method #

Optimize removes result flow paths that are equal in length or longer than the shortest heap flow path.

func (l *leaks) Optimize()

Result method #

Result returns the minimum deref count of any assignment flow from l to its function's i'th result parameter. If no such flows exist, Result returns -1.

func (l leaks) Result(i int) int

add method #

func (l *leaks) add(i int, derefs int)

addr method #

func (k hole) addr(where ir.Node, why string) hole

addr method #

addr evaluates an addressable expression n and returns a hole that represents storing into the represented location.

func (e *escape) addr(n ir.Node) hole

addrs method #

func (e *escape) addrs(l ir.Nodes) []hole

asHole method #

func (l *location) asHole() hole

assignHeap method #

func (e *escape) assignHeap(src ir.Node, why string, where ir.Node)

assignList method #

assignList evaluates the assignment dsts... = srcs....

func (e *escape) assignList(dsts []ir.Node, srcs []ir.Node, why string, where ir.Node)

block method #

block is like stmts, but preserves loopDepth.

func (e *escape) block(l ir.Nodes)

call method #

call evaluates a call expressions, including builtin calls. ks should contain the holes representing where the function callee's results flows.

func (e *escape) call(ks []hole, call ir.Node)

calleeHole method #

func (b *batch) calleeHole() hole

containsClosure function #

containsClosure reports whether c is a closure contained within f.

func containsClosure(f *ir.Func, c *ir.Func) bool

copyExpr method #

copyExpr creates and returns a new temporary variable within fn; appends statements to init to declare and initialize it to expr; and escape analyzes the data flow.

func (e *escape) copyExpr(pos src.XPos, expr ir.Node, init *ir.Nodes) *ir.Name

dcl method #

func (e *escape) dcl(n *ir.Name) hole

deref method #

func (k hole) deref(where ir.Node, why string) hole

discard method #

discard evaluates an expression n for side-effects, but discards its value.

func (e *escape) discard(n ir.Node)

discardHole method #

func (b *batch) discardHole() hole

discards method #

func (e *escape) discards(l ir.Nodes)

dotType method #

func (k hole) dotType(t *types.Type, where ir.Node, why string) hole

explainFlow method #

func (b *batch) explainFlow(pos string, dst *location, srcloc *location, derefs int, notes *note, explanation []*logopt.LoggedOpt) []*logopt.LoggedOpt

explainLoc method #

func (b *batch) explainLoc(l *location) string

explainPath method #

explainPath prints an explanation of how src flows to the walk root.

func (b *batch) explainPath(root *location, src *location) []*logopt.LoggedOpt

expr method #

expr models evaluating an expression n and flowing the result into hole k.

func (e *escape) expr(k hole, n ir.Node)

exprSkipInit method #

func (e *escape) exprSkipInit(k hole, n ir.Node)

finish method #

func (b *batch) finish(fns []*ir.Func)

flow method #

func (b *batch) flow(k hole, src *location)

flowClosure method #

func (b *batch) flowClosure(k hole, clo *ir.ClosureExpr)

get method #

func (l leaks) get(i int) int

goDeferStmt method #

goDeferStmt analyzes a "go" or "defer" statement.

func (e *escape) goDeferStmt(n *ir.GoDeferStmt)

hasAttr method #

func (l *location) hasAttr(attr locAttr) bool

hasNonStringPointers function #

func hasNonStringPointers(t *types.Type) bool

heapHole method #

func (b *batch) heapHole() hole

inMutualBatch method #

inMutualBatch reports whether function fn is in the batch of mutually recursive functions being analyzed. When this is true, fn has not yet been analyzed, so its parameters and results should be incorporated directly into the flow graph instead of relying on its escape analysis tagging.

func (b *batch) inMutualBatch(fn *ir.Name) bool

initFunc method #

func (b *batch) initFunc(fn *ir.Func)

isName method #

func (l *location) isName(c ir.Class) bool

isSelfAssign function #

isSelfAssign reports whether assignment from src to dst can be ignored by the escape analysis as it's effectively a self-assignment.

func isSelfAssign(dst ir.Node, src ir.Node) bool

isSliceSelfAssign function #

func isSliceSelfAssign(dst ir.Node, src ir.Node) bool

later method #

later returns a new hole that flows into k, but some time later. Its main effect is to prevent immediate reuse of temporary variables introduced during Order.

func (e *escape) later(k hole) hole

leakTo method #

leak records that parameter l leaks to sink.

func (l *location) leakTo(sink *location, derefs int)

leakTo method #

leakTo records that parameter l leaks to sink.

func (b *batch) leakTo(l *location, sink *location, derefs int)

mayAffectMemory function #

mayAffectMemory reports whether evaluation of n may affect the program's memory state. If the expression can't affect memory state, then it can be safely ignored by the escape analysis.

func mayAffectMemory(n ir.Node) bool

mutate method #

func (e *escape) mutate(n ir.Node)

mutatorHole method #

func (b *batch) mutatorHole() hole

newLoc method #

func (e *escape) newLoc(n ir.Node, persists bool) *location

note method #

func (k hole) note(where ir.Node, why string) hole

oldLoc method #

func (b *batch) oldLoc(n *ir.Name) *location

outlives method #

outlives reports whether values stored in l may survive beyond other's lifetime if stack allocated.

func (b *batch) outlives(l *location, other *location) bool

paramTag method #

func (b *batch) paramTag(fn *ir.Func, narg int, f *types.Field) string

parseLeaks function #

parseLeaks parses a binary string representing a leaks.

func parseLeaks(s string) leaks

reassigned method #

reassigned marks the locations associated with the given holes as reassigned, unless the location represents a variable declared and assigned exactly once by where.

func (e *escape) reassigned(ks []hole, where ir.Node)

reportLeaks method #

func (b *batch) reportLeaks(pos src.XPos, name string, esc leaks, sig *types.Type)

rewriteArgument method #

rewriteArgument rewrites the argument arg of the given call expression. fn is the static callee function, if known.

func (e *escape) rewriteArgument(arg ir.Node, call *ir.CallExpr, fn *ir.Name)

set method #

func (l *leaks) set(i int, derefs int)

shift method #

func (k hole) shift(delta int) hole

spill method #

spill allocates a new location associated with expression n, flows its address to k, and returns a hole that flows values to it. It's intended for use with most expressions that allocate storage.

func (e *escape) spill(k hole, n ir.Node) hole

stmt method #

stmt evaluates a single Go statement.

func (e *escape) stmt(n ir.Node)

stmts method #

func (e *escape) stmts(l ir.Nodes)

tagHole method #

tagHole returns a hole for evaluating an argument passed to param. ks should contain the holes representing where the function callee's results flows. fn is the statically-known callee function, if any.

func (e *escape) tagHole(ks []hole, fn *ir.Name, param *types.Field) hole

teeHole method #

teeHole returns a new hole that flows into each hole of ks, similar to the Unix tee(1) command.

func (e *escape) teeHole(ks ...hole) hole

unsafeValue method #

unsafeValue evaluates a uintptr-typed arithmetic expression looking for conversions from an unsafe.Pointer.

func (e *escape) unsafeValue(k hole, n ir.Node)

walkAll method #

walkAll computes the minimal dereferences between all pairs of locations.

func (b *batch) walkAll()

walkFunc method #

func (b *batch) walkFunc(fn *ir.Func)

walkOne method #

walkOne computes the minimal number of dereferences from root to all other locations.

func (b *batch) walkOne(root *location, walkgen uint32, enqueue func(*location))

with method #

func (b *batch) with(fn *ir.Func) *escape

Generated with Arrow