From: Robert Findley Date: Wed, 20 Oct 2021 18:54:13 +0000 (-0400) Subject: go/internal/gcimporter: avoid setting unnecessary lines in fakeFileSet X-Git-Tag: go1.18beta1~825 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=4320949f36f5f523a08ce8da6bdcd35ef51b8941;p=gostls13.git go/internal/gcimporter: avoid setting unnecessary lines in fakeFileSet This is a clean port of CL 357291 from x/tools. For #46586 Change-Id: Ib22087ae7fe8477d368acd230b263b83cdad4d36 Reviewed-on: https://go-review.googlesource.com/c/go/+/357429 Trust: Robert Findley Run-TryBot: Robert Findley Reviewed-by: Matthew Dempsky TryBot-Result: Go Bot --- diff --git a/src/go/internal/gcimporter/iimport.go b/src/go/internal/gcimporter/iimport.go index 9aae2a31f3..0771fa3c26 100644 --- a/src/go/internal/gcimporter/iimport.go +++ b/src/go/internal/gcimporter/iimport.go @@ -135,9 +135,10 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, dataRea fake: fakeFileSet{ fset: fset, - files: make(map[string]*token.File), + files: make(map[string]*fileInfo), }, } + defer p.fake.setLines() // set lines for files in fset for i, pt := range predeclared { p.typCache[uint64(i)] = pt diff --git a/src/go/internal/gcimporter/support.go b/src/go/internal/gcimporter/support.go index 09810dd85b..5aef63ec1e 100644 --- a/src/go/internal/gcimporter/support.go +++ b/src/go/internal/gcimporter/support.go @@ -25,37 +25,50 @@ const deltaNewFile = -64 // Synthesize a token.Pos type fakeFileSet struct { fset *token.FileSet - files map[string]*token.File + files map[string]*fileInfo } +type fileInfo struct { + file *token.File + lastline int +} + +const maxlines = 64 * 1024 + func (s *fakeFileSet) pos(file string, line, column int) token.Pos { // TODO(mdempsky): Make use of column. - // Since we don't know the set of needed file positions, we - // reserve maxlines positions per file. - const maxlines = 64 * 1024 + // Since we don't know the set of needed file positions, we reserve + // maxlines positions per file. We delay calling token.File.SetLines until + // all positions have been calculated (by way of fakeFileSet.setLines), so + // that we can avoid setting unnecessary lines. See also golang/go#46586. f := s.files[file] if f == nil { - f = s.fset.AddFile(file, -1, maxlines) + f = &fileInfo{file: s.fset.AddFile(file, -1, maxlines)} s.files[file] = f - // Allocate the fake linebreak indices on first use. - // TODO(adonovan): opt: save ~512KB using a more complex scheme? - fakeLinesOnce.Do(func() { - fakeLines = make([]int, maxlines) - for i := range fakeLines { - fakeLines[i] = i - } - }) - f.SetLines(fakeLines) } if line > maxlines { line = 1 } + if line > f.lastline { + f.lastline = line + } - // Treat the file as if it contained only newlines - // and column=1: use the line number as the offset. - return f.Pos(line - 1) + // Return a fake position assuming that f.file consists only of newlines. + return token.Pos(f.file.Base() + line - 1) +} + +func (s *fakeFileSet) setLines() { + fakeLinesOnce.Do(func() { + fakeLines = make([]int, maxlines) + for i := range fakeLines { + fakeLines[i] = i + } + }) + for _, f := range s.files { + f.file.SetLines(fakeLines[:f.lastline]) + } } var (