]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1.4] reflect: Fix reflect.funcLayout. The GC bitmap has two bits per
authorRuss Cox <rsc@golang.org>
Mon, 1 Dec 2014 16:18:47 +0000 (11:18 -0500)
committerRuss Cox <rsc@golang.org>
Mon, 1 Dec 2014 16:18:47 +0000 (11:18 -0500)
««« CL 182160043 / 321d04dea9d6
reflect: Fix reflect.funcLayout.  The GC bitmap has two bits per
pointer, not one.

Fixes #9179

LGTM=iant, rsc
R=golang-codereviews, iant, rsc
CC=golang-codereviews
https://golang.org/cl/182160043
»»»

TBR=khr
CC=golang-codereviews
https://golang.org/cl/180440044

src/reflect/all_test.go
src/reflect/export_test.go
src/reflect/type.go

index 268a9e319f6758adfc0cac38cdb179f64c0795a0..7a01c95d86e8f79f5de863a048952d1528b836b8 100644 (file)
@@ -4055,3 +4055,104 @@ func TestLargeGCProg(t *testing.T) {
        fv := ValueOf(func([256]*byte) {})
        fv.Call([]Value{ValueOf([256]*byte{})})
 }
+
+// Issue 9179.
+func TestCallGC(t *testing.T) {
+       f := func(a, b, c, d, e string) {
+       }
+       g := func(in []Value) []Value {
+               runtime.GC()
+               return nil
+       }
+       typ := ValueOf(f).Type()
+       f2 := MakeFunc(typ, g).Interface().(func(string, string, string, string, string))
+       f2("four", "five5", "six666", "seven77", "eight888")
+}
+
+type funcLayoutTest struct {
+       rcvr, t            Type
+       argsize, retOffset uintptr
+       stack              []byte
+}
+
+var funcLayoutTests []funcLayoutTest
+
+func init() {
+       var argAlign = PtrSize
+       if runtime.GOARCH == "amd64p32" {
+               argAlign = 2 * PtrSize
+       }
+       roundup := func(x uintptr, a uintptr) uintptr {
+               return (x + a - 1) / a * a
+       }
+
+       funcLayoutTests = append(funcLayoutTests,
+               funcLayoutTest{
+                       nil,
+                       ValueOf(func(a, b string) string { return "" }).Type(),
+                       4 * PtrSize,
+                       4 * PtrSize,
+                       []byte{BitsPointer, BitsScalar, BitsPointer},
+               })
+
+       var r []byte
+       if PtrSize == 4 {
+               r = []byte{BitsScalar, BitsScalar, BitsScalar, BitsPointer}
+       } else {
+               r = []byte{BitsScalar, BitsScalar, BitsPointer}
+       }
+       funcLayoutTests = append(funcLayoutTests,
+               funcLayoutTest{
+                       nil,
+                       ValueOf(func(a, b, c uint32, p *byte, d uint16) {}).Type(),
+                       roundup(3*4, PtrSize) + PtrSize + 2,
+                       roundup(roundup(3*4, PtrSize)+PtrSize+2, argAlign),
+                       r,
+               })
+
+       funcLayoutTests = append(funcLayoutTests,
+               funcLayoutTest{
+                       nil,
+                       ValueOf(func(a map[int]int, b uintptr, c interface{}) {}).Type(),
+                       4 * PtrSize,
+                       4 * PtrSize,
+                       []byte{BitsPointer, BitsScalar, BitsPointer, BitsPointer},
+               })
+
+       type S struct {
+               a, b uintptr
+               c, d *byte
+       }
+       funcLayoutTests = append(funcLayoutTests,
+               funcLayoutTest{
+                       nil,
+                       ValueOf(func(a S) {}).Type(),
+                       4 * PtrSize,
+                       4 * PtrSize,
+                       []byte{BitsScalar, BitsScalar, BitsPointer, BitsPointer},
+               })
+
+       funcLayoutTests = append(funcLayoutTests,
+               funcLayoutTest{
+                       ValueOf((*byte)(nil)).Type(),
+                       ValueOf(func(a uintptr, b *int) {}).Type(),
+                       3 * PtrSize,
+                       roundup(3*PtrSize, argAlign),
+                       []byte{BitsPointer, BitsScalar, BitsPointer},
+               })
+}
+
+func TestFuncLayout(t *testing.T) {
+       for _, lt := range funcLayoutTests {
+               _, argsize, retOffset, stack := FuncLayout(lt.t, lt.rcvr)
+               if argsize != lt.argsize {
+                       t.Errorf("funcLayout(%v, %v).argsize=%d, want %d", lt.t, lt.rcvr, argsize, lt.argsize)
+               }
+               if retOffset != lt.retOffset {
+                       t.Errorf("funcLayout(%v, %v).retOffset=%d, want %d", lt.t, lt.rcvr, retOffset, lt.retOffset)
+               }
+               if !bytes.Equal(stack, lt.stack) {
+                       t.Errorf("funcLayout(%v, %v).stack=%v, want %v", lt.t, lt.rcvr, stack, lt.stack)
+               }
+       }
+}
index 0778ad37f5c0526ba4026df49901d167bd0c5a2f..caaf51a50f6118adc0ed9adb127fb74e30cd585e 100644 (file)
@@ -17,3 +17,22 @@ func IsRO(v Value) bool {
 
 var ArrayOf = arrayOf
 var CallGC = &callGC
+
+const PtrSize = ptrSize
+const BitsPointer = bitsPointer
+const BitsScalar = bitsScalar
+
+func FuncLayout(t Type, rcvr Type) (frametype Type, argSize, retOffset uintptr, stack []byte) {
+       var ft *rtype
+       var s *bitVector
+       if rcvr != nil {
+               ft, argSize, retOffset, s = funcLayout(t.(*rtype), rcvr.(*rtype))
+       } else {
+               ft, argSize, retOffset, s = funcLayout(t.(*rtype), nil)
+       }
+       frametype = ft
+       for i := uint32(0); i < s.n; i += 2 {
+               stack = append(stack, s.data[i/8]>>(i%8)&3)
+       }
+       return
+}
index 572e611fa9d122227e620c4c9e4778ecaf06ca49..c0ddfcad0ad1f31266435564387147376187e338 100644 (file)
@@ -1894,14 +1894,14 @@ func addTypeBits(bv *bitVector, offset *uintptr, t *rtype) {
        switch Kind(t.kind & kindMask) {
        case Chan, Func, Map, Ptr, Slice, String, UnsafePointer:
                // 1 pointer at start of representation
-               for bv.n < uint32(*offset/uintptr(ptrSize)) {
+               for bv.n < 2*uint32(*offset/uintptr(ptrSize)) {
                        bv.append2(bitsScalar)
                }
                bv.append2(bitsPointer)
 
        case Interface:
                // 2 pointers
-               for bv.n < uint32(*offset/uintptr(ptrSize)) {
+               for bv.n < 2*uint32(*offset/uintptr(ptrSize)) {
                        bv.append2(bitsScalar)
                }
                bv.append2(bitsPointer)