devirtualize

Imports

Imports #

"cmd/compile/internal/base"
"cmd/compile/internal/ir"
"cmd/compile/internal/typecheck"
"cmd/compile/internal/types"
"cmd/compile/internal/base"
"cmd/compile/internal/inline"
"cmd/compile/internal/ir"
"cmd/compile/internal/logopt"
"cmd/compile/internal/pgoir"
"cmd/compile/internal/typecheck"
"cmd/compile/internal/types"
"cmd/internal/obj"
"cmd/internal/src"
"encoding/json"
"fmt"
"os"
"strings"

Structs

CallStat struct #

CallStat summarizes a single call site. This is used only for debug logging.

type CallStat struct {
Pkg string
Pos string
Caller string
Direct bool
Interface bool
Weight int64
Hottest string
HottestWeight int64
Devirtualized string
DevirtualizedWeight int64
}

Functions

ProfileGuided function #

ProfileGuided performs call devirtualization of indirect calls based on profile information. Specifically, it performs conditional devirtualization of interface calls or function value calls for the hottest callee. That is, for interface calls it performs a transformation like: type Iface interface { Foo() } type Concrete struct{} func (Concrete) Foo() {} func foo(i Iface) { i.Foo() } to: func foo(i Iface) { if c, ok := i.(Concrete); ok { c.Foo() } else { i.Foo() } } For function value calls it performs a transformation like: func Concrete() {} func foo(fn func()) { fn() } to: func foo(fn func()) { if internal/abi.FuncPCABIInternal(fn) == internal/abi.FuncPCABIInternal(Concrete) { Concrete() } else { fn() } } The primary benefit of this transformation is enabling inlining of the direct call.

func ProfileGuided(fn *ir.Func, p *pgoir.Profile)

StaticCall function #

StaticCall devirtualizes the given call if possible when the concrete callee is available statically.

func StaticCall(call *ir.CallExpr)

condCall function #

condCall returns an ir.InlinedCallExpr that performs a call to thenCall if cond is true and elseCall if cond is false. The return variables of the InlinedCallExpr evaluate to the return values from the call.

func condCall(curfn *ir.Func, pos src.XPos, cond ir.Node, thenCall *ir.CallExpr, elseCall *ir.CallExpr, init ir.Nodes) *ir.InlinedCallExpr

constructCallStat function #

constructCallStat builds an initial CallStat describing this call, for logging. If the call is devirtualized, the devirtualization fields should be updated.

func constructCallStat(p *pgoir.Profile, fn *ir.Func, name string, call *ir.CallExpr) *CallStat

copyInputs function #

copyInputs copies the inputs to a call: the receiver (for interface calls) or function value (for function value calls) and the arguments. These expressions are evaluated once and assigned to temporaries. The assignment statement is added to init and the copied receiver/fn expression and copied arguments expressions are returned.

func copyInputs(curfn *ir.Func, pos src.XPos, recvOrFn ir.Node, args []ir.Node, init *ir.Nodes) (ir.Node, []ir.Node)

findHotConcreteCallee function #

findHotConcreteCallee returns the *ir.Func of the hottest callee of a call, if available, and its edge weight. extraFn can perform additional applicability checks on each candidate edge. If extraFn returns false, candidate will not be considered a valid callee candidate.

func findHotConcreteCallee(p *pgoir.Profile, caller *ir.Func, call *ir.CallExpr, extraFn func(callerName string, callOffset int, candidate *pgoir.IREdge) bool) (*ir.Func, int64)

findHotConcreteFunctionCallee function #

findHotConcreteFunctionCallee returns the *ir.Func of the hottest callee of an indirect function call, if available, and its edge weight.

func findHotConcreteFunctionCallee(p *pgoir.Profile, caller *ir.Func, call *ir.CallExpr) (*ir.Func, int64)

findHotConcreteInterfaceCallee function #

findHotConcreteInterfaceCallee returns the *ir.Func of the hottest callee of an interface call, if available, and its edge weight.

func findHotConcreteInterfaceCallee(p *pgoir.Profile, caller *ir.Func, call *ir.CallExpr) (*ir.Func, int64)

interfaceCallRecvTypeAndMethod function #

interfaceCallRecvTypeAndMethod returns the type and the method of the interface used in an interface call.

func interfaceCallRecvTypeAndMethod(call *ir.CallExpr) (*types.Type, *types.Sym)

maybeDevirtualizeFunctionCall function #

Devirtualize an indirect function call if possible and eligible. Returns the new ir.Node if call was devirtualized, and if so also the callee and weight of the devirtualized edge.

func maybeDevirtualizeFunctionCall(p *pgoir.Profile, fn *ir.Func, call *ir.CallExpr) (ir.Node, *ir.Func, int64)

maybeDevirtualizeInterfaceCall function #

Devirtualize interface call if possible and eligible. Returns the new ir.Node if call was devirtualized, and if so also the callee and weight of the devirtualized edge.

func maybeDevirtualizeInterfaceCall(p *pgoir.Profile, fn *ir.Func, call *ir.CallExpr) (ir.Node, *ir.Func, int64)

methodRecvType function #

methodRecvType returns the type containing method fn. Returns nil if fn is not a method.

func methodRecvType(fn *ir.Func) *types.Type

retTemps function #

retTemps returns a slice of temporaries to be used for storing result values from call.

func retTemps(curfn *ir.Func, pos src.XPos, call *ir.CallExpr) []ir.Node

rewriteFunctionCall function #

rewriteFunctionCall devirtualizes the given OCALLFUNC using a direct function call to callee.

func rewriteFunctionCall(call *ir.CallExpr, curfn *ir.Func, callee *ir.Func) ir.Node

rewriteInterfaceCall function #

rewriteInterfaceCall devirtualizes the given interface call using a direct method call to concretetyp.

func rewriteInterfaceCall(call *ir.CallExpr, curfn *ir.Func, callee *ir.Func, concretetyp *types.Type) ir.Node

shouldPGODevirt function #

shouldPGODevirt checks if we should perform PGO devirtualization to the target function. PGO devirtualization is most valuable when the callee is inlined, so if it won't inline we can skip devirtualizing.

func shouldPGODevirt(fn *ir.Func) bool

Generated with Arrow