1
0
mirror of https://github.com/golang/go synced 2024-11-24 09:50:17 -07:00

cmd/compile: gracefully fallback when inline bodies are missing

Currently, we rely on a "crawling" step during export to identify
function and method bodies that need to be exported or re-exported so
we can trim out unnecessary ones and reduce build artifact sizes. To
catch cases where we expect a function to be inlinable but we failed
to export its body, we made this condition a fatal compiler error.

However, with generics, it's much harder to perfectly identify all
function bodies that need to be exported; and several attempts at
tweaking the algorithm have resulted in still having failure cases.
So for now, this CL changes a missing inline body into a graceful
failure instead.

Change-Id: I04b0872d0dcaae9c3de473e92ce584e4ec6fd782
Reviewed-on: https://go-review.googlesource.com/c/go/+/361403
Trust: Matthew Dempsky <mdempsky@google.com>
Trust: Dan Scales <danscales@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Dan Scales <danscales@google.com>
This commit is contained in:
Matthew Dempsky 2021-11-04 13:28:25 -07:00
parent b68c02e291
commit 6fefb7f9f3
3 changed files with 24 additions and 3 deletions

View File

@ -309,7 +309,7 @@ func (v *hairyVisitor) doNode(n ir.Node) bool {
break
}
if fn := inlCallee(n.X); fn != nil && fn.Inl != nil {
if fn := inlCallee(n.X); fn != nil && typecheck.HaveInlineBody(fn) {
v.budget -= fn.Inl.Cost
break
}
@ -585,7 +585,7 @@ func inlnode(n ir.Node, maxCost int32, inlMap map[*ir.Func]bool, edit func(ir.No
if ir.IsIntrinsicCall(call) {
break
}
if fn := inlCallee(call.X); fn != nil && fn.Inl != nil {
if fn := inlCallee(call.X); fn != nil && typecheck.HaveInlineBody(fn) {
n = mkinlcall(call, fn, maxCost, inlMap, edit)
}
}

View File

@ -207,7 +207,7 @@ func (p *crawler) markInlBody(n *ir.Name) {
if fn == nil {
base.Fatalf("markInlBody: missing Func on %v", n)
}
if fn.Inl == nil {
if !HaveInlineBody(fn) {
return
}

View File

@ -81,6 +81,27 @@ func ImportBody(fn *ir.Func) {
inimport = false
}
// HaveInlineBody reports whether we have fn's inline body available
// for inlining.
func HaveInlineBody(fn *ir.Func) bool {
if fn.Inl == nil {
return false
}
// Unified IR is much more conservative about pruning unreachable
// methods (at the cost of increased build artifact size).
if base.Debug.Unified != 0 {
return true
}
if fn.Inl.Body != nil {
return true
}
_, ok := inlineImporter[fn.Nname.Sym()]
return ok
}
func importReaderFor(sym *types.Sym, importers map[*types.Sym]iimporterAndOffset) *importReader {
x, ok := importers[sym]
if !ok {