]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: gracefully fallback when inline bodies are missing
authorMatthew Dempsky <mdempsky@google.com>
Thu, 4 Nov 2021 20:28:25 +0000 (13:28 -0700)
committerMatthew Dempsky <mdempsky@google.com>
Fri, 5 Nov 2021 07:00:05 +0000 (07:00 +0000)
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>
src/cmd/compile/internal/inline/inl.go
src/cmd/compile/internal/typecheck/crawler.go
src/cmd/compile/internal/typecheck/iimport.go

index b764aed534db7ffcf93aa18e1dad1a6c23e1036b..47b895f7e3fcebe6aada70c85f294b6f0835b2d4 100644 (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)
                }
        }
index ae2b3b1df4e1ca8d95692533071e71128cf6d325..ae6542d071976ffc0a80457364c8f2138a4e203e 100644 (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
        }
 
index 7c6c23e73714515a322c25c20c2672223d398236..26bc838ed99f8293679f3d3d452b175ac8ca4740 100644 (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 {