]> Cypherpunks repositories - gostls13.git/commitdiff
go/internal/gcimporter: avoid setting unnecessary lines in fakeFileSet
authorRobert Findley <rfindley@google.com>
Wed, 20 Oct 2021 18:54:13 +0000 (14:54 -0400)
committerRobert Findley <rfindley@google.com>
Wed, 20 Oct 2021 19:29:12 +0000 (19:29 +0000)
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 <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>

src/go/internal/gcimporter/iimport.go
src/go/internal/gcimporter/support.go

index 9aae2a31f38fad20d3bd1682c23275c2be41efb7..0771fa3c2614bfeb76925ebc1763fa1b7244ba93 100644 (file)
@@ -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
index 09810dd85b8b5949550b729debdbc5e7f04690cf..5aef63ec1e4fc2b4227512492765f8ddda167370 100644 (file)
@@ -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 (