in tool/instrument/optimize.go [241:306]
func (rp *RuleProcessor) optimizeTJumps() (err error) {
for _, tjump := range rp.trampolineJumps {
mustTJump(tjump.ifStmt)
// Strip the trampoline-jump-if anchor label as no longer needed
stripTJumpLabel(tjump)
// No onExit hook present? Simply remove defer call to onExit trampoline.
// Why we dont remove the whole else block of trampoline-jump-if? Well,
// because there might be more than one trampoline-jump-if in the same
// function, they are nested in the else block. See findJumpPoint for
// more details.
// TODO: Remove corresponding CallContextImpl methods
rule := tjump.rule
removedOnExit := false
if rule.OnExit == "" {
err = rp.removeOnExitTrampolineCall(tjump)
if err != nil {
return err
}
removedOnExit = true
}
// No onEnter hook present? Construct CallContext on the fly and pass it
// to onExit trampoline defer call and rewrite the whole condition to
// always false, then null out its initialization statement.
if rule.OnEnter == "" {
err = rp.removeOnEnterTrampolineCall(tjump)
if err != nil {
return err
}
}
// No SkipCall used in onEnter hook? Rewrite cond of trampoline-jump-if
// to always false, and remove return statement in then block, they are
// memory aware and may generate memory SSA values during compilation.
// This further simplifies the trampoline-jump-if and gives more chances
// for optimization passes to kick in.
if rule.OnEnter != "" {
onEnterHook, err := getHookFunc(rule, true)
if err != nil {
return err
}
foundPoison := false
const poison = "SkipCall"
// FIXME: We should traverse the call graph to find all possible
// usage of SkipCall, but for now, we just check the onEnter hook
// function body.
dst.Inspect(onEnterHook, func(node dst.Node) bool {
if ident, ok := node.(*dst.Ident); ok {
if strings.Contains(ident.Name, poison) {
foundPoison = true
return false
}
}
if foundPoison {
return false
}
return true
})
if !foundPoison {
flattenTJump(tjump, removedOnExit)
}
}
}
return nil
}