mirror of
https://github.com/golang/go
synced 2024-11-23 20:00:04 -07:00
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: David Crawshaw <crawshaw@golang.org>
This commit is contained in:
parent
34f0c0b3de
commit
36d5650a1c
@ -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
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user