Skip to content

Commit 95b8cbf

Browse files
committed
cmd/compile: add column details to export data
This CL updates the export data format to include column details when writing out position data. cmd/compile is updated to generate and make use of the new details, but go/internal/gcimporter only knows how to read the data. It doesn't yet actually make use of it. Experimentally across a wide range of packages, this increases export data size by around 4%. However, it has no impact on binary size. (Notably, it actually shrinks k8s.io/kubernetes/cmd/kubelet's binary size by 24kB, but it's unclear to me why at this time.) Updates #28259. Change-Id: I351fb340839df8d3adced49b3757c4537fb91b3f Reviewed-on: https://go-review.googlesource.com/c/go/+/196963 Run-TryBot: Matthew Dempsky <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Robert Griesemer <[email protected]> Reviewed-by: Rob Pike <[email protected]>
1 parent 683ef8c commit 95b8cbf

File tree

4 files changed

+85
-47
lines changed

4 files changed

+85
-47
lines changed

src/cmd/compile/internal/gc/iexport.go

+36-23
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,9 @@
184184
// }
185185
//
186186
//
187-
// Pos encodes a file:line pair, incorporating a simple delta encoding
188-
// scheme within a data object. See exportWriter.pos for details.
187+
// Pos encodes a file:line:column triple, incorporating a simple delta
188+
// encoding scheme within a data object. See exportWriter.pos for
189+
// details.
189190
//
190191
//
191192
// Compiler-specific details.
@@ -212,8 +213,9 @@ import (
212213
)
213214

214215
// Current indexed export format version. Increase with each format change.
216+
// 1: added column details to Pos
215217
// 0: Go1.11 encoding
216-
const iexportVersion = 0
218+
const iexportVersion = 1
217219

218220
// predeclReserved is the number of type offsets reserved for types
219221
// implicitly declared in the universe block.
@@ -401,10 +403,11 @@ func (p *iexporter) pushDecl(n *Node) {
401403
type exportWriter struct {
402404
p *iexporter
403405

404-
data intWriter
405-
currPkg *types.Pkg
406-
prevFile string
407-
prevLine int64
406+
data intWriter
407+
currPkg *types.Pkg
408+
prevFile string
409+
prevLine int64
410+
prevColumn int64
408411
}
409412

410413
func (p *iexporter) doDecl(n *Node) {
@@ -510,29 +513,39 @@ func (w *exportWriter) pos(pos src.XPos) {
510513
p := Ctxt.PosTable.Pos(pos)
511514
file := p.Base().AbsFilename()
512515
line := int64(p.RelLine())
516+
column := int64(p.RelCol())
513517

514-
// When file is the same as the last position (common case),
515-
// we can save a few bytes by delta encoding just the line
516-
// number.
518+
// Encode position relative to the last position: column
519+
// delta, then line delta, then file name. We reserve the
520+
// bottom bit of the column and line deltas to encode whether
521+
// the remaining fields are present.
517522
//
518523
// Note: Because data objects may be read out of order (or not
519524
// at all), we can only apply delta encoding within a single
520-
// object. This is handled implicitly by tracking prevFile and
521-
// prevLine as fields of exportWriter.
522-
523-
if file == w.prevFile {
524-
delta := line - w.prevLine
525-
w.int64(delta)
526-
if delta == deltaNewFile {
527-
w.int64(-1)
525+
// object. This is handled implicitly by tracking prevFile,
526+
// prevLine, and prevColumn as fields of exportWriter.
527+
528+
deltaColumn := (column - w.prevColumn) << 1
529+
deltaLine := (line - w.prevLine) << 1
530+
531+
if file != w.prevFile {
532+
deltaLine |= 1
533+
}
534+
if deltaLine != 0 {
535+
deltaColumn |= 1
536+
}
537+
538+
w.int64(deltaColumn)
539+
if deltaColumn&1 != 0 {
540+
w.int64(deltaLine)
541+
if deltaLine&1 != 0 {
542+
w.string(file)
528543
}
529-
} else {
530-
w.int64(deltaNewFile)
531-
w.int64(line) // line >= 0
532-
w.string(file)
533-
w.prevFile = file
534544
}
545+
546+
w.prevFile = file
535547
w.prevLine = line
548+
w.prevColumn = column
536549
}
537550

538551
func (w *exportWriter) pkg(pkg *types.Pkg) {

src/cmd/compile/internal/gc/iimport.go

+13-12
Original file line numberDiff line numberDiff line change
@@ -242,9 +242,10 @@ type importReader struct {
242242
strings.Reader
243243
p *iimporter
244244

245-
currPkg *types.Pkg
246-
prevBase *src.PosBase
247-
prevLine int64
245+
currPkg *types.Pkg
246+
prevBase *src.PosBase
247+
prevLine int64
248+
prevColumn int64
248249
}
249250

250251
func (p *iimporter) newReader(off uint64, pkg *types.Pkg) *importReader {
@@ -446,16 +447,16 @@ func (r *importReader) qualifiedIdent() *types.Sym {
446447

447448
func (r *importReader) pos() src.XPos {
448449
delta := r.int64()
449-
if delta != deltaNewFile {
450-
r.prevLine += delta
451-
} else if l := r.int64(); l == -1 {
452-
r.prevLine += deltaNewFile
453-
} else {
454-
r.prevBase = r.posBase()
455-
r.prevLine = l
450+
r.prevColumn += delta >> 1
451+
if delta&1 != 0 {
452+
delta = r.int64()
453+
r.prevLine += delta >> 1
454+
if delta&1 != 0 {
455+
r.prevBase = r.posBase()
456+
}
456457
}
457458

458-
if (r.prevBase == nil || r.prevBase.AbsFilename() == "") && r.prevLine == 0 {
459+
if (r.prevBase == nil || r.prevBase.AbsFilename() == "") && r.prevLine == 0 && r.prevColumn == 0 {
459460
// TODO(mdempsky): Remove once we reliably write
460461
// position information for all nodes.
461462
return src.NoXPos
@@ -464,7 +465,7 @@ func (r *importReader) pos() src.XPos {
464465
if r.prevBase == nil {
465466
Fatalf("missing posbase")
466467
}
467-
pos := src.MakePos(r.prevBase, uint(r.prevLine), 0)
468+
pos := src.MakePos(r.prevBase, uint(r.prevLine), uint(r.prevColumn))
468469
return Ctxt.PosTable.XPos(pos)
469470
}
470471

src/go/internal/gcimporter/bimport.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ func (p *importer) pos() token.Pos {
328328
p.prevFile = file
329329
p.prevLine = line
330330

331-
return p.fake.pos(file, line)
331+
return p.fake.pos(file, line, 0)
332332
}
333333

334334
// Synthesize a token.Pos
@@ -337,7 +337,9 @@ type fakeFileSet struct {
337337
files map[string]*token.File
338338
}
339339

340-
func (s *fakeFileSet) pos(file string, line int) token.Pos {
340+
func (s *fakeFileSet) pos(file string, line, column int) token.Pos {
341+
// TODO(mdempsky): Make use of column.
342+
341343
// Since we don't know the set of needed file positions, we
342344
// reserve maxlines positions per file.
343345
const maxlines = 64 * 1024

src/go/internal/gcimporter/iimport.go

+32-10
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ const (
6161
// If the export data version is not recognized or the format is otherwise
6262
// compromised, an error is returned.
6363
func iImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) {
64-
const currentVersion = 0
65-
version := -1
64+
const currentVersion = 1
65+
version := int64(-1)
6666
defer func() {
6767
if e := recover(); e != nil {
6868
if version > currentVersion {
@@ -75,9 +75,9 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, data []
7575

7676
r := &intReader{bytes.NewReader(data), path}
7777

78-
version = int(r.uint64())
78+
version = int64(r.uint64())
7979
switch version {
80-
case currentVersion:
80+
case currentVersion, 0:
8181
default:
8282
errorf("unknown iexport format version %d", version)
8383
}
@@ -91,7 +91,8 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, data []
9191
r.Seek(sLen+dLen, io.SeekCurrent)
9292

9393
p := iimporter{
94-
ipath: path,
94+
ipath: path,
95+
version: int(version),
9596

9697
stringData: stringData,
9798
stringCache: make(map[uint64]string),
@@ -169,7 +170,8 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, data []
169170
}
170171

171172
type iimporter struct {
172-
ipath string
173+
ipath string
174+
version int
173175

174176
stringData []byte
175177
stringCache map[uint64]string
@@ -249,6 +251,7 @@ type importReader struct {
249251
currPkg *types.Package
250252
prevFile string
251253
prevLine int64
254+
prevColumn int64
252255
}
253256

254257
func (r *importReader) obj(name string) {
@@ -438,6 +441,19 @@ func (r *importReader) qualifiedIdent() (*types.Package, string) {
438441
}
439442

440443
func (r *importReader) pos() token.Pos {
444+
if r.p.version >= 1 {
445+
r.posv1()
446+
} else {
447+
r.posv0()
448+
}
449+
450+
if r.prevFile == "" && r.prevLine == 0 && r.prevColumn == 0 {
451+
return token.NoPos
452+
}
453+
return r.p.fake.pos(r.prevFile, int(r.prevLine), int(r.prevColumn))
454+
}
455+
456+
func (r *importReader) posv0() {
441457
delta := r.int64()
442458
if delta != deltaNewFile {
443459
r.prevLine += delta
@@ -447,12 +463,18 @@ func (r *importReader) pos() token.Pos {
447463
r.prevFile = r.string()
448464
r.prevLine = l
449465
}
466+
}
450467

451-
if r.prevFile == "" && r.prevLine == 0 {
452-
return token.NoPos
468+
func (r *importReader) posv1() {
469+
delta := r.int64()
470+
r.prevColumn += delta >> 1
471+
if delta&1 != 0 {
472+
delta = r.int64()
473+
r.prevLine += delta >> 1
474+
if delta&1 != 0 {
475+
r.prevFile = r.string()
476+
}
453477
}
454-
455-
return r.p.fake.pos(r.prevFile, int(r.prevLine))
456478
}
457479

458480
func (r *importReader) typ() types.Type {

0 commit comments

Comments
 (0)