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
diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go
index 268a9e3..7a01c95 100644
--- a/src/reflect/all_test.go
+++ b/src/reflect/all_test.go
@@ -4055,3 +4055,104 @@
 	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)
+		}
+	}
+}
diff --git a/src/reflect/export_test.go b/src/reflect/export_test.go
index 0778ad3..caaf51a 100644
--- a/src/reflect/export_test.go
+++ b/src/reflect/export_test.go
@@ -17,3 +17,22 @@
 
 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
+}
diff --git a/src/reflect/type.go b/src/reflect/type.go
index 572e611..c0ddfca 100644
--- a/src/reflect/type.go
+++ b/src/reflect/type.go
@@ -1894,14 +1894,14 @@
 	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)