mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00: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
3 changed files with 67 additions and 51 deletions
|
|
@ -236,15 +236,16 @@ var (
|
||||||
|
|
||||||
// An objReader is an object file reader.
|
// An objReader is an object file reader.
|
||||||
type objReader struct {
|
type objReader struct {
|
||||||
p *Package
|
p *Package
|
||||||
b *bufio.Reader
|
b *bufio.Reader
|
||||||
f io.ReadSeeker
|
f io.ReadSeeker
|
||||||
err error
|
err error
|
||||||
offset int64
|
offset int64
|
||||||
limit int64
|
dataOffset int64
|
||||||
tmp [256]byte
|
limit int64
|
||||||
pkg string
|
tmp [256]byte
|
||||||
pkgprefix string
|
pkg string
|
||||||
|
pkgprefix string
|
||||||
}
|
}
|
||||||
|
|
||||||
// importPathToPrefix returns the prefix that will be used in the
|
// 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.
|
// readData reads a data reference from the input file.
|
||||||
func (r *objReader) readData() Data {
|
func (r *objReader) readData() Data {
|
||||||
n := r.readInt()
|
n := r.readInt()
|
||||||
d := Data{Offset: r.offset, Size: int64(n)}
|
d := Data{Offset: r.dataOffset, Size: int64(n)}
|
||||||
r.skip(int64(n))
|
r.dataOffset += int64(n)
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -610,6 +611,10 @@ func (r *objReader) parseObject(prefix []byte) error {
|
||||||
r.readRef()
|
r.readRef()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dataLength := r.readInt()
|
||||||
|
r.dataOffset = r.offset
|
||||||
|
r.skip(int64(dataLength))
|
||||||
|
|
||||||
// Symbols.
|
// Symbols.
|
||||||
for {
|
for {
|
||||||
if b := r.readByte(); b != 0xfe {
|
if b := r.readByte(); b != 0xfe {
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,10 @@
|
||||||
// - byte 1 - version number
|
// - byte 1 - version number
|
||||||
// - sequence of strings giving dependencies (imported packages)
|
// - sequence of strings giving dependencies (imported packages)
|
||||||
// - empty string (marks end of sequence)
|
// - 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)
|
// - byte 0xff (marks end of sequence)
|
||||||
|
// - integer (length of following data)
|
||||||
|
// - data, the content of the defined symbols
|
||||||
// - sequence of defined symbols
|
// - sequence of defined symbols
|
||||||
// - byte 0xff (marks end of sequence)
|
// - byte 0xff (marks end of sequence)
|
||||||
// - magic footer: "\xff\xffgo13ld"
|
// - magic footer: "\xff\xffgo13ld"
|
||||||
|
|
@ -96,9 +98,6 @@
|
||||||
//
|
//
|
||||||
// TODO(rsc): The file format is good for a first pass but needs work.
|
// 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.
|
// - 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
|
package obj
|
||||||
|
|
||||||
|
|
@ -319,15 +318,42 @@ func Writeobjfile(ctxt *Link, b *Biobuf) {
|
||||||
}
|
}
|
||||||
wrstring(b, "")
|
wrstring(b, "")
|
||||||
|
|
||||||
|
var dataLength int64
|
||||||
// Emit symbol references.
|
// Emit symbol references.
|
||||||
for _, s := range ctxt.Text {
|
for _, s := range ctxt.Text {
|
||||||
writerefs(ctxt, b, s)
|
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 {
|
for _, s := range ctxt.Data {
|
||||||
writerefs(ctxt, b, s)
|
writerefs(ctxt, b, s)
|
||||||
|
dataLength += int64(len(s.P))
|
||||||
}
|
}
|
||||||
Bputc(b, 0xff)
|
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.
|
// Emit symbols.
|
||||||
for _, s := range ctxt.Text {
|
for _, s := range ctxt.Text {
|
||||||
writesym(ctxt, b, s)
|
writesym(ctxt, b, s)
|
||||||
|
|
@ -480,7 +506,7 @@ func writesym(ctxt *Link, b *Biobuf, s *LSym) {
|
||||||
wrint(b, flags)
|
wrint(b, flags)
|
||||||
wrint(b, s.Size)
|
wrint(b, s.Size)
|
||||||
wrsym(b, s.Gotype)
|
wrsym(b, s.Gotype)
|
||||||
wrdata(b, s.P)
|
wrint(b, int64(len(s.P)))
|
||||||
|
|
||||||
wrint(b, int64(len(s.R)))
|
wrint(b, int64(len(s.R)))
|
||||||
var r *Reloc
|
var r *Reloc
|
||||||
|
|
@ -521,12 +547,12 @@ func writesym(ctxt *Link, b *Biobuf, s *LSym) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pc := s.Pcln
|
pc := s.Pcln
|
||||||
wrdata(b, pc.Pcsp.P)
|
wrint(b, int64(len(pc.Pcsp.P)))
|
||||||
wrdata(b, pc.Pcfile.P)
|
wrint(b, int64(len(pc.Pcfile.P)))
|
||||||
wrdata(b, pc.Pcline.P)
|
wrint(b, int64(len(pc.Pcline.P)))
|
||||||
wrint(b, int64(len(pc.Pcdata)))
|
wrint(b, int64(len(pc.Pcdata)))
|
||||||
for i := 0; i < len(pc.Pcdata); i++ {
|
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)))
|
wrint(b, int64(len(pc.Funcdataoff)))
|
||||||
for i := 0; i < len(pc.Funcdataoff); i++ {
|
for i := 0; i < len(pc.Funcdataoff); i++ {
|
||||||
|
|
@ -564,11 +590,6 @@ func wrstring(b *Biobuf, s string) {
|
||||||
b.w.WriteString(s)
|
b.w.WriteString(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func wrdata(b *Biobuf, v []byte) {
|
|
||||||
wrint(b, int64(len(v)))
|
|
||||||
b.Write(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func wrsym(b *Biobuf, s *LSym) {
|
func wrsym(b *Biobuf, s *LSym) {
|
||||||
if s == nil {
|
if s == nil {
|
||||||
wrint(b, 0)
|
wrint(b, 0)
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@ package ld
|
||||||
// - empty string (marks end of sequence)
|
// - empty string (marks end of sequence)
|
||||||
// - sequence of sybol references used by the defined symbols
|
// - sequence of sybol references used by the defined symbols
|
||||||
// - byte 0xff (marks end of sequence)
|
// - byte 0xff (marks end of sequence)
|
||||||
|
// - integer (length of following data)
|
||||||
|
// - data, the content of the defined symbols
|
||||||
// - sequence of defined symbols
|
// - sequence of defined symbols
|
||||||
// - byte 0xff (marks end of sequence)
|
// - byte 0xff (marks end of sequence)
|
||||||
// - magic footer: "\xff\xffgo13ld"
|
// - magic footer: "\xff\xffgo13ld"
|
||||||
|
|
@ -98,9 +100,6 @@ package ld
|
||||||
//
|
//
|
||||||
// TODO(rsc): The file format is good for a first pass but needs work.
|
// 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.
|
// - 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 (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
@ -151,6 +150,10 @@ func ldobjfile(ctxt *Link, f *obj.Biobuf, pkg string, length int64, pn string) {
|
||||||
readref(ctxt, f, pkg, pn)
|
readref(ctxt, f, pkg, pn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dataLength := rdint64(f)
|
||||||
|
data := make([]byte, dataLength)
|
||||||
|
obj.Bread(f, data)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
c, err := f.Peek(1)
|
c, err := f.Peek(1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -159,7 +162,7 @@ func ldobjfile(ctxt *Link, f *obj.Biobuf, pkg string, length int64, pn string) {
|
||||||
if c[0] == 0xff {
|
if c[0] == 0xff {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
readsym(ctxt, f, pkg, pn)
|
readsym(ctxt, f, &data, pkg, pn)
|
||||||
}
|
}
|
||||||
|
|
||||||
buf = [8]uint8{}
|
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 {
|
if obj.Bgetc(f) != 0xfe {
|
||||||
log.Fatalf("readsym out of sync")
|
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
|
local := flags&2 != 0
|
||||||
size := rdint(f)
|
size := rdint(f)
|
||||||
typ := rdsym(ctxt, f, pkg)
|
typ := rdsym(ctxt, f, pkg)
|
||||||
data := rddata(f)
|
data := rddata(f, buf)
|
||||||
nreloc := rdint(f)
|
nreloc := rdint(f)
|
||||||
|
|
||||||
var dup *LSym
|
var dup *LSym
|
||||||
|
|
@ -283,14 +286,14 @@ overwrite:
|
||||||
|
|
||||||
s.Pcln = new(Pcln)
|
s.Pcln = new(Pcln)
|
||||||
pc := s.Pcln
|
pc := s.Pcln
|
||||||
pc.Pcsp.P = rddata(f)
|
pc.Pcsp.P = rddata(f, buf)
|
||||||
pc.Pcfile.P = rddata(f)
|
pc.Pcfile.P = rddata(f, buf)
|
||||||
pc.Pcline.P = rddata(f)
|
pc.Pcline.P = rddata(f, buf)
|
||||||
n = rdint(f)
|
n = rdint(f)
|
||||||
pc.Pcdata = make([]Pcdata, n)
|
pc.Pcdata = make([]Pcdata, n)
|
||||||
pc.Npcdata = n
|
pc.Npcdata = n
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
pc.Pcdata[i].P = rddata(f)
|
pc.Pcdata[i].P = rddata(f, buf)
|
||||||
}
|
}
|
||||||
n = rdint(f)
|
n = rdint(f)
|
||||||
pc.Funcdata = make([]*LSym, n)
|
pc.Funcdata = make([]*LSym, n)
|
||||||
|
|
@ -482,23 +485,10 @@ func rdstring(f *obj.Biobuf) string {
|
||||||
return string(rdBuf[:n])
|
return string(rdBuf[:n])
|
||||||
}
|
}
|
||||||
|
|
||||||
const rddataBufMax = 1 << 14
|
func rddata(f *obj.Biobuf, buf *[]byte) []byte {
|
||||||
|
|
||||||
var rddataBuf = make([]byte, rddataBufMax)
|
|
||||||
|
|
||||||
func rddata(f *obj.Biobuf) []byte {
|
|
||||||
var p []byte
|
|
||||||
n := rdint(f)
|
n := rdint(f)
|
||||||
if n > rddataBufMax {
|
p := (*buf)[:n:n]
|
||||||
p = make([]byte, n)
|
*buf = (*buf)[n:]
|
||||||
} else {
|
|
||||||
if len(rddataBuf) < n {
|
|
||||||
rddataBuf = make([]byte, rddataBufMax)
|
|
||||||
}
|
|
||||||
p = rddataBuf[:n:n]
|
|
||||||
rddataBuf = rddataBuf[n:]
|
|
||||||
}
|
|
||||||
obj.Bread(f, p)
|
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue