]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: delay inlinable method compilation for -c=1
authorThan McIntosh <thanm@google.com>
Fri, 15 May 2020 16:19:07 +0000 (12:19 -0400)
committerThan McIntosh <thanm@google.com>
Thu, 21 May 2020 14:45:26 +0000 (14:45 +0000)
When the concurrent back end is not enabled, it is possible to have a
scenario where: we compile a specific inlinable non-pointer-receiver
method T.M, then at some point later on in the compilation we visit a
type that triggers generation of a pointer-receiver wrapper (*T).M,
which then results in an inline of T.M into (*T).M. This introduces
subtle differences in the DWARF as compared with when the concurrent
back end is enabled (in the concurrent case, by the time we run the
SSA back end on T.M is is marked as being inlined, whereas in the
non-current case it is not marked inlined).

As a fix, at the point where we would normally compile a given
function in the xtop list right away, if the function is a method AND
is inlinable AND hasn't been inlined, then delay its compilation until
compileFunctions (so as to make sure that when we do compile it, all
possible inlining has been complete). In addition, make sure that
the abstract function symbol for the inlined function gets recorded
correctly.

Fixes #38068.

Change-Id: I57410ab5658bd4ee5b4b80750518e9b20fd6ba52
Reviewed-on: https://go-review.googlesource.com/c/go/+/234178
Run-TryBot: Than McIntosh <thanm@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/gc/pgen.go
src/cmd/internal/obj/objfile.go

index 6ccd0b8d943a70a060da296b47703e1050d42ad9..74654c86bc07774219df28ca16a690a447420f83 100644 (file)
@@ -271,7 +271,7 @@ func compile(fn *Node) {
                }
        }
 
-       if compilenow() {
+       if compilenow(fn) {
                compileSSA(fn, 0)
        } else {
                compilequeue = append(compilequeue, fn)
@@ -282,10 +282,31 @@ func compile(fn *Node) {
 // If functions are not compiled immediately,
 // they are enqueued in compilequeue,
 // which is drained by compileFunctions.
-func compilenow() bool {
+func compilenow(fn *Node) bool {
+       // Issue 38068: if this function is a method AND an inline
+       // candidate AND was not inlined (yet), put it onto the compile
+       // queue instead of compiling it immediately. This is in case we
+       // wind up inlining it into a method wrapper that is generated by
+       // compiling a function later on in the xtop list.
+       if fn.IsMethod() && isInlinableButNotInlined(fn) {
+               return false
+       }
        return nBackendWorkers == 1 && Debug_compilelater == 0
 }
 
+// isInlinableButNotInlined returns true if 'fn' was marked as an
+// inline candidate but then never inlined (presumably because we
+// found no call sites).
+func isInlinableButNotInlined(fn *Node) bool {
+       if fn.Func.Nname.Func.Inl == nil {
+               return false
+       }
+       if fn.Sym == nil {
+               return true
+       }
+       return !fn.Sym.Linksym().WasInlined()
+}
+
 const maxStackSize = 1 << 30
 
 // compileSSA builds an SSA backend function,
index 6d7f42ed0b069902370e6ab75038fccaef0411f6..93c313862e3d9ad322e19dc2283072cb27df6a67 100644 (file)
@@ -788,6 +788,14 @@ func (ft *DwarfFixupTable) SetPrecursorFunc(s *LSym, fn interface{}) {
        absfn.Type = objabi.SDWARFINFO
        ft.ctxt.Data = append(ft.ctxt.Data, absfn)
 
+       // In the case of "late" inlining (inlines that happen during
+       // wrapper generation as opposed to the main inlining phase) it's
+       // possible that we didn't cache the abstract function sym for the
+       // text symbol -- do so now if needed. See issue 38068.
+       if s.Func != nil && s.Func.dwarfAbsFnSym == nil {
+               s.Func.dwarfAbsFnSym = absfn
+       }
+
        ft.precursor[s] = fnState{precursor: fn, absfn: absfn}
 }