package gc
-import "cmd/compile/internal/types"
+import (
+ "cmd/compile/internal/types"
+)
// A function named init is a special case.
// It is called by the initialization before main is run.
// (6)
for _, s := range types.InitSyms {
if s.Def != nil && s != initsym {
- // could check that it is fn of no args/returns
- a = nod(OCALL, asNode(s.Def), nil)
+ n := asNode(s.Def)
+ n.checkInitFuncSignature()
+ a = nod(OCALL, n, nil)
r = append(r, a)
}
}
r = append(r, nf...)
// (8)
- // could check that it is fn of no args/returns
- for i := 0; i < renameinitgen; i++ {
- s := lookupN("init.", i)
- a = nod(OCALL, asNode(s.Def), nil)
- r = append(r, a)
+
+ // maxInlineInitCalls is the threshold at which we switch
+ // from generating calls inline to generating a static array
+ // of functions and calling them in a loop.
+ // See CL 41500 for more discussion.
+ const maxInlineInitCalls = 500
+
+ if renameinitgen < maxInlineInitCalls {
+ // Not many init functions. Just call them all directly.
+ for i := 0; i < renameinitgen; i++ {
+ s := lookupN("init.", i)
+ n := asNode(s.Def)
+ n.checkInitFuncSignature()
+ a = nod(OCALL, n, nil)
+ r = append(r, a)
+ }
+ } else {
+ // Lots of init functions.
+ // Set up an array of functions and loop to call them.
+ // This is faster to compile and similar at runtime.
+
+ // Build type [renameinitgen]func().
+ typ := types.NewArray(functype(nil, nil, nil), int64(renameinitgen))
+
+ // Make and fill array.
+ fnarr := staticname(typ)
+ fnarr.Name.SetReadonly(true)
+ for i := 0; i < renameinitgen; i++ {
+ s := lookupN("init.", i)
+ lhs := nod(OINDEX, fnarr, nodintconst(int64(i)))
+ rhs := asNode(s.Def)
+ rhs.checkInitFuncSignature()
+ as := nod(OAS, lhs, rhs)
+ as = typecheck(as, Etop)
+ genAsStatic(as)
+ }
+
+ // Generate a loop that calls each function in turn.
+ // for i := 0; i < renameinitgen; i++ {
+ // fnarr[i]()
+ // }
+ i := temp(types.Types[TINT])
+ fnidx := nod(OINDEX, fnarr, i)
+ fnidx.SetBounded(true)
+
+ zero := nod(OAS, i, nodintconst(0))
+ cond := nod(OLT, i, nodintconst(int64(renameinitgen)))
+ incr := nod(OAS, i, nod(OADD, i, nodintconst(1)))
+ body := nod(OCALL, fnidx, nil)
+
+ loop := nod(OFOR, cond, incr)
+ loop.Nbody.Set1(body)
+ loop.Ninit.Set1(zero)
+
+ loop = typecheck(loop, Etop)
+ loop = walkstmt(loop)
+ r = append(r, loop)
}
// (9)
Curfn = nil
funccompile(fn)
}
+
+func (n *Node) checkInitFuncSignature() {
+ ft := n.Type.FuncType()
+ if ft.Receiver.Fields().Len()+ft.Params.Fields().Len()+ft.Results.Fields().Len() > 0 {
+ Fatalf("init function cannot have receiver, params, or results: %v (%v)", n, n.Type)
+ }
+}