Commit 7d0d1222 authored by Robert Griesemer's avatar Robert Griesemer

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/21939Reviewed-by: 's avatarMatthew Dempsky <mdempsky@google.com>
parent d8e8fc29
...@@ -124,10 +124,11 @@ const exportVersion = "v0" ...@@ -124,10 +124,11 @@ const exportVersion = "v0"
const exportInlined = true // default: true const exportInlined = true // default: true
type exporter struct { type exporter struct {
out *bufio.Writer out *bufio.Writer
pkgIndex map[*Pkg]int
typIndex map[*Type]int pkgIndex map[*Pkg]int // pkg -> pkg index in order of appearance
inlined []*Func typIndex map[*Type]int // type -> type index in order of appearance
funcList []*Func // in order of appearance
// debugging support // debugging support
written int // bytes written written int // bytes written
...@@ -322,27 +323,39 @@ func export(out *bufio.Writer, trace bool) int { ...@@ -322,27 +323,39 @@ func export(out *bufio.Writer, trace bool) int {
// --- inlined function bodies --- // --- inlined function bodies ---
if p.trace { if p.trace {
p.tracef("\n--- inlined function bodies ---\n[ ") p.tracef("\n--- inlined function bodies ---\n")
if p.indent != 0 { if p.indent != 0 {
Fatalf("exporter: incorrect indentation") Fatalf("exporter: incorrect indentation")
} }
} }
// write inlined function bodies // write inlineable function bodies
p.int(len(p.inlined)) objcount = 0
if p.trace { for i, f := range p.funcList {
p.tracef("]\n") if f != nil {
} // function has inlineable body:
for _, f := range p.inlined { // write index and body
if p.trace { if p.trace {
p.tracef("\n----\nfunc { %s }\n", Hconv(f.Inl, FmtSharp)) p.tracef("\n----\nfunc { %s }\n", Hconv(f.Inl, FmtSharp))
} }
p.stmtList(f.Inl) p.int(i)
if p.trace { p.stmtList(f.Inl)
p.tracef("\n") 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 { if p.trace {
p.tracef("\n--- end ---\n") p.tracef("\n--- end ---\n")
} }
...@@ -443,10 +456,9 @@ func (p *exporter) obj(sym *Sym) { ...@@ -443,10 +456,9 @@ func (p *exporter) obj(sym *Sym) {
p.paramList(sig.Params(), inlineable) p.paramList(sig.Params(), inlineable)
p.paramList(sig.Results(), inlineable) p.paramList(sig.Results(), inlineable)
index := -1 var f *Func
if inlineable { if inlineable {
index = len(p.inlined) f = sym.Def.Func
p.inlined = append(p.inlined, sym.Def.Func)
// TODO(gri) re-examine reexportdeplist: // TODO(gri) re-examine reexportdeplist:
// Because we can trivially export types // Because we can trivially export types
// in-place, we don't need to collect types // in-place, we don't need to collect types
...@@ -454,9 +466,9 @@ func (p *exporter) obj(sym *Sym) { ...@@ -454,9 +466,9 @@ func (p *exporter) obj(sym *Sym) {
// With an adjusted reexportdeplist used only // With an adjusted reexportdeplist used only
// by the binary exporter, we can also avoid // by the binary exporter, we can also avoid
// the global exportlist. // the global exportlist.
reexportdeplist(sym.Def.Func.Inl) reexportdeplist(f.Inl)
} }
p.int(index) p.funcList = append(p.funcList, f)
} else { } else {
// variable // variable
p.tag(varTag) p.tag(varTag)
...@@ -563,13 +575,12 @@ func (p *exporter) typ(t *Type) { ...@@ -563,13 +575,12 @@ func (p *exporter) typ(t *Type) {
p.paramList(sig.Params(), inlineable) p.paramList(sig.Params(), inlineable)
p.paramList(sig.Results(), inlineable) p.paramList(sig.Results(), inlineable)
index := -1 var f *Func
if inlineable { if inlineable {
index = len(p.inlined) f = mfn.Func
p.inlined = append(p.inlined, mfn.Func)
reexportdeplist(mfn.Func.Inl) reexportdeplist(mfn.Func.Inl)
} }
p.int(index) p.funcList = append(p.funcList, f)
} }
if p.trace && len(methods) > 0 { if p.trace && len(methods) > 0 {
......
...@@ -23,9 +23,10 @@ type importer struct { ...@@ -23,9 +23,10 @@ type importer struct {
in *bufio.Reader in *bufio.Reader
buf []byte // for reading strings buf []byte // for reading strings
bufarray [64]byte // initial underlying array for buf, large enough to avoid allocation when compiling std lib bufarray [64]byte // initial underlying array for buf, large enough to avoid allocation when compiling std lib
pkgList []*Pkg
typList []*Type pkgList []*Pkg // in order of appearance
inlined []*Node // functions with pending inlined function bodies typList []*Type // in order of appearance
funcList []*Node // in order of appearance; nil entry means already declared
// debugging support // debugging support
debugFormat bool debugFormat bool
...@@ -107,21 +108,35 @@ func Import(in *bufio.Reader) { ...@@ -107,21 +108,35 @@ func Import(in *bufio.Reader) {
Fatalf("importer: got %d objects; want %d", objcount, count) Fatalf("importer: got %d objects; want %d", objcount, count)
} }
// read inlined functions bodies // read inlineable functions bodies
if dclcontext != PEXTERN { if dclcontext != PEXTERN {
Fatalf("importer: unexpected context %d", dclcontext) Fatalf("importer: unexpected context %d", dclcontext)
} }
bcount := p.int() // consistency check only objcount = 0
if bcount != len(p.inlined) { for i0 := -1; ; {
Fatalf("importer: expected %d inlined function bodies; got %d", bcount, len(p.inlined)) i := p.int() // index of function with inlineable body
} if i < 0 {
for _, f := range p.inlined { 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 { if Funcdepth != 0 {
Fatalf("importer: unexpected Funcdepth %d", Funcdepth) 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) funchdr(f)
f.Func.Inl.Set(p.stmtList()) f.Func.Inl.Set(p.stmtList())
funcbody(f) funcbody(f)
...@@ -131,6 +146,13 @@ func Import(in *bufio.Reader) { ...@@ -131,6 +146,13 @@ func Import(in *bufio.Reader) {
p.stmtList() p.stmtList()
dclcontext = PEXTERN dclcontext = PEXTERN
} }
objcount++
}
// self-verification
if count := p.int(); count != objcount {
Fatalf("importer: got %d functions; want %d", objcount, count)
} }
if dclcontext != PEXTERN { if dclcontext != PEXTERN {
...@@ -214,47 +236,23 @@ func (p *importer) obj(tag int) { ...@@ -214,47 +236,23 @@ func (p *importer) obj(tag int) {
sym := p.qualifiedName() sym := p.qualifiedName()
params := p.paramList() params := p.paramList()
result := p.paramList() result := p.paramList()
inl := p.int()
sig := functype(nil, params, result) sig := functype(nil, params, result)
importsym(sym, ONAME) importsym(sym, ONAME)
if sym.Def != nil && sym.Def.Op == ONAME { if sym.Def != nil && sym.Def.Op == ONAME {
if Eqtype(sig, sym.Def.Type) { // function was imported before (via another import)
// function was imported before (via another import) if !Eqtype(sig, sym.Def.Type) {
dclcontext = PDISCARD // since we skip funchdr below
} else {
Fatalf("importer: inconsistent definition for func %v during import\n\t%v\n\t%v", sym, sym.Def.Type, sig) Fatalf("importer: inconsistent definition for func %v during import\n\t%v\n\t%v", sym, sym.Def.Type, sig)
} }
} p.funcList = append(p.funcList, nil)
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
break break
} }
if inl < 0 { n := newfuncname(sym)
funcbody(n) n.Type = sig
} declare(n, PFUNC)
importlist = append(importlist, n) // TODO(gri) may only be needed for inlineable functions p.funcList = append(p.funcList, n)
importlist = append(importlist, n)
if Debug['E'] > 0 { if Debug['E'] > 0 {
fmt.Printf("import [%q] func %v \n", importpkg.Path, n) fmt.Printf("import [%q] func %v \n", importpkg.Path, n)
...@@ -316,23 +314,13 @@ func (p *importer) typ() *Type { ...@@ -316,23 +314,13 @@ func (p *importer) typ() *Type {
recv := p.paramList() // TODO(gri) do we need a full param list for the receiver? recv := p.paramList() // TODO(gri) do we need a full param list for the receiver?
params := p.paramList() params := p.paramList()
result := p.paramList() result := p.paramList()
inl := p.int()
n := methodname1(newname(sym), recv[0].Right) n := methodname1(newname(sym), recv[0].Right)
n.Type = functype(recv[0], params, result) n.Type = functype(recv[0], params, result)
checkwidth(n.Type) checkwidth(n.Type)
addmethod(sym, n.Type, tsym.Pkg, false, false) addmethod(sym, n.Type, tsym.Pkg, false, false)
if inl < 0 { p.funcList = append(p.funcList, n)
funchdr(n) importlist = append(importlist, 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)
}
// (comment from parser.go) // (comment from parser.go)
// inl.C's inlnode in on a dotmeth node expects to find the inlineable body as // 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 { ...@@ -341,12 +329,6 @@ func (p *importer) typ() *Type {
// this back link here we avoid special casing there. // this back link here we avoid special casing there.
n.Type.SetNname(n) 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 { if Debug['E'] > 0 {
fmt.Printf("import [%q] meth %v \n", importpkg.Path, n) fmt.Printf("import [%q] meth %v \n", importpkg.Path, n)
if Debug['m'] > 2 && len(n.Func.Inl.Slice()) != 0 { if Debug['m'] > 2 && len(n.Func.Inl.Slice()) != 0 {
......
...@@ -186,7 +186,6 @@ func (p *importer) obj(tag int) { ...@@ -186,7 +186,6 @@ func (p *importer) obj(tag int) {
params, isddd := p.paramList() params, isddd := p.paramList()
result, _ := p.paramList() result, _ := p.paramList()
sig := types.NewSignature(nil, params, result, isddd) 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)) p.declare(types.NewFunc(token.NoPos, pkg, name, sig))
default: default:
...@@ -269,7 +268,6 @@ func (p *importer) typ(parent *types.Package) types.Type { ...@@ -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? recv, _ := p.paramList() // TODO(gri) do we need a full param list for the receiver?
params, isddd := p.paramList() params, isddd := p.paramList()
result, _ := p.paramList() result, _ := p.paramList()
p.int() // read and discard index of inlined function body
sig := types.NewSignature(recv.At(0), params, result, isddd) sig := types.NewSignature(recv.At(0), params, result, isddd)
t0.AddMethod(types.NewFunc(token.NoPos, parent, name, sig)) t0.AddMethod(types.NewFunc(token.NoPos, parent, name, sig))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment