mirror of
https://github.com/golang/go
synced 2024-11-24 09:30:07 -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:
parent
b68c02e291
commit
6fefb7f9f3
@ -309,7 +309,7 @@ func (v *hairyVisitor) doNode(n ir.Node) bool {
|
|||||||
break
|
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
|
v.budget -= fn.Inl.Cost
|
||||||
break
|
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) {
|
if ir.IsIntrinsicCall(call) {
|
||||||
break
|
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)
|
n = mkinlcall(call, fn, maxCost, inlMap, edit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,7 +207,7 @@ func (p *crawler) markInlBody(n *ir.Name) {
|
|||||||
if fn == nil {
|
if fn == nil {
|
||||||
base.Fatalf("markInlBody: missing Func on %v", n)
|
base.Fatalf("markInlBody: missing Func on %v", n)
|
||||||
}
|
}
|
||||||
if fn.Inl == nil {
|
if !HaveInlineBody(fn) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,6 +81,27 @@ func ImportBody(fn *ir.Func) {
|
|||||||
inimport = false
|
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 {
|
func importReaderFor(sym *types.Sym, importers map[*types.Sym]iimporterAndOffset) *importReader {
|
||||||
x, ok := importers[sym]
|
x, ok := importers[sym]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
Loading…
Reference in New Issue
Block a user