mirror of
https://github.com/golang/go
synced 2024-11-18 16:14:46 -07:00
runtime: remove type-punning for Type.gc[0], gc[1]
Depending on flags&KindGCProg, gc[0] and gc[1] are either pointers or inlined bitmap bits. That's not compatible with a precise garbage collector: it needs to be always pointers or never pointers. Change the inlined bitmap case to store a pointer to an out-of-line bitmap in gc[0]. The out-of-line bitmaps are dedup'ed, so that for example all pointer types share the same out-of-line bitmap. Fixes #8864. LGTM=r R=golang-codereviews, dvyukov, r CC=golang-codereviews, iant, khr, rlh https://golang.org/cl/155820043
This commit is contained in:
parent
f739b77508
commit
18172c42ff
@ -716,9 +716,10 @@ static int
|
||||
dcommontype(Sym *s, int ot, Type *t)
|
||||
{
|
||||
int i, alg, sizeofAlg, gcprog;
|
||||
Sym *sptr, *algsym, *zero, *gcprog0, *gcprog1;
|
||||
Sym *sptr, *algsym, *zero, *gcprog0, *gcprog1, *sbits;
|
||||
uint8 gcmask[16];
|
||||
static Sym *algarray;
|
||||
uint64 x1, x2;
|
||||
char *p;
|
||||
|
||||
if(ot != 0)
|
||||
@ -804,8 +805,26 @@ dcommontype(Sym *s, int ot, Type *t)
|
||||
ot = dsymptr(s, ot, gcprog1, 0);
|
||||
} else {
|
||||
gengcmask(t, gcmask);
|
||||
for(i = 0; i < 2*widthptr; i++)
|
||||
ot = duint8(s, ot, gcmask[i]);
|
||||
x1 = 0;
|
||||
for(i=0; i<8; i++)
|
||||
x1 = x1<<8 | gcmask[i];
|
||||
if(widthptr == 4) {
|
||||
p = smprint("gcbits.%#016x", x1);
|
||||
} else {
|
||||
x2 = 0;
|
||||
for(i=0; i<8; i++)
|
||||
x2 = x2<<8 | gcmask[i+8];
|
||||
p = smprint("gcbits.%#016llux%016llux", x1, x2);
|
||||
}
|
||||
sbits = pkglookup(p, runtimepkg);
|
||||
if((sbits->flags & SymUniq) == 0) {
|
||||
sbits->flags |= SymUniq;
|
||||
for(i = 0; i < 2*widthptr; i++)
|
||||
duint8(sbits, i, gcmask[i]);
|
||||
ggloblsym(sbits, 2*widthptr, DUPOK|RODATA);
|
||||
}
|
||||
ot = dsymptr(s, ot, sbits, 0);
|
||||
ot = duintptr(s, ot, 0);
|
||||
}
|
||||
p = smprint("%-uT", t);
|
||||
//print("dcommontype: %s\n", p);
|
||||
|
@ -111,7 +111,10 @@ decodetype_gcprog(LSym *s)
|
||||
uint8*
|
||||
decodetype_gcmask(LSym *s)
|
||||
{
|
||||
return (uint8*)(s->p + 1*PtrSize + 8 + 1*PtrSize);
|
||||
LSym *mask;
|
||||
|
||||
mask = decode_reloc_sym(s, 1*PtrSize + 8 + 1*PtrSize);
|
||||
return mask->p;
|
||||
}
|
||||
|
||||
// Type.ArrayType.elem and Type.SliceType.Elem
|
||||
|
@ -1523,8 +1523,8 @@ func (gc *gcProg) appendProg(t *rtype) {
|
||||
// The program is stored in t.gc[0], skip unroll flag.
|
||||
prog = (*[1 << 30]byte)(unsafe.Pointer(t.gc[0]))[1:]
|
||||
} else {
|
||||
// The mask is embed directly in t.gc.
|
||||
prog = (*[1 << 30]byte)(unsafe.Pointer(&t.gc[0]))[:]
|
||||
// The mask is linked directly in t.gc.
|
||||
prog = (*[2 * ptrSize]byte)(unsafe.Pointer(t.gc[0]))[:]
|
||||
}
|
||||
for i := uintptr(0); i < nptr; i++ {
|
||||
gc.appendWord(extractGCWord(prog, i))
|
||||
|
@ -270,7 +270,7 @@ func mallocgc(size uintptr, typ *_type, flags int) unsafe.Pointer {
|
||||
}
|
||||
ptrmask = (*uint8)(add(unsafe.Pointer(ptrmask), 1)) // skip the unroll flag byte
|
||||
} else {
|
||||
ptrmask = (*uint8)(unsafe.Pointer(&typ.gc[0])) // embed mask
|
||||
ptrmask = (*uint8)(unsafe.Pointer(typ.gc[0])) // pointer to unrolled mask
|
||||
}
|
||||
if size == 2*ptrSize {
|
||||
*xbits = *ptrmask | bitBoundary
|
||||
|
@ -23,7 +23,7 @@ struct Type
|
||||
uint8 kind;
|
||||
void* alg;
|
||||
// gc stores type info required for garbage collector.
|
||||
// If (kind&KindGCProg)==0, then gc directly contains sparse GC bitmap
|
||||
// If (kind&KindGCProg)==0, then gc[0] points at sparse GC bitmap
|
||||
// (no indirection), 4 bits per word.
|
||||
// If (kind&KindGCProg)!=0, then gc[1] points to a compiler-generated
|
||||
// read-only GC program; and gc[0] points to BSS space for sparse GC bitmap.
|
||||
|
Loading…
Reference in New Issue
Block a user