// first word dumped is the total number of bitmaps. The second word is the
// length of the bitmaps. All bitmaps are assumed to be of equal length. The
// remaining bytes are the raw bitmaps.
-func (lv *Liveness) emit(argssym, livesym, regssym *obj.LSym) {
+func (lv *Liveness) emit() (argsSym, liveSym, regsSym *obj.LSym) {
// Size args bitmaps to be just large enough to hold the largest pointer.
// First, find the largest Xoffset node we care about.
// (Nodes without pointers aren't in lv.vars; see livenessShouldTrack.)
// This would require shifting all bitmaps.
maxLocals := lv.stkptrsize
+ // Temporary symbols for encoding bitmaps.
+ var argsSymTmp, liveSymTmp, regsSymTmp obj.LSym
+
args := bvalloc(int32(maxArgs / int64(Widthptr)))
- aoff := duint32(argssym, 0, uint32(len(lv.stackMaps))) // number of bitmaps
- aoff = duint32(argssym, aoff, uint32(args.n)) // number of bits in each bitmap
+ aoff := duint32(&argsSymTmp, 0, uint32(len(lv.stackMaps))) // number of bitmaps
+ aoff = duint32(&argsSymTmp, aoff, uint32(args.n)) // number of bits in each bitmap
locals := bvalloc(int32(maxLocals / int64(Widthptr)))
- loff := duint32(livesym, 0, uint32(len(lv.stackMaps))) // number of bitmaps
- loff = duint32(livesym, loff, uint32(locals.n)) // number of bits in each bitmap
+ loff := duint32(&liveSymTmp, 0, uint32(len(lv.stackMaps))) // number of bitmaps
+ loff = duint32(&liveSymTmp, loff, uint32(locals.n)) // number of bits in each bitmap
for _, live := range lv.stackMaps {
args.Clear()
lv.pointerMap(live, lv.vars, args, locals)
- aoff = dbvec(argssym, aoff, args)
- loff = dbvec(livesym, loff, locals)
+ aoff = dbvec(&argsSymTmp, aoff, args)
+ loff = dbvec(&liveSymTmp, loff, locals)
}
regs := bvalloc(lv.usedRegs())
- roff := duint32(regssym, 0, uint32(len(lv.regMaps))) // number of bitmaps
- roff = duint32(regssym, roff, uint32(regs.n)) // number of bits in each bitmap
+ roff := duint32(®sSymTmp, 0, uint32(len(lv.regMaps))) // number of bitmaps
+ roff = duint32(®sSymTmp, roff, uint32(regs.n)) // number of bits in each bitmap
if regs.n > 32 {
// Our uint32 conversion below won't work.
Fatalf("GP registers overflow uint32")
for _, live := range lv.regMaps {
regs.Clear()
regs.b[0] = uint32(live)
- roff = dbvec(regssym, roff, regs)
+ roff = dbvec(®sSymTmp, roff, regs)
}
}
// Give these LSyms content-addressable names,
// so that they can be de-duplicated.
// This provides significant binary size savings.
- // It is safe to rename these LSyms because
- // they are tracked separately from ctxt.hash.
- argssym.Name = fmt.Sprintf("gclocals·%x", md5.Sum(argssym.P))
- livesym.Name = fmt.Sprintf("gclocals·%x", md5.Sum(livesym.P))
- regssym.Name = fmt.Sprintf("gclocals·%x", md5.Sum(regssym.P))
+ //
+ // These symbols will be added to Ctxt.Data by addGCLocals
+ // after parallel compilation is done.
+ makeSym := func(tmpSym *obj.LSym) *obj.LSym {
+ return Ctxt.LookupInit(fmt.Sprintf("gclocals·%x", md5.Sum(tmpSym.P)), func(lsym *obj.LSym) {
+ lsym.P = tmpSym.P
+ })
+ }
+ return makeSym(&argsSymTmp), makeSym(&liveSymTmp), makeSym(®sSymTmp)
}
// Entry pointer for liveness analysis. Solves for the liveness of
// pointer variables in the function and emits a runtime data
// structure read by the garbage collector.
// Returns a map from GC safe points to their corresponding stack map index.
-func liveness(e *ssafn, f *ssa.Func) LivenessMap {
+func liveness(e *ssafn, f *ssa.Func, pp *Progs) LivenessMap {
// Construct the global liveness state.
vars, idx := getvariables(e.curfn)
lv := newliveness(e.curfn, f, vars, idx, e.stkptrsize)
// Emit the live pointer map data structures
if ls := e.curfn.Func.lsym; ls != nil {
- lv.emit(&ls.Func.GCArgs, &ls.Func.GCLocals, &ls.Func.GCRegs)
+ ls.Func.GCArgs, ls.Func.GCLocals, ls.Func.GCRegs = lv.emit()
+
+ p := pp.Prog(obj.AFUNCDATA)
+ Addrconst(&p.From, objabi.FUNCDATA_ArgsPointerMaps)
+ p.To.Type = obj.TYPE_MEM
+ p.To.Name = obj.NAME_EXTERN
+ p.To.Sym = ls.Func.GCArgs
+
+ p = pp.Prog(obj.AFUNCDATA)
+ Addrconst(&p.From, objabi.FUNCDATA_LocalsPointerMaps)
+ p.To.Type = obj.TYPE_MEM
+ p.To.Name = obj.NAME_EXTERN
+ p.To.Sym = ls.Func.GCLocals
+
+ p = pp.Prog(obj.AFUNCDATA)
+ Addrconst(&p.From, objabi.FUNCDATA_RegPointerMaps)
+ p.To.Type = obj.TYPE_MEM
+ p.To.Name = obj.NAME_EXTERN
+ p.To.Sym = ls.Func.GCRegs
}
return lv.livenessMap
}