Commit 36d5650a authored by Michael Hudson-Doyle's avatar Michael Hudson-Doyle

cmd/internal/obj, cmd/link: put all symbol data in one contiguous section

Another object file change, gives a reasonable improvement:

name       old s/op   new s/op   delta
LinkCmdGo  0.46 ± 3%  0.44 ± 9%  -3.34%  (p=0.000 n=98+82)
LinkJuju   4.09 ± 4%  3.92 ± 5%  -4.30%  (p=0.000 n=98+99)

I guess the data section could be mmap-ed instead of read, I haven't tried
that.

Change-Id: I959eee470a05526ab1579e3f5d3ede41c16c954f
Reviewed-on: https://go-review.googlesource.com/20928
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarDavid Crawshaw <crawshaw@golang.org>
parent 34f0c0b3
......@@ -236,15 +236,16 @@ var (
// An objReader is an object file reader.
type objReader struct {
p *Package
b *bufio.Reader
f io.ReadSeeker
err error
offset int64
limit int64
tmp [256]byte
pkg string
pkgprefix string
p *Package
b *bufio.Reader
f io.ReadSeeker
err error
offset int64
dataOffset int64
limit int64
tmp [256]byte
pkg string
pkgprefix string
}
// importPathToPrefix returns the prefix that will be used in the
......@@ -416,8 +417,8 @@ func (r *objReader) readRef() {
// readData reads a data reference from the input file.
func (r *objReader) readData() Data {
n := r.readInt()
d := Data{Offset: r.offset, Size: int64(n)}
r.skip(int64(n))
d := Data{Offset: r.dataOffset, Size: int64(n)}
r.dataOffset += int64(n)
return d
}
......@@ -610,6 +611,10 @@ func (r *objReader) parseObject(prefix []byte) error {
r.readRef()
}
dataLength := r.readInt()
r.dataOffset = r.offset
r.skip(int64(dataLength))
// Symbols.
for {
if b := r.readByte(); b != 0xfe {
......
......@@ -19,8 +19,10 @@
// - byte 1 - version number
// - sequence of strings giving dependencies (imported packages)
// - empty string (marks end of sequence)
// - sequence of sybol references used by the defined symbols
// - sequence of symbol references used by the defined symbols
// - byte 0xff (marks end of sequence)
// - integer (length of following data)
// - data, the content of the defined symbols
// - sequence of defined symbols
// - byte 0xff (marks end of sequence)
// - magic footer: "\xff\xffgo13ld"
......@@ -96,9 +98,6 @@
//
// TODO(rsc): The file format is good for a first pass but needs work.
// - There are SymID in the object file that should really just be strings.
// - The actual symbol memory images are interlaced with the symbol
// metadata. They should be separated, to reduce the I/O required to
// load just the metadata.
package obj
......@@ -319,15 +318,42 @@ func Writeobjfile(ctxt *Link, b *Biobuf) {
}
wrstring(b, "")
var dataLength int64
// Emit symbol references.
for _, s := range ctxt.Text {
writerefs(ctxt, b, s)
dataLength += int64(len(s.P))
pc := s.Pcln
dataLength += int64(len(pc.Pcsp.P))
dataLength += int64(len(pc.Pcfile.P))
dataLength += int64(len(pc.Pcline.P))
for i := 0; i < len(pc.Pcdata); i++ {
dataLength += int64(len(pc.Pcdata[i].P))
}
}
for _, s := range ctxt.Data {
writerefs(ctxt, b, s)
dataLength += int64(len(s.P))
}
Bputc(b, 0xff)
// Write data block
wrint(b, dataLength)
for _, s := range ctxt.Text {
b.w.Write(s.P)
pc := s.Pcln
b.w.Write(pc.Pcsp.P)
b.w.Write(pc.Pcfile.P)
b.w.Write(pc.Pcline.P)
for i := 0; i < len(pc.Pcdata); i++ {
b.w.Write(pc.Pcdata[i].P)
}
}
for _, s := range ctxt.Data {
b.w.Write(s.P)
}
// Emit symbols.
for _, s := range ctxt.Text {
writesym(ctxt, b, s)
......@@ -480,7 +506,7 @@ func writesym(ctxt *Link, b *Biobuf, s *LSym) {
wrint(b, flags)
wrint(b, s.Size)
wrsym(b, s.Gotype)
wrdata(b, s.P)
wrint(b, int64(len(s.P)))
wrint(b, int64(len(s.R)))
var r *Reloc
......@@ -521,12 +547,12 @@ func writesym(ctxt *Link, b *Biobuf, s *LSym) {
}
pc := s.Pcln
wrdata(b, pc.Pcsp.P)
wrdata(b, pc.Pcfile.P)
wrdata(b, pc.Pcline.P)
wrint(b, int64(len(pc.Pcsp.P)))
wrint(b, int64(len(pc.Pcfile.P)))
wrint(b, int64(len(pc.Pcline.P)))
wrint(b, int64(len(pc.Pcdata)))
for i := 0; i < len(pc.Pcdata); i++ {
wrdata(b, pc.Pcdata[i].P)
wrint(b, int64(len(pc.Pcdata[i].P)))
}
wrint(b, int64(len(pc.Funcdataoff)))
for i := 0; i < len(pc.Funcdataoff); i++ {
......@@ -564,11 +590,6 @@ func wrstring(b *Biobuf, s string) {
b.w.WriteString(s)
}
func wrdata(b *Biobuf, v []byte) {
wrint(b, int64(len(v)))
b.Write(v)
}
func wrsym(b *Biobuf, s *LSym) {
if s == nil {
wrint(b, 0)
......
......@@ -23,6 +23,8 @@ package ld
// - empty string (marks end of sequence)
// - sequence of sybol references used by the defined symbols
// - byte 0xff (marks end of sequence)
// - integer (length of following data)
// - data, the content of the defined symbols
// - sequence of defined symbols
// - byte 0xff (marks end of sequence)
// - magic footer: "\xff\xffgo13ld"
......@@ -98,9 +100,6 @@ package ld
//
// TODO(rsc): The file format is good for a first pass but needs work.
// - There are SymID in the object file that should really just be strings.
// - The actual symbol memory images are interlaced with the symbol
// metadata. They should be separated, to reduce the I/O required to
// load just the metadata.
import (
"bytes"
......@@ -151,6 +150,10 @@ func ldobjfile(ctxt *Link, f *obj.Biobuf, pkg string, length int64, pn string) {
readref(ctxt, f, pkg, pn)
}
dataLength := rdint64(f)
data := make([]byte, dataLength)
obj.Bread(f, data)
for {
c, err := f.Peek(1)
if err != nil {
......@@ -159,7 +162,7 @@ func ldobjfile(ctxt *Link, f *obj.Biobuf, pkg string, length int64, pn string) {
if c[0] == 0xff {
break
}
readsym(ctxt, f, pkg, pn)
readsym(ctxt, f, &data, pkg, pn)
}
buf = [8]uint8{}
......@@ -173,7 +176,7 @@ func ldobjfile(ctxt *Link, f *obj.Biobuf, pkg string, length int64, pn string) {
}
}
func readsym(ctxt *Link, f *obj.Biobuf, pkg string, pn string) {
func readsym(ctxt *Link, f *obj.Biobuf, buf *[]byte, pkg string, pn string) {
if obj.Bgetc(f) != 0xfe {
log.Fatalf("readsym out of sync")
}
......@@ -184,7 +187,7 @@ func readsym(ctxt *Link, f *obj.Biobuf, pkg string, pn string) {
local := flags&2 != 0
size := rdint(f)
typ := rdsym(ctxt, f, pkg)
data := rddata(f)
data := rddata(f, buf)
nreloc := rdint(f)
var dup *LSym
......@@ -283,14 +286,14 @@ overwrite:
s.Pcln = new(Pcln)
pc := s.Pcln
pc.Pcsp.P = rddata(f)
pc.Pcfile.P = rddata(f)
pc.Pcline.P = rddata(f)
pc.Pcsp.P = rddata(f, buf)
pc.Pcfile.P = rddata(f, buf)
pc.Pcline.P = rddata(f, buf)
n = rdint(f)
pc.Pcdata = make([]Pcdata, n)
pc.Npcdata = n
for i := 0; i < n; i++ {
pc.Pcdata[i].P = rddata(f)
pc.Pcdata[i].P = rddata(f, buf)
}
n = rdint(f)
pc.Funcdata = make([]*LSym, n)
......@@ -482,23 +485,10 @@ func rdstring(f *obj.Biobuf) string {
return string(rdBuf[:n])
}
const rddataBufMax = 1 << 14
var rddataBuf = make([]byte, rddataBufMax)
func rddata(f *obj.Biobuf) []byte {
var p []byte
func rddata(f *obj.Biobuf, buf *[]byte) []byte {
n := rdint(f)
if n > rddataBufMax {
p = make([]byte, n)
} else {
if len(rddataBuf) < n {
rddataBuf = make([]byte, rddataBufMax)
}
p = rddataBuf[:n:n]
rddataBuf = rddataBuf[n:]
}
obj.Bread(f, p)
p := (*buf)[:n:n]
*buf = (*buf)[n:]
return p
}
......
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