}
}
+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 {
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
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 {
}
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)
}
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
}
}
+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 {
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
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
}
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)
}
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
// 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
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.
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 {
// 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
}
// 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
}