mirror of
https://github.com/golang/go
synced 2024-11-17 20:04:47 -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
|
||||
// and waits for them to complete.
|
||||
func compileFunctions() {
|
||||
if len(compilequeue) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if race.Enabled {
|
||||
// Randomize compilation order to try to shake out races.
|
||||
tmp := make([]*ir.Func, len(compilequeue))
|
||||
|
@ -298,18 +298,47 @@ func Main(archInit func(*ssagen.ArchInfo)) {
|
||||
|
||||
ir.CurFunc = nil
|
||||
|
||||
// Compile top level functions.
|
||||
// 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")
|
||||
reflectdata.WriteBasicTypes()
|
||||
|
||||
// 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()
|
||||
continue
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
base.Timer.AddEvent(int64(len(typecheck.Target.Funcs)), "funcs")
|
||||
|
||||
if base.Flag.CompilingRuntime {
|
||||
// Write barriers are now known. Check the call graph.
|
||||
|
@ -110,39 +110,11 @@ func dumpCompilerObj(bout *bio.Writer) {
|
||||
}
|
||||
|
||||
func dumpdata() {
|
||||
numExterns := len(typecheck.Target.Externs)
|
||||
numDecls := len(typecheck.Target.Funcs)
|
||||
dumpglobls(typecheck.Target.Externs)
|
||||
addsignats(typecheck.Target.Externs)
|
||||
reflectdata.WriteRuntimeTypes()
|
||||
reflectdata.WriteGCSymbols()
|
||||
reflectdata.WritePluginTable()
|
||||
reflectdata.WriteImportStrings()
|
||||
reflectdata.WriteBasicTypes()
|
||||
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 {
|
||||
zero := base.PkgLinksym("go:map", "zero", obj.ABI0)
|
||||
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))
|
||||
}
|
||||
|
||||
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.
|
||||
//
|
||||
// This is done during the sequential phase after compilation, since
|
||||
@ -323,12 +283,3 @@ func dumpembeds() {
|
||||
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):]
|
||||
}
|
||||
}
|
||||
|
||||
func WriteGCSymbols() {
|
||||
// Emit GC data symbols.
|
||||
gcsyms := make([]typeAndStr, 0, len(gcsymset))
|
||||
for t := range gcsymset {
|
||||
|
Loading…
Reference in New Issue
Block a user