mirror of
https://github.com/golang/go
synced 2024-11-19 05:44:40 -07:00
reflect: generated unrolled GC bitmask directly
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
This commit is contained in:
parent
7c74850d76
commit
3cf9acccae
@ -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{})})
|
||||
}
|
||||
|
@ -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 + ")"
|
||||
|
Loading…
Reference in New Issue
Block a user