// uncommonType
// [2]*rtype // [0] is in, [1] is out
// }
-type funcType struct {
- rtype
- InCount uint16
- OutCount uint16 // top bit is set if last input parameter is ...
-}
+type funcType = abi.FuncType
// interfaceType represents an interface type.
type interfaceType struct {
fl := flag(Func)
mtyp := t.typeOff(p.Mtyp)
ft := (*funcType)(unsafe.Pointer(mtyp))
- in := make([]Type, 0, 1+len(ft.in()))
+ in := make([]Type, 0, 1+ft.NumIn())
in = append(in, t)
- for _, arg := range ft.in() {
- in = append(in, arg)
+ for _, arg := range ft.InSlice() {
+ in = append(in, toRType(arg))
}
- out := make([]Type, 0, len(ft.out()))
- for _, ret := range ft.out() {
- out = append(out, ret)
+ out := make([]Type, 0, ft.NumOut())
+ for _, ret := range ft.OutSlice() {
+ out = append(out, toRType(ret))
}
mt := FuncOf(in, out, ft.IsVariadic())
m.Type = mt
if t.Kind() != Chan {
panic("reflect: ChanDir of non-chan type " + t.String())
}
- tt := (*chanType)(unsafe.Pointer(t))
+ tt := (*abi.ChanType)(unsafe.Pointer(t))
return ChanDir(tt.Dir)
}
-func (t *rtype) IsVariadic() bool {
- if t.Kind() != Func {
- panic("reflect: IsVariadic of non-func type " + t.String())
- }
- tt := (*funcType)(unsafe.Pointer(t))
- return tt.OutCount&(1<<15) != 0
-}
-
func toRType(t *abi.Type) *rtype {
return (*rtype)(unsafe.Pointer(t))
}
return tt.FieldByNameFunc(match)
}
-func (t *rtype) In(i int) Type {
- if t.Kind() != Func {
- panic("reflect: In of non-func type " + t.String())
- }
- tt := (*funcType)(unsafe.Pointer(t))
- return toType(tt.in()[i])
-}
-
func (t *rtype) Key() Type {
if t.Kind() != Map {
panic("reflect: Key of non-map type " + t.String())
return len(tt.Fields)
}
+func (t *rtype) In(i int) Type {
+ if t.Kind() != Func {
+ panic("reflect: In of non-func type " + t.String())
+ }
+ tt := (*abi.FuncType)(unsafe.Pointer(t))
+ return toType(toRType(tt.InSlice()[i]))
+}
+
func (t *rtype) NumIn() int {
if t.Kind() != Func {
panic("reflect: NumIn of non-func type " + t.String())
}
- tt := (*funcType)(unsafe.Pointer(t))
- return int(tt.InCount)
+ tt := (*abi.FuncType)(unsafe.Pointer(t))
+ return tt.NumIn()
}
func (t *rtype) NumOut() int {
if t.Kind() != Func {
panic("reflect: NumOut of non-func type " + t.String())
}
- tt := (*funcType)(unsafe.Pointer(t))
- return len(tt.out())
+ tt := (*abi.FuncType)(unsafe.Pointer(t))
+ return tt.NumOut()
}
func (t *rtype) Out(i int) Type {
if t.Kind() != Func {
panic("reflect: Out of non-func type " + t.String())
}
- tt := (*funcType)(unsafe.Pointer(t))
- return toType(tt.out()[i])
-}
-
-func (t *funcType) in() []*rtype {
- uadd := unsafe.Sizeof(*t)
- if t.t.TFlag&abi.TFlagUncommon != 0 {
- uadd += unsafe.Sizeof(uncommonType{})
- }
- if t.InCount == 0 {
- return nil
- }
- return (*[1 << 20]*rtype)(add(unsafe.Pointer(t), uadd, "t.inCount > 0"))[:t.InCount:t.InCount]
+ tt := (*abi.FuncType)(unsafe.Pointer(t))
+ return toType(toRType(tt.OutSlice()[i]))
}
-func (t *funcType) out() []*rtype {
- uadd := unsafe.Sizeof(*t)
- if t.t.TFlag&abi.TFlagUncommon != 0 {
- uadd += unsafe.Sizeof(uncommonType{})
- }
- outCount := t.OutCount & (1<<15 - 1)
- if outCount == 0 {
- return nil
+func (t *rtype) IsVariadic() bool {
+ if t.Kind() != Func {
+ panic("reflect: IsVariadic of non-func type " + t.String())
}
- return (*[1 << 20]*rtype)(add(unsafe.Pointer(t), uadd, "outCount > 0"))[t.InCount : t.InCount+outCount : t.InCount+outCount]
+ tt := (*abi.FuncType)(unsafe.Pointer(t))
+ return tt.IsVariadic()
}
// add returns p+x.
return false
}
for i := 0; i < t.NumIn(); i++ {
- if !haveIdenticalType(t.In(i), v.In(i), cmpTags) {
+ if !haveIdenticalType(toRType(t.In(i)), toRType(v.In(i)), cmpTags) {
return false
}
}
for i := 0; i < t.NumOut(); i++ {
- if !haveIdenticalType(t.Out(i), v.Out(i), cmpTags) {
+ if !haveIdenticalType(toRType(t.Out(i)), toRType(v.Out(i)), cmpTags) {
return false
}
}
hash = fnv1(hash, byte(t.t.Hash>>24), byte(t.t.Hash>>16), byte(t.t.Hash>>8), byte(t.t.Hash))
}
- ft.t.TFlag = 0
- ft.t.Hash = hash
+ ft.TFlag = 0
+ ft.Hash = hash
ft.InCount = uint16(len(in))
ft.OutCount = uint16(len(out))
if variadic {
// Look in cache.
if ts, ok := funcLookupCache.m.Load(hash); ok {
for _, t := range ts.([]*rtype) {
- if haveIdenticalUnderlyingType(&ft.rtype, t, true) {
+ if haveIdenticalUnderlyingType(toRType(&ft.Type), t, true) {
return t
}
}
defer funcLookupCache.Unlock()
if ts, ok := funcLookupCache.m.Load(hash); ok {
for _, t := range ts.([]*rtype) {
- if haveIdenticalUnderlyingType(&ft.rtype, t, true) {
+ if haveIdenticalUnderlyingType(toRType(&ft.Type), t, true) {
return t
}
}
// Look in known types for the same string representation.
str := funcStr(ft)
for _, tt := range typesByString(str) {
- if haveIdenticalUnderlyingType(&ft.rtype, tt, true) {
+ if haveIdenticalUnderlyingType(toRType(&ft.Type), tt, true) {
return addToCache(tt)
}
}
// Populate the remaining fields of ft and store in cache.
- ft.t.Str = resolveReflectName(newName(str, "", false, false))
- ft.t.PtrToThis = 0
- return addToCache(&ft.rtype)
+ ft.Str = resolveReflectName(newName(str, "", false, false))
+ ft.PtrToThis = 0
+ return addToCache(toRType(&ft.Type))
+}
+func stringFor(t *abi.Type) string {
+ return toRType(t).String()
}
// funcStr builds a string representation of a funcType.
func funcStr(ft *funcType) string {
repr := make([]byte, 0, 64)
repr = append(repr, "func("...)
- for i, t := range ft.in() {
+ for i, t := range ft.InSlice() {
if i > 0 {
repr = append(repr, ", "...)
}
repr = append(repr, "..."...)
repr = append(repr, (*sliceType)(unsafe.Pointer(t)).Elem.String()...)
} else {
- repr = append(repr, t.String()...)
+ repr = append(repr, stringFor(t)...)
}
}
repr = append(repr, ')')
- out := ft.out()
+ out := ft.OutSlice()
if len(out) == 1 {
repr = append(repr, ' ')
} else if len(out) > 1 {
if i > 0 {
repr = append(repr, ", "...)
}
- repr = append(repr, t.String()...)
+ repr = append(repr, stringFor(t)...)
}
if len(out) > 1 {
repr = append(repr, ')')
// Currently, that's just size and the GC program. We also fill in
// the name for possible debugging use.
func funcLayout(t *funcType, rcvr *rtype) (frametype *rtype, framePool *sync.Pool, abid abiDesc) {
- if t.Kind() != Func {
- panic("reflect: funcLayout of non-func type " + t.String())
+ if t.Kind() != abi.Func {
+ panic("reflect: funcLayout of non-func type " + stringFor(&t.Type))
}
if rcvr != nil && rcvr.Kind() == Interface {
panic("reflect: funcLayout with interface receiver " + rcvr.String())
var s string
if rcvr != nil {
- s = "methodargs(" + rcvr.String() + ")(" + t.String() + ")"
+ s = "methodargs(" + rcvr.String() + ")(" + stringFor(&t.Type) + ")"
} else {
- s = "funcargs(" + t.String() + ")"
+ s = "funcargs(" + stringFor(&t.Type) + ")"
}
x.t.Str = resolveReflectName(newName(s, "", false, false))
}
}
for i := 0; i < n; i++ {
- if xt, targ := in[i].Type(), t.In(i); !xt.AssignableTo(targ) {
- panic("reflect: " + op + " using " + xt.String() + " as type " + targ.String())
+ if xt, targ := in[i].Type(), t.In(i); !xt.AssignableTo(toRType(targ)) {
+ panic("reflect: " + op + " using " + xt.String() + " as type " + stringFor(targ))
}
}
if !isSlice && isVariadic {
// prepare slice for remaining values
m := len(in) - n
- slice := MakeSlice(t.In(n), m, m)
- elem := t.In(n).Elem()
+ slice := MakeSlice(toRType(t.In(n)), m, m)
+ elem := toRType(t.In(n)).Elem() // FIXME cast to slice type and Elem()
for i := 0; i < m; i++ {
x := in[n+i]
if xt := x.Type(); !xt.AssignableTo(elem) {
frameSize := frametype.Size()
if debugReflectCall {
- println("reflect.call", t.String())
+ println("reflect.call", stringFor(&t.Type))
abid.dump()
}
// Handle arguments.
for i, v := range in {
v.mustBeExported()
- targ := t.In(i).(*rtype)
+ targ := toRType(t.In(i))
// TODO(mknyszek): Figure out if it's possible to get some
// scratch space for this assignment check. Previously, it
// was possible to use space in the argument frame.
if tv.Size() == 0 {
// For zero-sized return value, args+off may point to the next object.
// In this case, return the zero value instead.
- ret[i] = Zero(tv)
+ ret[i] = Zero(toRType(tv))
continue
}
steps := abid.ret.stepsForValue(i)
// allocated, the entire value is according to the ABI. So
// just make an indirection into the allocated frame.
fl := flagIndir | flag(tv.Kind())
- ret[i] = Value{tv.common(), add(stackArgs, st.stkOff, "tv.Size() != 0"), fl}
+ ret[i] = Value{toRType(tv), add(stackArgs, st.stkOff, "tv.Size() != 0"), fl}
// Note: this does introduce false sharing between results -
// if any result is live, they are all live.
// (And the space for the args is live as well, but as we've
}
// Handle pointers passed in registers.
- if !ifaceIndir(tv.common()) {
+ if !ifaceIndir(toRType(tv)) {
// Pointer-valued data gets put directly
// into v.ptr.
if steps[0].kind != abiStepPointer {
- print("kind=", steps[0].kind, ", type=", tv.String(), "\n")
+ print("kind=", steps[0].kind, ", type=", stringFor(tv), "\n")
panic("mismatch between ABI description and types")
}
- ret[i] = Value{tv.common(), regArgs.Ptrs[steps[0].ireg], flag(tv.Kind())}
+ ret[i] = Value{toRType(tv), regArgs.Ptrs[steps[0].ireg], flag(tv.Kind())}
continue
}
// additional space to the allocated stack frame and storing the
// register-allocated return values into the allocated stack frame and
// referring there in the resulting Value.
- s := unsafe_New(tv.common())
+ s := unsafe_New(toRType(tv))
for _, st := range steps {
switch st.kind {
case abiStepIntReg:
panic("unknown ABI part kind")
}
}
- ret[i] = Value{tv.common(), s, flagIndir | flag(tv.Kind())}
+ ret[i] = Value{toRType(tv), s, flagIndir | flag(tv.Kind())}
}
}
// Copy arguments into Values.
ptr := frame
in := make([]Value, 0, int(ftyp.InCount))
- for i, typ := range ftyp.in() {
+ for i, typ := range ftyp.InSlice() {
+ typ := toRType(typ) // FIXME cleanup this loop body
if typ.Size() == 0 {
in = append(in, Zero(typ))
continue
// Copy results back into argument frame and register space.
if numOut > 0 {
- for i, typ := range ftyp.out() {
+ for i, typ := range ftyp.OutSlice() {
v := out[i]
if v.typ == nil {
panic("reflect: function created by MakeFunc using " + funcName(f) +
// We must clear the destination before calling assignTo,
// in case assignTo writes (with memory barriers) to the
// target location used as scratch space. See issue 39541.
- v = v.assignTo("reflect.MakeFunc", typ, nil)
+ v = v.assignTo("reflect.MakeFunc", toRType(typ), nil)
stepsLoop:
for _, st := range abid.ret.stepsForValue(i) {
switch st.kind {
}
// Translate the rest of the arguments.
- for i, t := range valueFuncType.in() {
+ for i, t := range valueFuncType.InSlice() {
valueSteps := valueABI.call.stepsForValue(i)
methodSteps := methodABI.call.stepsForValue(i + 1)
if vStep.size != mStep.size {
panic("method ABI and value ABI do not align")
}
- typedmemmove(t,
+ typedmemmove(toRType(t),
add(methodFrame, mStep.stkOff, "precomputed stack offset"),
add(valueFrame, vStep.stkOff, "precomputed stack offset"))
continue