From: Dmitriy Vyukov Date: Fri, 15 Aug 2014 18:36:12 +0000 (+0400) Subject: runtime: fix getgcmask X-Git-Tag: go1.4beta1~820 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=c5e648d684312b979e243077f909a798adbf6e5b;p=gostls13.git runtime: fix getgcmask 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 --- diff --git a/src/pkg/runtime/gcinfo_test.go b/src/pkg/runtime/gcinfo_test.go index 6afa9a4e2b..892484ea6f 100644 --- a/src/pkg/runtime/gcinfo_test.go +++ b/src/pkg/runtime/gcinfo_test.go @@ -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: diff --git a/src/pkg/runtime/mgc0.c b/src/pkg/runtime/mgc0.c index 6e307bfce4..59dfd51e65 100644 --- a/src/pkg/runtime/mgc0.c +++ b/src/pkg/runtime/mgc0.c @@ -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; } }