summaryrefslogtreecommitdiff
path: root/src/reflect/type.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/reflect/type.go')
-rw-r--r--src/reflect/type.go62
1 files changed, 38 insertions, 24 deletions
diff --git a/src/reflect/type.go b/src/reflect/type.go
index f099546d2..26328e74b 100644
--- a/src/reflect/type.go
+++ b/src/reflect/type.go
@@ -498,7 +498,7 @@ func (t *uncommonType) Method(i int) (m Method) {
mt := p.typ
m.Type = mt
fn := unsafe.Pointer(&p.tfn)
- m.Func = Value{mt, fn, 0, fl}
+ m.Func = Value{mt, fn, fl}
m.Index = i
return
}
@@ -1514,20 +1514,32 @@ 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 embed directly in t.gc.
- prog = (*[1 << 30]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(bitsPointer)
+ gc.appendWord(bitsPointer)
+ case Struct:
+ c := t.NumField()
+ for i := 0; i < c; i++ {
+ gc.appendProg(t.Field(i).Type.common())
+ }
}
}
@@ -1562,7 +1574,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 +1585,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 +1635,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
@@ -1786,7 +1801,7 @@ func funcLayout(t *rtype, rcvr *rtype) (frametype *rtype, argSize, retOffset uin
// Reflect uses the "interface" calling convention for
// methods, where receivers take one word of argument
// space no matter how big they actually are.
- if !isDirectIface(rcvr) {
+ if ifaceIndir(rcvr) {
// we pass a pointer to the receiver.
gc.append(bitsPointer)
stack.append2(bitsPointer)
@@ -1821,7 +1836,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 + ")"
@@ -1844,9 +1858,9 @@ func funcLayout(t *rtype, rcvr *rtype) (frametype *rtype, argSize, retOffset uin
return x, argSize, retOffset, stack
}
-// isDirectIface reports whether t is stored directly in an interface value.
-func isDirectIface(t *rtype) bool {
- return t.kind&kindDirectIface != 0
+// ifaceIndir reports whether t is stored indirectly in an interface value.
+func ifaceIndir(t *rtype) bool {
+ return t.kind&kindDirectIface == 0
}
// Layout matches runtime.BitVector (well enough).