From 7d0d1222477ce50736ee24adb38c1f487d0801d9 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 12 Apr 2016 18:00:04 -0700 Subject: [PATCH] cmd/compile: move more compiler specifics into compiler specific export section Instead of indicating with each function signature if it has an inlineable body, collect all functions in order and export function bodies with function index in platform-specific section. Moves this compiler specific information out of the platform-independent export data section, and removes an int value for all functions w/o body. Also simplifies the code a bit. Change-Id: I8b2d7299dbe81f2706be49ecfb9d9f7da85fd854 Reviewed-on: https://go-review.googlesource.com/21939 Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/bexport.go | 63 ++++++++------- src/cmd/compile/internal/gc/bimport.go | 104 ++++++++++--------------- src/go/internal/gcimporter/bimport.go | 2 - 3 files changed, 80 insertions(+), 89 deletions(-) diff --git a/src/cmd/compile/internal/gc/bexport.go b/src/cmd/compile/internal/gc/bexport.go index cb438d7573..e780bcf577 100644 --- a/src/cmd/compile/internal/gc/bexport.go +++ b/src/cmd/compile/internal/gc/bexport.go @@ -124,10 +124,11 @@ const exportVersion = "v0" const exportInlined = true // default: true type exporter struct { - out *bufio.Writer - pkgIndex map[*Pkg]int - typIndex map[*Type]int - inlined []*Func + out *bufio.Writer + + pkgIndex map[*Pkg]int // pkg -> pkg index in order of appearance + typIndex map[*Type]int // type -> type index in order of appearance + funcList []*Func // in order of appearance // debugging support written int // bytes written @@ -322,27 +323,39 @@ func export(out *bufio.Writer, trace bool) int { // --- inlined function bodies --- if p.trace { - p.tracef("\n--- inlined function bodies ---\n[ ") + p.tracef("\n--- inlined function bodies ---\n") if p.indent != 0 { Fatalf("exporter: incorrect indentation") } } - // write inlined function bodies - p.int(len(p.inlined)) - if p.trace { - p.tracef("]\n") - } - for _, f := range p.inlined { - if p.trace { - p.tracef("\n----\nfunc { %s }\n", Hconv(f.Inl, FmtSharp)) - } - p.stmtList(f.Inl) - if p.trace { - p.tracef("\n") + // write inlineable function bodies + objcount = 0 + for i, f := range p.funcList { + if f != nil { + // function has inlineable body: + // write index and body + if p.trace { + p.tracef("\n----\nfunc { %s }\n", Hconv(f.Inl, FmtSharp)) + } + p.int(i) + p.stmtList(f.Inl) + if p.trace { + p.tracef("\n") + } + objcount++ } } + // indicate end of list + if p.trace { + p.tracef("\n") + } + p.tag(-1) // invalid index terminates list + + // for self-verification only (redundant) + p.int(objcount) + if p.trace { p.tracef("\n--- end ---\n") } @@ -443,10 +456,9 @@ func (p *exporter) obj(sym *Sym) { p.paramList(sig.Params(), inlineable) p.paramList(sig.Results(), inlineable) - index := -1 + var f *Func if inlineable { - index = len(p.inlined) - p.inlined = append(p.inlined, sym.Def.Func) + f = sym.Def.Func // TODO(gri) re-examine reexportdeplist: // Because we can trivially export types // in-place, we don't need to collect types @@ -454,9 +466,9 @@ func (p *exporter) obj(sym *Sym) { // With an adjusted reexportdeplist used only // by the binary exporter, we can also avoid // the global exportlist. - reexportdeplist(sym.Def.Func.Inl) + reexportdeplist(f.Inl) } - p.int(index) + p.funcList = append(p.funcList, f) } else { // variable p.tag(varTag) @@ -563,13 +575,12 @@ func (p *exporter) typ(t *Type) { p.paramList(sig.Params(), inlineable) p.paramList(sig.Results(), inlineable) - index := -1 + var f *Func if inlineable { - index = len(p.inlined) - p.inlined = append(p.inlined, mfn.Func) + f = mfn.Func reexportdeplist(mfn.Func.Inl) } - p.int(index) + p.funcList = append(p.funcList, f) } if p.trace && len(methods) > 0 { diff --git a/src/cmd/compile/internal/gc/bimport.go b/src/cmd/compile/internal/gc/bimport.go index 9cebafcaef..2e80b9f81d 100644 --- a/src/cmd/compile/internal/gc/bimport.go +++ b/src/cmd/compile/internal/gc/bimport.go @@ -23,9 +23,10 @@ type importer struct { in *bufio.Reader buf []byte // for reading strings bufarray [64]byte // initial underlying array for buf, large enough to avoid allocation when compiling std lib - pkgList []*Pkg - typList []*Type - inlined []*Node // functions with pending inlined function bodies + + pkgList []*Pkg // in order of appearance + typList []*Type // in order of appearance + funcList []*Node // in order of appearance; nil entry means already declared // debugging support debugFormat bool @@ -107,21 +108,35 @@ func Import(in *bufio.Reader) { Fatalf("importer: got %d objects; want %d", objcount, count) } - // read inlined functions bodies + // read inlineable functions bodies if dclcontext != PEXTERN { Fatalf("importer: unexpected context %d", dclcontext) } - bcount := p.int() // consistency check only - if bcount != len(p.inlined) { - Fatalf("importer: expected %d inlined function bodies; got %d", bcount, len(p.inlined)) - } - for _, f := range p.inlined { + objcount = 0 + for i0 := -1; ; { + i := p.int() // index of function with inlineable body + if i < 0 { + break + } + + // don't process the same function twice + if i <= i0 { + Fatalf("importer: index not increasing: %d <= %d", i, i0) + } + i0 = i + if Funcdepth != 0 { Fatalf("importer: unexpected Funcdepth %d", Funcdepth) } - if f != nil { - // function body not yet imported - read body and set it + + // Note: In the original code, funchdr and funcbody are called for + // all functions (that were not yet imported). Now, we are calling + // them only for functions with inlineable bodies. funchdr does + // parameter renaming which doesn't matter if we don't have a body. + + if f := p.funcList[i]; f != nil { + // function not yet imported - read body and set it funchdr(f) f.Func.Inl.Set(p.stmtList()) funcbody(f) @@ -131,6 +146,13 @@ func Import(in *bufio.Reader) { p.stmtList() dclcontext = PEXTERN } + + objcount++ + } + + // self-verification + if count := p.int(); count != objcount { + Fatalf("importer: got %d functions; want %d", objcount, count) } if dclcontext != PEXTERN { @@ -214,47 +236,23 @@ func (p *importer) obj(tag int) { sym := p.qualifiedName() params := p.paramList() result := p.paramList() - inl := p.int() sig := functype(nil, params, result) importsym(sym, ONAME) if sym.Def != nil && sym.Def.Op == ONAME { - if Eqtype(sig, sym.Def.Type) { - // function was imported before (via another import) - dclcontext = PDISCARD // since we skip funchdr below - } else { + // function was imported before (via another import) + if !Eqtype(sig, sym.Def.Type) { Fatalf("importer: inconsistent definition for func %v during import\n\t%v\n\t%v", sym, sym.Def.Type, sig) } - } - - var n *Node - if dclcontext != PDISCARD { - n = newfuncname(sym) - n.Type = sig - declare(n, PFUNC) - if inl < 0 { - funchdr(n) - } - } - - if inl >= 0 { - // function has inlined body - collect for later - if inl != len(p.inlined) { - Fatalf("importer: inlined index = %d; want %d", inl, len(p.inlined)) - } - p.inlined = append(p.inlined, n) - } - - // parser.go:hidden_import - if dclcontext == PDISCARD { - dclcontext = PEXTERN // since we skip the funcbody below + p.funcList = append(p.funcList, nil) break } - if inl < 0 { - funcbody(n) - } - importlist = append(importlist, n) // TODO(gri) may only be needed for inlineable functions + n := newfuncname(sym) + n.Type = sig + declare(n, PFUNC) + p.funcList = append(p.funcList, n) + importlist = append(importlist, n) if Debug['E'] > 0 { fmt.Printf("import [%q] func %v \n", importpkg.Path, n) @@ -316,23 +314,13 @@ func (p *importer) typ() *Type { recv := p.paramList() // TODO(gri) do we need a full param list for the receiver? params := p.paramList() result := p.paramList() - inl := p.int() n := methodname1(newname(sym), recv[0].Right) n.Type = functype(recv[0], params, result) checkwidth(n.Type) addmethod(sym, n.Type, tsym.Pkg, false, false) - if inl < 0 { - funchdr(n) - } - - if inl >= 0 { - // method has inlined body - collect for later - if inl != len(p.inlined) { - Fatalf("importer: inlined index = %d; want %d", inl, len(p.inlined)) - } - p.inlined = append(p.inlined, n) - } + p.funcList = append(p.funcList, n) + importlist = append(importlist, n) // (comment from parser.go) // inl.C's inlnode in on a dotmeth node expects to find the inlineable body as @@ -341,12 +329,6 @@ func (p *importer) typ() *Type { // this back link here we avoid special casing there. n.Type.SetNname(n) - // parser.go:hidden_import - if inl < 0 { - funcbody(n) - } - importlist = append(importlist, n) // TODO(gri) may only be needed for inlineable functions - if Debug['E'] > 0 { fmt.Printf("import [%q] meth %v \n", importpkg.Path, n) if Debug['m'] > 2 && len(n.Func.Inl.Slice()) != 0 { diff --git a/src/go/internal/gcimporter/bimport.go b/src/go/internal/gcimporter/bimport.go index a9d678b021..81af064b88 100644 --- a/src/go/internal/gcimporter/bimport.go +++ b/src/go/internal/gcimporter/bimport.go @@ -186,7 +186,6 @@ func (p *importer) obj(tag int) { params, isddd := p.paramList() result, _ := p.paramList() sig := types.NewSignature(nil, params, result, isddd) - p.int() // read and discard index of inlined function body p.declare(types.NewFunc(token.NoPos, pkg, name, sig)) default: @@ -269,7 +268,6 @@ func (p *importer) typ(parent *types.Package) types.Type { recv, _ := p.paramList() // TODO(gri) do we need a full param list for the receiver? params, isddd := p.paramList() result, _ := p.paramList() - p.int() // read and discard index of inlined function body sig := types.NewSignature(recv.At(0), params, result, isddd) t0.AddMethod(types.NewFunc(token.NoPos, parent, name, sig)) -- 2.48.1