]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: introduce "temporary" readers for more storage reuse
authorDavid Chase <drchase@google.com>
Fri, 23 Sep 2022 02:27:33 +0000 (22:27 -0400)
committerDavid Chase <drchase@google.com>
Tue, 27 Sep 2022 20:36:31 +0000 (20:36 +0000)
Change-Id: Id05d6099624284a9c1583b066d1a703e806b1e22
Reviewed-on: https://go-review.googlesource.com/c/go/+/433037
Run-TryBot: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
src/cmd/compile/internal/importer/ureader.go
src/go/internal/gcimporter/ureader.go
src/internal/pkgbits/decoder.go

index a227ab64db883380155b6d1b36d0abaf4dcd08a5..f5c2f41069de8b40086ceadba60eae624814f494 100644 (file)
@@ -83,6 +83,17 @@ func (pr *pkgReader) newReader(k pkgbits.RelocKind, idx pkgbits.Index, marker pk
        }
 }
 
+func (pr *pkgReader) tempReader(k pkgbits.RelocKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader {
+       return &reader{
+               Decoder: pr.TempDecoder(k, idx, marker),
+               p:       pr,
+       }
+}
+
+func (pr *pkgReader) retireReader(r *reader) {
+       pr.RetireDecoder(&r.Decoder)
+}
+
 // @@@ Positions
 
 func (r *reader) pos() syntax.Pos {
@@ -106,19 +117,21 @@ func (pr *pkgReader) posBaseIdx(idx pkgbits.Index) *syntax.PosBase {
        if b := pr.posBases[idx]; b != nil {
                return b
        }
-
-       r := pr.newReader(pkgbits.RelocPosBase, idx, pkgbits.SyncPosBase)
        var b *syntax.PosBase
+       {
+               r := pr.tempReader(pkgbits.RelocPosBase, idx, pkgbits.SyncPosBase)
 
-       filename := r.String()
+               filename := r.String()
 
-       if r.Bool() {
-               b = syntax.NewTrimmedFileBase(filename, true)
-       } else {
-               pos := r.pos()
-               line := r.Uint()
-               col := r.Uint()
-               b = syntax.NewLineBase(pos, filename, true, line, col)
+               if r.Bool() {
+                       b = syntax.NewTrimmedFileBase(filename, true)
+               } else {
+                       pos := r.pos()
+                       line := r.Uint()
+                       col := r.Uint()
+                       b = syntax.NewLineBase(pos, filename, true, line, col)
+               }
+               pr.retireReader(r)
        }
 
        pr.posBases[idx] = b
@@ -202,11 +215,15 @@ func (pr *pkgReader) typIdx(info typeInfo, dict *readerDict) types2.Type {
                return typ
        }
 
-       r := pr.newReader(pkgbits.RelocType, idx, pkgbits.SyncTypeIdx)
-       r.dict = dict
+       var typ types2.Type
+       {
+               r := pr.tempReader(pkgbits.RelocType, idx, pkgbits.SyncTypeIdx)
+               r.dict = dict
 
-       typ := r.doTyp()
-       assert(typ != nil)
+               typ = r.doTyp()
+               assert(typ != nil)
+               pr.retireReader(r)
+       }
 
        // See comment in pkgReader.typIdx explaining how this happens.
        if prev := *where; prev != nil {
@@ -361,12 +378,18 @@ func (r *reader) obj() (types2.Object, []types2.Type) {
 }
 
 func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types2.Package, string) {
-       rname := pr.newReader(pkgbits.RelocName, idx, pkgbits.SyncObject1)
+       var objPkg *types2.Package
+       var objName string
+       var tag pkgbits.CodeObj
+       {
+               rname := pr.tempReader(pkgbits.RelocName, idx, pkgbits.SyncObject1)
 
-       objPkg, objName := rname.qualifiedIdent()
-       assert(objName != "")
+               objPkg, objName = rname.qualifiedIdent()
+               assert(objName != "")
 
-       tag := pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj))
+               tag = pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj))
+               pr.retireReader(rname)
+       }
 
        if tag == pkgbits.ObjStub {
                base.Assertf(objPkg == nil || objPkg == types2.Unsafe, "unexpected stub package: %v", objPkg)
@@ -431,25 +454,27 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types2.Package, string) {
 }
 
 func (pr *pkgReader) objDictIdx(idx pkgbits.Index) *readerDict {
-       r := pr.newReader(pkgbits.RelocObjDict, idx, pkgbits.SyncObject1)
-
        var dict readerDict
+       {
+               r := pr.tempReader(pkgbits.RelocObjDict, idx, pkgbits.SyncObject1)
 
-       if implicits := r.Len(); implicits != 0 {
-               base.Fatalf("unexpected object with %v implicit type parameter(s)", implicits)
-       }
+               if implicits := r.Len(); implicits != 0 {
+                       base.Fatalf("unexpected object with %v implicit type parameter(s)", implicits)
+               }
 
-       dict.bounds = make([]typeInfo, r.Len())
-       for i := range dict.bounds {
-               dict.bounds[i] = r.typInfo()
-       }
+               dict.bounds = make([]typeInfo, r.Len())
+               for i := range dict.bounds {
+                       dict.bounds[i] = r.typInfo()
+               }
 
-       dict.derived = make([]derivedInfo, r.Len())
-       dict.derivedTypes = make([]types2.Type, len(dict.derived))
-       for i := range dict.derived {
-               dict.derived[i] = derivedInfo{r.Reloc(pkgbits.RelocType), r.Bool()}
-       }
+               dict.derived = make([]derivedInfo, r.Len())
+               dict.derivedTypes = make([]types2.Type, len(dict.derived))
+               for i := range dict.derived {
+                       dict.derived[i] = derivedInfo{r.Reloc(pkgbits.RelocType), r.Bool()}
+               }
 
+               pr.retireReader(r)
+       }
        // function references follow, but reader doesn't need those
 
        return &dict
index ad8e9a43d91bb5f0abfaa14c6285ea3edef49bdc..94c1f2802a2b249be1bcaadfc370a5ec15954124 100644 (file)
@@ -131,6 +131,17 @@ func (pr *pkgReader) newReader(k pkgbits.RelocKind, idx pkgbits.Index, marker pk
        }
 }
 
+func (pr *pkgReader) tempReader(k pkgbits.RelocKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader {
+       return &reader{
+               Decoder: pr.TempDecoder(k, idx, marker),
+               p:       pr,
+       }
+}
+
+func (pr *pkgReader) retireReader(r *reader) {
+       pr.RetireDecoder(&r.Decoder)
+}
+
 // @@@ Positions
 
 func (r *reader) pos() token.Pos {
@@ -155,26 +166,29 @@ func (pr *pkgReader) posBaseIdx(idx pkgbits.Index) string {
                return b
        }
 
-       r := pr.newReader(pkgbits.RelocPosBase, idx, pkgbits.SyncPosBase)
+       var filename string
+       {
+               r := pr.tempReader(pkgbits.RelocPosBase, idx, pkgbits.SyncPosBase)
 
-       // Within types2, position bases have a lot more details (e.g.,
-       // keeping track of where //line directives appeared exactly).
-       //
-       // For go/types, we just track the file name.
+               // Within types2, position bases have a lot more details (e.g.,
+               // keeping track of where //line directives appeared exactly).
+               //
+               // For go/types, we just track the file name.
 
-       filename := r.String()
+               filename = r.String()
 
-       if r.Bool() { // file base
-               // Was: "b = token.NewTrimmedFileBase(filename, true)"
-       } else { // line base
-               pos := r.pos()
-               line := r.Uint()
-               col := r.Uint()
+               if r.Bool() { // file base
+                       // Was: "b = token.NewTrimmedFileBase(filename, true)"
+               } else { // line base
+                       pos := r.pos()
+                       line := r.Uint()
+                       col := r.Uint()
 
-               // Was: "b = token.NewLineBase(pos, filename, true, line, col)"
-               _, _, _ = pos, line, col
+                       // Was: "b = token.NewLineBase(pos, filename, true, line, col)"
+                       _, _, _ = pos, line, col
+               }
+               pr.retireReader(r)
        }
-
        b := filename
        pr.posBases[idx] = b
        return b
@@ -286,12 +300,15 @@ func (pr *pkgReader) typIdx(info typeInfo, dict *readerDict) types.Type {
                return typ
        }
 
-       r := pr.newReader(pkgbits.RelocType, idx, pkgbits.SyncTypeIdx)
-       r.dict = dict
-
-       typ := r.doTyp()
-       assert(typ != nil)
+       var typ types.Type
+       {
+               r := pr.tempReader(pkgbits.RelocType, idx, pkgbits.SyncTypeIdx)
+               r.dict = dict
 
+               typ = r.doTyp()
+               assert(typ != nil)
+               pr.retireReader(r)
+       }
        // See comment in pkgReader.typIdx explaining how this happens.
        if prev := *where; prev != nil {
                return prev
@@ -457,12 +474,19 @@ func (r *reader) obj() (types.Object, []types.Type) {
 }
 
 func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) {
-       rname := pr.newReader(pkgbits.RelocName, idx, pkgbits.SyncObject1)
 
-       objPkg, objName := rname.qualifiedIdent()
-       assert(objName != "")
+       var objPkg *types.Package
+       var objName string
+       var tag pkgbits.CodeObj
+       {
+               rname := pr.tempReader(pkgbits.RelocName, idx, pkgbits.SyncObject1)
 
-       tag := pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj))
+               objPkg, objName = rname.qualifiedIdent()
+               assert(objName != "")
+
+               tag = pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj))
+               pr.retireReader(rname)
+       }
 
        if tag == pkgbits.ObjStub {
                assert(objPkg == nil || objPkg == types.Unsafe)
@@ -567,25 +591,28 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) {
 }
 
 func (pr *pkgReader) objDictIdx(idx pkgbits.Index) *readerDict {
-       r := pr.newReader(pkgbits.RelocObjDict, idx, pkgbits.SyncObject1)
 
        var dict readerDict
 
-       if implicits := r.Len(); implicits != 0 {
-               errorf("unexpected object with %v implicit type parameter(s)", implicits)
-       }
+       {
+               r := pr.tempReader(pkgbits.RelocObjDict, idx, pkgbits.SyncObject1)
+               if implicits := r.Len(); implicits != 0 {
+                       errorf("unexpected object with %v implicit type parameter(s)", implicits)
+               }
 
-       dict.bounds = make([]typeInfo, r.Len())
-       for i := range dict.bounds {
-               dict.bounds[i] = r.typInfo()
-       }
+               dict.bounds = make([]typeInfo, r.Len())
+               for i := range dict.bounds {
+                       dict.bounds[i] = r.typInfo()
+               }
 
-       dict.derived = make([]derivedInfo, r.Len())
-       dict.derivedTypes = make([]types.Type, len(dict.derived))
-       for i := range dict.derived {
-               dict.derived[i] = derivedInfo{r.Reloc(pkgbits.RelocType), r.Bool()}
-       }
+               dict.derived = make([]derivedInfo, r.Len())
+               dict.derivedTypes = make([]types.Type, len(dict.derived))
+               for i := range dict.derived {
+                       dict.derived[i] = derivedInfo{r.Reloc(pkgbits.RelocType), r.Bool()}
+               }
 
+               pr.retireReader(r)
+       }
        // function references follow, but reader doesn't need those
 
        return &dict
index 357e328a3bae49b7e708dffb0de28f3e40fd6554..1a18da330148fccfb0cad2045edeef3435915c68 100644 (file)
@@ -52,6 +52,8 @@ type PkgDecoder struct {
        // For example, section K's end positions start at elemEndsEnds[K-1]
        // (or 0, if K==0) and end at elemEndsEnds[K].
        elemEndsEnds [numRelocs]uint32
+
+       scratchRelocEnt []RelocEnt
 }
 
 // PkgPath returns the package path for the package
@@ -165,6 +167,21 @@ func (pr *PkgDecoder) NewDecoder(k RelocKind, idx Index, marker SyncMarker) Deco
        return r
 }
 
+// TempDecoder returns a Decoder for the given (section, index) pair,
+// and decodes the given SyncMarker from the element bitstream.
+// If possible the Decoder should be RetireDecoder'd when it is no longer
+// needed, this will avoid heap allocations.
+func (pr *PkgDecoder) TempDecoder(k RelocKind, idx Index, marker SyncMarker) Decoder {
+       r := pr.TempDecoderRaw(k, idx)
+       r.Sync(marker)
+       return r
+}
+
+func (pr *PkgDecoder) RetireDecoder(d *Decoder) {
+       pr.scratchRelocEnt = d.Relocs
+       d.Relocs = nil
+}
+
 // NewDecoderRaw returns a Decoder for the given (section, index) pair.
 //
 // Most callers should use NewDecoder instead.
@@ -186,6 +203,30 @@ func (pr *PkgDecoder) NewDecoderRaw(k RelocKind, idx Index) Decoder {
        return r
 }
 
+func (pr *PkgDecoder) TempDecoderRaw(k RelocKind, idx Index) Decoder {
+       r := Decoder{
+               common: pr,
+               k:      k,
+               Idx:    idx,
+       }
+
+       r.Data.Reset(pr.DataIdx(k, idx))
+       r.Sync(SyncRelocs)
+       l := r.Len()
+       if cap(pr.scratchRelocEnt) >= l {
+               r.Relocs = pr.scratchRelocEnt[:l]
+               pr.scratchRelocEnt = nil
+       } else {
+               r.Relocs = make([]RelocEnt, l)
+       }
+       for i := range r.Relocs {
+               r.Sync(SyncReloc)
+               r.Relocs[i] = RelocEnt{RelocKind(r.Len()), Index(r.Len())}
+       }
+
+       return r
+}
+
 // A Decoder provides methods for decoding an individual element's
 // bitstream data.
 type Decoder struct {
@@ -408,8 +449,12 @@ func (r *Decoder) bigFloat() *big.Float {
 // PeekPkgPath returns the package path for the specified package
 // index.
 func (pr *PkgDecoder) PeekPkgPath(idx Index) string {
-       r := pr.NewDecoder(RelocPkg, idx, SyncPkgDef)
-       path := r.String()
+       var path string
+       {
+               r := pr.TempDecoder(RelocPkg, idx, SyncPkgDef)
+               path = r.String()
+               pr.RetireDecoder(&r)
+       }
        if path == "" {
                path = pr.pkgPath
        }
@@ -419,14 +464,23 @@ func (pr *PkgDecoder) PeekPkgPath(idx Index) string {
 // PeekObj returns the package path, object name, and CodeObj for the
 // specified object index.
 func (pr *PkgDecoder) PeekObj(idx Index) (string, string, CodeObj) {
-       r := pr.NewDecoder(RelocName, idx, SyncObject1)
-       r.Sync(SyncSym)
-       r.Sync(SyncPkg)
-       path := pr.PeekPkgPath(r.Reloc(RelocPkg))
-       name := r.String()
+       var ridx Index
+       var name string
+       var rcode int
+       {
+               r := pr.TempDecoder(RelocName, idx, SyncObject1)
+               r.Sync(SyncSym)
+               r.Sync(SyncPkg)
+               ridx = r.Reloc(RelocPkg)
+               name = r.String()
+               rcode = r.Code(SyncCodeObj)
+               pr.RetireDecoder(&r)
+       }
+
+       path := pr.PeekPkgPath(ridx)
        assert(name != "")
 
-       tag := CodeObj(r.Code(SyncCodeObj))
+       tag := CodeObj(rcode)
 
        return path, name, tag
 }