]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: move more compiler specifics into compiler specific export section
authorRobert Griesemer <gri@golang.org>
Wed, 13 Apr 2016 01:00:04 +0000 (18:00 -0700)
committerRobert Griesemer <gri@golang.org>
Wed, 13 Apr 2016 17:00:49 +0000 (17:00 +0000)
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 <mdempsky@google.com>
src/cmd/compile/internal/gc/bexport.go
src/cmd/compile/internal/gc/bimport.go
src/go/internal/gcimporter/bimport.go

index cb438d7573f081b2b6dddcf53a44892a547d45b2..e780bcf5777850806f5a324e07d2d12100d46dc7 100644 (file)
@@ -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 {
index 9cebafcaefb40f6e738df14edbc28072a2d0fd9a..2e80b9f81d2ebbced7df570f86868f61d6599387 100644 (file)
@@ -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 {
index a9d678b0216aed1498fc18eefb8256872b47f9c7..81af064b88b4836995ec590f8c02483e84b4091e 100644 (file)
@@ -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))