aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/reflectdata/reflect.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile/internal/reflectdata/reflect.go')
-rw-r--r--src/cmd/compile/internal/reflectdata/reflect.go64
1 files changed, 52 insertions, 12 deletions
diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go
index 06c4986cf4..01eaf26a0a 100644
--- a/src/cmd/compile/internal/reflectdata/reflect.go
+++ b/src/cmd/compile/internal/reflectdata/reflect.go
@@ -52,6 +52,9 @@ var (
signatset = make(map[*types.Type]struct{})
signatslice []*types.Type
+ gcsymmu sync.Mutex // protects gcsymset and gcsymslice
+ gcsymset = make(map[*types.Type]struct{})
+
itabs []itabEntry
ptabs []*ir.Name
)
@@ -694,7 +697,8 @@ func dcommontype(lsym *obj.LSym, t *types.Type) int {
sptr = writeType(tptr)
}
- gcsym, useGCProg, ptrdata := dgcsym(t)
+ gcsym, useGCProg, ptrdata := dgcsym(t, true)
+ delete(gcsymset, t)
// ../../../../reflect/type.go:/^type.rtype
// actual type structure
@@ -1321,6 +1325,16 @@ func WriteRuntimeTypes() {
}
}
}
+
+ // Emit GC data symbols.
+ gcsyms := make([]typeAndStr, 0, len(gcsymset))
+ for t := range gcsymset {
+ gcsyms = append(gcsyms, typeAndStr{t: t, short: types.TypeSymName(t), regular: t.String()})
+ }
+ sort.Sort(typesByString(gcsyms))
+ for _, ts := range gcsyms {
+ dgcsym(ts.t, true)
+ }
}
func WriteTabs() {
@@ -1490,29 +1504,46 @@ func (a typesByString) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
//
const maxPtrmaskBytes = 2048
-// dgcsym emits and returns a data symbol containing GC information for type t,
-// along with a boolean reporting whether the UseGCProg bit should be set in
-// the type kind, and the ptrdata field to record in the reflect type information.
-func dgcsym(t *types.Type) (lsym *obj.LSym, useGCProg bool, ptrdata int64) {
+// GCSym returns a data symbol containing GC information for type t, along
+// with a boolean reporting whether the UseGCProg bit should be set in the
+// type kind, and the ptrdata field to record in the reflect type information.
+// GCSym may be called in concurrent backend, so it does not emit the symbol
+// content.
+func GCSym(t *types.Type) (lsym *obj.LSym, useGCProg bool, ptrdata int64) {
+ // Record that we need to emit the GC symbol.
+ gcsymmu.Lock()
+ if _, ok := gcsymset[t]; !ok {
+ gcsymset[t] = struct{}{}
+ }
+ gcsymmu.Unlock()
+
+ return dgcsym(t, false)
+}
+
+// dgcsym returns a data symbol containing GC information for type t, along
+// with a boolean reporting whether the UseGCProg bit should be set in the
+// type kind, and the ptrdata field to record in the reflect type information.
+// When write is true, it writes the symbol data.
+func dgcsym(t *types.Type, write bool) (lsym *obj.LSym, useGCProg bool, ptrdata int64) {
ptrdata = types.PtrDataSize(t)
if ptrdata/int64(types.PtrSize) <= maxPtrmaskBytes*8 {
- lsym = dgcptrmask(t)
+ lsym = dgcptrmask(t, write)
return
}
useGCProg = true
- lsym, ptrdata = dgcprog(t)
+ lsym, ptrdata = dgcprog(t, write)
return
}
// dgcptrmask emits and returns the symbol containing a pointer mask for type t.
-func dgcptrmask(t *types.Type) *obj.LSym {
+func dgcptrmask(t *types.Type, write bool) *obj.LSym {
ptrmask := make([]byte, (types.PtrDataSize(t)/int64(types.PtrSize)+7)/8)
fillptrmask(t, ptrmask)
p := fmt.Sprintf("runtime.gcbits.%x", ptrmask)
lsym := base.Ctxt.Lookup(p)
- if !lsym.OnList() {
+ if write && !lsym.OnList() {
for i, x := range ptrmask {
objw.Uint8(lsym, i, x)
}
@@ -1549,14 +1580,14 @@ func fillptrmask(t *types.Type, ptrmask []byte) {
// [types.PtrDataSize(t), t.Width]).
// In practice, the size is types.PtrDataSize(t) except for non-trivial arrays.
// For non-trivial arrays, the program describes the full t.Width size.
-func dgcprog(t *types.Type) (*obj.LSym, int64) {
+func dgcprog(t *types.Type, write bool) (*obj.LSym, int64) {
types.CalcSize(t)
if t.Width == types.BADWIDTH {
base.Fatalf("dgcprog: %v badwidth", t)
}
lsym := TypeLinksymPrefix(".gcprog", t)
var p gcProg
- p.init(lsym)
+ p.init(lsym, write)
p.emit(t, 0)
offset := p.w.BitIndex() * int64(types.PtrSize)
p.end()
@@ -1570,11 +1601,17 @@ type gcProg struct {
lsym *obj.LSym
symoff int
w gcprog.Writer
+ write bool
}
-func (p *gcProg) init(lsym *obj.LSym) {
+func (p *gcProg) init(lsym *obj.LSym, write bool) {
p.lsym = lsym
+ p.write = write && !lsym.OnList()
p.symoff = 4 // first 4 bytes hold program length
+ if !write {
+ p.w.Init(func(byte) {})
+ return
+ }
p.w.Init(p.writeByte)
if base.Debug.GCProg > 0 {
fmt.Fprintf(os.Stderr, "compile: start GCProg for %v\n", lsym)
@@ -1588,6 +1625,9 @@ func (p *gcProg) writeByte(x byte) {
func (p *gcProg) end() {
p.w.End()
+ if !p.write {
+ return
+ }
objw.Uint32(p.lsym, 0, uint32(p.symoff-4))
objw.Global(p.lsym, int32(p.symoff), obj.DUPOK|obj.RODATA|obj.LOCAL)
p.lsym.Set(obj.AttrContentAddressable, true)