]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: remove type-punning for Type.gc[0], gc[1]
authorRuss Cox <rsc@golang.org>
Tue, 7 Oct 2014 15:06:51 +0000 (11:06 -0400)
committerRuss Cox <rsc@golang.org>
Tue, 7 Oct 2014 15:06:51 +0000 (11:06 -0400)
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

src/cmd/gc/reflect.c
src/cmd/ld/decodesym.c
src/reflect/type.go
src/runtime/malloc.go
src/runtime/type.h

index 4892ab75708e0cfe57e5d99cc3ca0fdb9878c49a..d0ebf6b481cbf6e6c1fc1d9629642bbfbba2cdaf 100644 (file)
@@ -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);
index c530669425e15f889de322da413b80845da4c298..037263dce766b89f8fcd4c2c2f89cda9deaa593d 100644 (file)
@@ -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
index f099546d270fd80fe39083d7a2e2d5780734f70f..a36c0ba604d9f728355ea48077bcbf8ae77ca6b5 100644 (file)
@@ -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))
index 99d14e31459a223a42cc2a322adfe8cd3a0a2cb2..9b4264f2b3daccedeb5ba3eeef3578b90ab24a77 100644 (file)
@@ -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
index de82e886f29be96658effe9ab2c41d8b15702d3e..f5b4f9d13fd4ef229b8ab5e7d88f8684490cb871 100644 (file)
@@ -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.