mirror of
https://github.com/golang/go
synced 2024-11-23 05:00:07 -07:00
cmd/compile/internal/gc: steps towards work-queue
This CL reorganizes the top-level functions for handling package-level declarations, runtime type descriptors, and SSA compilation to work in a loop. This generalizes the loop that previously existed in dumpdata. Change-Id: I0e51e60f6ef9e7f96a4a3ccd5801f7baf83eba9a Reviewed-on: https://go-review.googlesource.com/c/go/+/520611 Run-TryBot: Matthew Dempsky <mdempsky@google.com> Auto-Submit: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
This commit is contained in:
parent
7af28fa90e
commit
ca858a43f4
@ -113,10 +113,6 @@ func prepareFunc(fn *ir.Func) {
|
|||||||
// It fans out nBackendWorkers to do the work
|
// It fans out nBackendWorkers to do the work
|
||||||
// and waits for them to complete.
|
// and waits for them to complete.
|
||||||
func compileFunctions() {
|
func compileFunctions() {
|
||||||
if len(compilequeue) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if race.Enabled {
|
if race.Enabled {
|
||||||
// Randomize compilation order to try to shake out races.
|
// Randomize compilation order to try to shake out races.
|
||||||
tmp := make([]*ir.Func, len(compilequeue))
|
tmp := make([]*ir.Func, len(compilequeue))
|
||||||
|
@ -298,18 +298,47 @@ func Main(archInit func(*ssagen.ArchInfo)) {
|
|||||||
|
|
||||||
ir.CurFunc = nil
|
ir.CurFunc = nil
|
||||||
|
|
||||||
// Compile top level functions.
|
reflectdata.WriteBasicTypes()
|
||||||
// Don't use range--walk can add functions to Target.Decls.
|
|
||||||
base.Timer.Start("be", "compilefuncs")
|
|
||||||
fcount := int64(0)
|
|
||||||
for i := 0; i < len(typecheck.Target.Funcs); i++ {
|
|
||||||
fn := typecheck.Target.Funcs[i]
|
|
||||||
enqueueFunc(fn)
|
|
||||||
fcount++
|
|
||||||
}
|
|
||||||
base.Timer.AddEvent(fcount, "funcs")
|
|
||||||
|
|
||||||
|
// Compile top-level declarations.
|
||||||
|
//
|
||||||
|
// There are cyclic dependencies between all of these phases, so we
|
||||||
|
// need to iterate all of them until we reach a fixed point.
|
||||||
|
base.Timer.Start("be", "compilefuncs")
|
||||||
|
for nextFunc, nextExtern := 0, 0; ; {
|
||||||
|
reflectdata.WriteRuntimeTypes()
|
||||||
|
|
||||||
|
if nextExtern < len(typecheck.Target.Externs) {
|
||||||
|
switch n := typecheck.Target.Externs[nextExtern]; n.Op() {
|
||||||
|
case ir.ONAME:
|
||||||
|
dumpGlobal(n)
|
||||||
|
case ir.OLITERAL:
|
||||||
|
dumpGlobalConst(n)
|
||||||
|
case ir.OTYPE:
|
||||||
|
reflectdata.NeedRuntimeType(n.Type())
|
||||||
|
}
|
||||||
|
nextExtern++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if nextFunc < len(typecheck.Target.Funcs) {
|
||||||
|
enqueueFunc(typecheck.Target.Funcs[nextFunc])
|
||||||
|
nextFunc++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// The SSA backend supports using multiple goroutines, so keep it
|
||||||
|
// as the last step to maximize how much work we can batch and
|
||||||
|
// process concurrently.
|
||||||
|
if len(compilequeue) != 0 {
|
||||||
compileFunctions()
|
compileFunctions()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
base.Timer.AddEvent(int64(len(typecheck.Target.Funcs)), "funcs")
|
||||||
|
|
||||||
if base.Flag.CompilingRuntime {
|
if base.Flag.CompilingRuntime {
|
||||||
// Write barriers are now known. Check the call graph.
|
// Write barriers are now known. Check the call graph.
|
||||||
|
@ -110,39 +110,11 @@ func dumpCompilerObj(bout *bio.Writer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func dumpdata() {
|
func dumpdata() {
|
||||||
numExterns := len(typecheck.Target.Externs)
|
reflectdata.WriteGCSymbols()
|
||||||
numDecls := len(typecheck.Target.Funcs)
|
|
||||||
dumpglobls(typecheck.Target.Externs)
|
|
||||||
addsignats(typecheck.Target.Externs)
|
|
||||||
reflectdata.WriteRuntimeTypes()
|
|
||||||
reflectdata.WritePluginTable()
|
reflectdata.WritePluginTable()
|
||||||
reflectdata.WriteImportStrings()
|
reflectdata.WriteImportStrings()
|
||||||
reflectdata.WriteBasicTypes()
|
|
||||||
dumpembeds()
|
dumpembeds()
|
||||||
|
|
||||||
// Calls to WriteRuntimeTypes can generate functions,
|
|
||||||
// like method wrappers and hash and equality routines.
|
|
||||||
// Compile any generated functions, process any new resulting types, repeat.
|
|
||||||
// This can't loop forever, because there is no way to generate an infinite
|
|
||||||
// number of types in a finite amount of code.
|
|
||||||
// In the typical case, we loop 0 or 1 times.
|
|
||||||
// It was not until issue 24761 that we found any code that required a loop at all.
|
|
||||||
for {
|
|
||||||
for i := numDecls; i < len(typecheck.Target.Funcs); i++ {
|
|
||||||
fn := typecheck.Target.Funcs[i]
|
|
||||||
enqueueFunc(fn)
|
|
||||||
}
|
|
||||||
numDecls = len(typecheck.Target.Funcs)
|
|
||||||
compileFunctions()
|
|
||||||
reflectdata.WriteRuntimeTypes()
|
|
||||||
if numDecls == len(typecheck.Target.Funcs) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dump extra globals.
|
|
||||||
dumpglobls(typecheck.Target.Externs[numExterns:])
|
|
||||||
|
|
||||||
if reflectdata.ZeroSize > 0 {
|
if reflectdata.ZeroSize > 0 {
|
||||||
zero := base.PkgLinksym("go:map", "zero", obj.ABI0)
|
zero := base.PkgLinksym("go:map", "zero", obj.ABI0)
|
||||||
objw.Global(zero, int32(reflectdata.ZeroSize), obj.DUPOK|obj.RODATA)
|
objw.Global(zero, int32(reflectdata.ZeroSize), obj.DUPOK|obj.RODATA)
|
||||||
@ -217,18 +189,6 @@ func dumpGlobalConst(n *ir.Name) {
|
|||||||
base.Ctxt.DwarfIntConst(base.Ctxt.Pkgpath, n.Sym().Name, types.TypeSymName(t), ir.IntVal(t, v))
|
base.Ctxt.DwarfIntConst(base.Ctxt.Pkgpath, n.Sym().Name, types.TypeSymName(t), ir.IntVal(t, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
func dumpglobls(externs []*ir.Name) {
|
|
||||||
// add globals
|
|
||||||
for _, n := range externs {
|
|
||||||
switch n.Op() {
|
|
||||||
case ir.ONAME:
|
|
||||||
dumpGlobal(n)
|
|
||||||
case ir.OLITERAL:
|
|
||||||
dumpGlobalConst(n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// addGCLocals adds gcargs, gclocals, gcregs, and stack object symbols to Ctxt.Data.
|
// addGCLocals adds gcargs, gclocals, gcregs, and stack object symbols to Ctxt.Data.
|
||||||
//
|
//
|
||||||
// This is done during the sequential phase after compilation, since
|
// This is done during the sequential phase after compilation, since
|
||||||
@ -323,12 +283,3 @@ func dumpembeds() {
|
|||||||
staticdata.WriteEmbed(v)
|
staticdata.WriteEmbed(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func addsignats(dcls []*ir.Name) {
|
|
||||||
// copy types from dcl list to signatset
|
|
||||||
for _, n := range dcls {
|
|
||||||
if n.Op() == ir.OTYPE {
|
|
||||||
reflectdata.NeedRuntimeType(n.Type())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1264,7 +1264,9 @@ func WriteRuntimeTypes() {
|
|||||||
}
|
}
|
||||||
signatslice = signatslice[len(signats):]
|
signatslice = signatslice[len(signats):]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteGCSymbols() {
|
||||||
// Emit GC data symbols.
|
// Emit GC data symbols.
|
||||||
gcsyms := make([]typeAndStr, 0, len(gcsymset))
|
gcsyms := make([]typeAndStr, 0, len(gcsymset))
|
||||||
for t := range gcsymset {
|
for t := range gcsymset {
|
||||||
|
Loading…
Reference in New Issue
Block a user