]> Cypherpunks repositories - gostls13.git/commitdiff
reflect: generated unrolled GC bitmask directly
authorIan Lance Taylor <iant@golang.org>
Mon, 13 Oct 2014 17:01:34 +0000 (10:01 -0700)
committerIan Lance Taylor <iant@golang.org>
Mon, 13 Oct 2014 17:01:34 +0000 (10:01 -0700)
The code for a generated type is already generating an
unrolled GC bitmask.  Rather than unrolling the the source
type bitmasks and copying them, just generate the required
bitmask directly.  Don't mark it as an unrolled GC program,
since there is no need to do so.

Fixes #8917.

LGTM=rsc
R=dvyukov, rsc
CC=golang-codereviews
https://golang.org/cl/156930044

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

index f0cd6a41280977b2683746d59479a2e57da89370..6bdc9be9dd3b185af4708190e668ed9c68137b9f 100644 (file)
@@ -4018,3 +4018,9 @@ func TestInvalid(t *testing.T) {
                t.Errorf("field elem: IsValid=%v, Kind=%v, want false, Invalid", v.IsValid(), v.Kind())
        }
 }
+
+// Issue 8917.
+func TestLargeGCProg(t *testing.T) {
+       fv := ValueOf(func([256]*byte) {})
+       fv.Call([]Value{ValueOf([256]*byte{})})
+}
index a36c0ba604d9f728355ea48077bcbf8ae77ca6b5..821b60412ee0e662a675f73f65fdc38700a54993 100644 (file)
@@ -1514,20 +1514,36 @@ func (gc *gcProg) appendProg(t *rtype) {
                gc.size += t.size
                return
        }
-       nptr := t.size / unsafe.Sizeof(uintptr(0))
-       var prog []byte
-       if t.kind&kindGCProg != 0 {
-               // Ensure that the runtime has unrolled GC program.
-               // TODO(rsc): Do not allocate.
-               unsafe_New(t)
-               // 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 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))
+       switch t.Kind() {
+       default:
+               panic("reflect: non-pointer type marked as having pointers")
+       case Ptr, UnsafePointer, Chan, Func, Map:
+               gc.appendWord(bitsPointer)
+       case Slice:
+               gc.appendWord(bitsPointer)
+               gc.appendWord(bitsScalar)
+               gc.appendWord(bitsScalar)
+       case String:
+               gc.appendWord(bitsPointer)
+               gc.appendWord(bitsScalar)
+       case Array:
+               c := t.Len()
+               e := t.Elem().common()
+               for i := 0; i < c; i++ {
+                       gc.appendProg(e)
+               }
+       case Interface:
+               gc.appendWord(bitsMultiWord)
+               if t.NumMethod() == 0 {
+                       gc.appendWord(bitsEface)
+               } else {
+                       gc.appendWord(bitsIface)
+               }
+       case Struct:
+               c := t.NumField()
+               for i := 0; i < c; i++ {
+                       gc.appendProg(t.Field(i).Type.common())
+               }
        }
 }
 
@@ -1562,7 +1578,6 @@ func (gc *gcProg) finalize() unsafe.Pointer {
                        gc.appendWord(extractGCWord(gc.gc, i))
                }
        }
-       gc.gc = append([]byte{1}, gc.gc...) // prepend unroll flag
        return unsafe.Pointer(&gc.gc[0])
 }
 
@@ -1574,9 +1589,14 @@ func (gc *gcProg) align(a uintptr) {
        gc.size = align(gc.size, a)
 }
 
+// These constants must stay in sync with ../runtime/mgc0.h.
 const (
-       bitsScalar  = 1
-       bitsPointer = 2
+       bitsScalar    = 1
+       bitsPointer   = 2
+       bitsMultiWord = 3
+
+       bitsIface = 2
+       bitsEface = 3
 )
 
 // Make sure these routines stay in sync with ../../runtime/hashmap.go!
@@ -1619,7 +1639,6 @@ func bucketOf(ktyp, etyp *rtype) *rtype {
        b := new(rtype)
        b.size = gc.size
        b.gc[0] = gc.finalize()
-       b.kind |= kindGCProg
        s := "bucket(" + *ktyp.string + "," + *etyp.string + ")"
        b.string = &s
        return b
@@ -1821,7 +1840,6 @@ func funcLayout(t *rtype, rcvr *rtype) (frametype *rtype, argSize, retOffset uin
        x := new(rtype)
        x.size = gc.size
        x.gc[0] = gc.finalize()
-       x.kind |= kindGCProg
        var s string
        if rcvr != nil {
                s = "methodargs(" + *rcvr.string + ")(" + *t.string + ")"