]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: fix getgcmask
authorDmitriy Vyukov <dvyukov@google.com>
Fri, 15 Aug 2014 18:36:12 +0000 (22:36 +0400)
committerDmitriy Vyukov <dvyukov@google.com>
Fri, 15 Aug 2014 18:36:12 +0000 (22:36 +0400)
bv.data is an array of uint32s but the code was using
offsets computed for an array of bytes.
Add a test for stack GC info.
Fixes #8531.

LGTM=rsc
R=golang-codereviews
CC=golang-codereviews, khr, rsc
https://golang.org/cl/124450043

src/pkg/runtime/gcinfo_test.go
src/pkg/runtime/mgc0.c

index 6afa9a4e2bd172692102c06c164dd3ae3cd6f605..892484ea6fb57cc58a7c717a2fd4520ab1f63c5e 100644 (file)
@@ -12,24 +12,30 @@ import (
 
 // TestGCInfo tests that various objects in heap, data and bss receive correct GC pointer type info.
 func TestGCInfo(t *testing.T) {
-       verifyGCInfo(t, "bss ScalarPtr", &bssScalarPtr, infoScalarPtr)
-       verifyGCInfo(t, "bss PtrScalar", &bssPtrScalar, infoPtrScalar)
-       verifyGCInfo(t, "bss Complex", &bssComplex, infoComplex())
-       verifyGCInfo(t, "bss string", &bssString, infoString)
-       verifyGCInfo(t, "bss eface", &bssEface, infoEface)
-
-       verifyGCInfo(t, "data ScalarPtr", &dataScalarPtr, infoScalarPtr)
-       verifyGCInfo(t, "data PtrScalar", &dataPtrScalar, infoPtrScalar)
-       verifyGCInfo(t, "data Complex", &dataComplex, infoComplex())
-       verifyGCInfo(t, "data string", &dataString, infoString)
-       verifyGCInfo(t, "data eface", &dataEface, infoEface)
+       verifyGCInfo(t, "bss ScalarPtr", &bssScalarPtr, nonStackInfo(infoScalarPtr))
+       verifyGCInfo(t, "bss PtrScalar", &bssPtrScalar, nonStackInfo(infoPtrScalar))
+       verifyGCInfo(t, "bss Complex", &bssComplex, nonStackInfo(infoComplex()))
+       verifyGCInfo(t, "bss string", &bssString, nonStackInfo(infoString))
+       verifyGCInfo(t, "bss eface", &bssEface, nonStackInfo(infoEface))
+
+       verifyGCInfo(t, "data ScalarPtr", &dataScalarPtr, nonStackInfo(infoScalarPtr))
+       verifyGCInfo(t, "data PtrScalar", &dataPtrScalar, nonStackInfo(infoPtrScalar))
+       verifyGCInfo(t, "data Complex", &dataComplex, nonStackInfo(infoComplex()))
+       verifyGCInfo(t, "data string", &dataString, nonStackInfo(infoString))
+       verifyGCInfo(t, "data eface", &dataEface, nonStackInfo(infoEface))
+
+       verifyGCInfo(t, "stack ScalarPtr", new(ScalarPtr), infoScalarPtr)
+       verifyGCInfo(t, "stack PtrScalar", new(PtrScalar), infoPtrScalar)
+       verifyGCInfo(t, "stack Complex", new(Complex), infoComplex())
+       verifyGCInfo(t, "stack string", new(string), infoString)
+       verifyGCInfo(t, "stack eface", new(interface{}), infoEface)
 
        for i := 0; i < 3; i++ {
-               verifyGCInfo(t, "heap ScalarPtr", escape(new(ScalarPtr)), infoScalarPtr)
-               verifyGCInfo(t, "heap PtrScalar", escape(new(PtrScalar)), infoPtrScalar)
-               verifyGCInfo(t, "heap Complex", escape(new(Complex)), infoComplex())
-               verifyGCInfo(t, "heap string", escape(new(string)), infoString)
-               verifyGCInfo(t, "heap eface", escape(new(interface{})), infoEface)
+               verifyGCInfo(t, "heap ScalarPtr", escape(new(ScalarPtr)), nonStackInfo(infoScalarPtr))
+               verifyGCInfo(t, "heap PtrScalar", escape(new(PtrScalar)), nonStackInfo(infoPtrScalar))
+               verifyGCInfo(t, "heap Complex", escape(new(Complex)), nonStackInfo(infoComplex()))
+               verifyGCInfo(t, "heap string", escape(new(string)), nonStackInfo(infoString))
+               verifyGCInfo(t, "heap eface", escape(new(interface{})), nonStackInfo(infoEface))
        }
 
 }
@@ -46,6 +52,20 @@ func verifyGCInfo(t *testing.T, name string, p interface{}, mask0 []byte) {
        }
 }
 
+func nonStackInfo(mask []byte) []byte {
+       // BitsDead is replaced with BitsScalar everywhere except stacks.
+       mask1 := make([]byte, len(mask))
+       mw := false
+       for i, v := range mask {
+               if !mw && v == BitsDead {
+                       v = BitsScalar
+               }
+               mw = !mw && v == BitsMultiWord
+               mask1[i] = v
+       }
+       return mask1
+}
+
 var gcinfoSink interface{}
 
 func escape(p interface{}) interface{} {
@@ -106,20 +126,20 @@ func infoComplex() []byte {
                return []byte{
                        BitsPointer, BitsScalar, BitsScalar, BitsScalar,
                        BitsScalar, BitsScalar, BitsMultiWord, BitsSlice,
-                       BitsScalar, BitsScalar, BitsScalar, BitsScalar,
+                       BitsDead, BitsScalar, BitsScalar, BitsScalar,
                        BitsScalar, BitsMultiWord, BitsString,
                }
        case "amd64":
                return []byte{
                        BitsPointer, BitsScalar, BitsScalar, BitsScalar,
-                       BitsMultiWord, BitsSlice, BitsScalar, BitsScalar,
+                       BitsMultiWord, BitsSlice, BitsDead, BitsScalar,
                        BitsScalar, BitsScalar, BitsMultiWord, BitsString,
                }
        case "amd64p32":
                return []byte{
                        BitsPointer, BitsScalar, BitsScalar, BitsScalar,
                        BitsScalar, BitsScalar, BitsMultiWord, BitsSlice,
-                       BitsScalar, BitsScalar, BitsScalar, BitsScalar,
+                       BitsDead, BitsScalar, BitsScalar, BitsDead,
                        BitsScalar, BitsScalar, BitsMultiWord, BitsString,
                }
        default:
index 6e307bfce4719e04f4952bda480ad5969aac757a..59dfd51e65c18f9661b18b19a41e2fd565f065d9 100644 (file)
@@ -2087,7 +2087,7 @@ runtime·getgcmask(byte *p, Type *t, byte **mask, uintptr *len)
                *mask = runtime·mallocgc(*len, nil, 0);
                for(i = 0; i < n; i += PtrSize) {
                        off = (p+i-frame.varp+size)/PtrSize;
-                       bits = (bv.data[off/PointersPerByte] >> ((off%PointersPerByte)*BitsPerPointer))&BitsMask;
+                       bits = (bv.data[off*BitsPerPointer/32] >> ((off*BitsPerPointer)%32))&BitsMask;
                        (*mask)[i/PtrSize] = bits;
                }
        }