isddd = t1.Isddd
dtypesym(t1.Type)
}
-
for t1 := getoutargx(t).Type; t1 != nil; t1 = t1.Down {
dtypesym(t1.Type)
}
ot = dcommontype(s, ot, t)
- ot = duint8(s, ot, uint8(obj.Bool2int(isddd)))
-
- // two slice headers: in and out.
- ot = int(Rnd(int64(ot), int64(Widthptr)))
-
- ot = dsymptr(s, ot, s, ot+2*(Widthptr+2*Widthint)+uncommonSize(t))
- n := t.Thistuple + t.Intuple
- ot = duintxx(s, ot, uint64(n), Widthint)
- ot = duintxx(s, ot, uint64(n), Widthint)
- ot = dsymptr(s, ot, s, ot+1*(Widthptr+2*Widthint)+uncommonSize(t)+n*Widthptr)
- ot = duintxx(s, ot, uint64(t.Outtuple), Widthint)
- ot = duintxx(s, ot, uint64(t.Outtuple), Widthint)
-
- dataAdd := 0
- for t1 := getthisx(t).Type; t1 != nil; t1 = t1.Down {
- dataAdd += Widthptr
+ inCount := t.Thistuple + t.Intuple
+ outCount := t.Outtuple
+ if isddd {
+ outCount |= 1 << 15
}
- for t1 := getinargx(t).Type; t1 != nil; t1 = t1.Down {
- dataAdd += Widthptr
- }
- for t1 := getoutargx(t).Type; t1 != nil; t1 = t1.Down {
- dataAdd += Widthptr
+ ot = duint16(s, ot, uint16(inCount))
+ ot = duint16(s, ot, uint16(outCount))
+ if Widthptr == 8 {
+ ot += 4 // align for *rtype
}
+
+ dataAdd := (inCount + outCount) * Widthptr
ot = dextratype(s, ot, t, dataAdd)
- // slice data
+ // Array of rtype pointers follows funcType.
for t1 := getthisx(t).Type; t1 != nil; t1 = t1.Down {
ot = dsymptr(s, ot, dtypesym(t1.Type), 0)
- n++
}
for t1 := getinargx(t).Type; t1 != nil; t1 = t1.Down {
ot = dsymptr(s, ot, dtypesym(t1.Type), 0)
- n++
}
for t1 := getoutargx(t).Type; t1 != nil; t1 = t1.Down {
ot = dsymptr(s, ot, dtypesym(t1.Type), 0)
- n++
}
case TINTER:
}
// Type.FuncType.dotdotdot
-func decodetype_funcdotdotdot(s *LSym) int {
- return int(s.P[commonsize()])
+func decodetype_funcdotdotdot(s *LSym) bool {
+ return uint16(decode_inuxi(s.P[commonsize()+2:], 2))&(1<<15) != 0
}
-// Type.FuncType.in.length
+// Type.FuncType.inCount
func decodetype_funcincount(s *LSym) int {
- return int(decode_inuxi(s.P[commonsize()+2*Thearch.Ptrsize:], Thearch.Intsize))
+ return int(decode_inuxi(s.P[commonsize():], 2))
}
func decodetype_funcoutcount(s *LSym) int {
- return int(decode_inuxi(s.P[commonsize()+3*Thearch.Ptrsize+2*Thearch.Intsize:], Thearch.Intsize))
+ return int(uint16(decode_inuxi(s.P[commonsize()+2:], 2)) & (1<<15 - 1))
}
func decodetype_funcintype(s *LSym, i int) *LSym {
- r := decode_reloc(s, int32(commonsize())+int32(Thearch.Ptrsize))
- if r == nil {
- return nil
+ uadd := commonsize() + 4
+ if Thearch.Ptrsize == 8 {
+ uadd += 4
+ }
+ if decodetype_hasUncommon(s) {
+ uadd += uncommonSize()
}
- return decode_reloc_sym(r.Sym, int32(r.Add+int64(int32(i)*int32(Thearch.Ptrsize))))
+ return decode_reloc_sym(s, int32(uadd+i*Thearch.Ptrsize))
}
func decodetype_funcouttype(s *LSym, i int) *LSym {
- r := decode_reloc(s, int32(commonsize())+2*int32(Thearch.Ptrsize)+2*int32(Thearch.Intsize))
- if r == nil {
- return nil
- }
- return decode_reloc_sym(r.Sym, int32(r.Add+int64(int32(i)*int32(Thearch.Ptrsize))))
+ return decodetype_funcintype(s, i+decodetype_funcincount(s))
}
// Type.StructType.fields.Slice::length
newrefattr(fld, DW_AT_type, defgotype(s))
}
- if decodetype_funcdotdotdot(gotype) != 0 {
+ if decodetype_funcdotdotdot(gotype) {
newdie(die, DW_ABRV_DOTDOTDOT, "...")
}
nfields = decodetype_funcoutcount(gotype)
}
// funcType represents a function type.
+//
+// A *rtype for each in and out parameter is stored in an array that
+// directly follows the funcType (and possibly its uncommonType). So
+// a function type with one method, one input, and one output is:
+//
+// struct {
+// funcType
+// uncommonType
+// [2]*rtype // [0] is in, [1] is out
+// }
type funcType struct {
- rtype `reflect:"func"`
- dotdotdot bool // last input parameter is ...
- in []*rtype // input parameter types
- out []*rtype // output parameter types
+ rtype `reflect:"func"`
+ inCount uint16
+ outCount uint16 // top bit is set if last input parameter is ...
}
// imethod represents a method on an interface type
panic("reflect: IsVariadic of non-func type")
}
tt := (*funcType)(unsafe.Pointer(t))
- return tt.dotdotdot
+ return tt.outCount&(1<<15) != 0
}
func (t *rtype) Elem() Type {
panic("reflect: In of non-func type")
}
tt := (*funcType)(unsafe.Pointer(t))
- return toType(tt.in[i])
+ return toType(tt.in()[i])
}
func (t *rtype) Key() Type {
panic("reflect: NumIn of non-func type")
}
tt := (*funcType)(unsafe.Pointer(t))
- return len(tt.in)
+ return int(tt.inCount)
}
func (t *rtype) NumOut() int {
panic("reflect: NumOut of non-func type")
}
tt := (*funcType)(unsafe.Pointer(t))
- return len(tt.out)
+ return len(tt.out())
}
func (t *rtype) Out(i int) Type {
panic("reflect: Out of non-func type")
}
tt := (*funcType)(unsafe.Pointer(t))
- return toType(tt.out[i])
+ return toType(tt.out()[i])
+}
+
+func (t *funcType) in() []*rtype {
+ uadd := uintptr(unsafe.Sizeof(*t))
+ if t.tflag&tflagUncommon != 0 {
+ uadd += unsafe.Sizeof(uncommonType{})
+ }
+ return (*[1 << 20]*rtype)(add(unsafe.Pointer(t), uadd))[:t.inCount]
+}
+
+func (t *funcType) out() []*rtype {
+ uadd := uintptr(unsafe.Sizeof(*t))
+ if t.tflag&tflagUncommon != 0 {
+ uadd += unsafe.Sizeof(uncommonType{})
+ }
+ outCount := t.outCount & (1<<15 - 1)
+ return (*[1 << 20]*rtype)(add(unsafe.Pointer(t), uadd))[t.inCount : t.inCount+outCount]
+}
+
+func add(p unsafe.Pointer, x uintptr) unsafe.Pointer {
+ return unsafe.Pointer(uintptr(p) + x)
}
func (d ChanDir) String() string {
case Func:
t := (*funcType)(unsafe.Pointer(T))
v := (*funcType)(unsafe.Pointer(V))
- if t.dotdotdot != v.dotdotdot || len(t.in) != len(v.in) || len(t.out) != len(v.out) {
+ if t.outCount != v.outCount || t.inCount != v.inCount {
return false
}
- for i, typ := range t.in {
- if typ != v.in[i] {
+ for i := 0; i < t.NumIn(); i++ {
+ if t.In(i) != v.In(i) {
return false
}
}
- for i, typ := range t.out {
- if typ != v.out[i] {
+ for i := 0; i < t.NumOut(); i++ {
+ if t.Out(i) != v.Out(i) {
return false
}
}
return cachePut(ckey, &mt.rtype)
}
+type funcTypeFixed4 struct {
+ funcType
+ args [4]*rtype
+}
+type funcTypeFixed8 struct {
+ funcType
+ args [8]*rtype
+}
+type funcTypeFixed16 struct {
+ funcType
+ args [16]*rtype
+}
+type funcTypeFixed32 struct {
+ funcType
+ args [32]*rtype
+}
+type funcTypeFixed64 struct {
+ funcType
+ args [64]*rtype
+}
+type funcTypeFixed128 struct {
+ funcType
+ args [128]*rtype
+}
+
// FuncOf returns the function type with the given argument and result types.
// For example if k represents int and e represents string,
// FuncOf([]Type{k}, []Type{e}, false) represents func(int) string.
// Make a func type.
var ifunc interface{} = (func())(nil)
prototype := *(**funcType)(unsafe.Pointer(&ifunc))
- ft := new(funcType)
+ n := len(in) + len(out)
+
+ var ft *funcType
+ var args []*rtype
+ switch {
+ case n <= 4:
+ fixed := new(funcTypeFixed4)
+ args = fixed.args[:0:len(fixed.args)]
+ ft = &fixed.funcType
+ case n <= 8:
+ fixed := new(funcTypeFixed8)
+ args = fixed.args[:0:len(fixed.args)]
+ ft = &fixed.funcType
+ case n <= 16:
+ fixed := new(funcTypeFixed16)
+ args = fixed.args[:0:len(fixed.args)]
+ ft = &fixed.funcType
+ case n <= 32:
+ fixed := new(funcTypeFixed32)
+ args = fixed.args[:0:len(fixed.args)]
+ ft = &fixed.funcType
+ case n <= 64:
+ fixed := new(funcTypeFixed64)
+ args = fixed.args[:0:len(fixed.args)]
+ ft = &fixed.funcType
+ case n <= 128:
+ fixed := new(funcTypeFixed128)
+ args = fixed.args[:0:len(fixed.args)]
+ ft = &fixed.funcType
+ default:
+ panic("reflect.FuncOf: too many arguments")
+ }
*ft = *prototype
// Build a hash and minimally populate ft.
var hash uint32
- var fin, fout []*rtype
for _, in := range in {
t := in.(*rtype)
- fin = append(fin, t)
+ args = append(args, t)
hash = fnv1(hash, byte(t.hash>>24), byte(t.hash>>16), byte(t.hash>>8), byte(t.hash))
}
if variadic {
hash = fnv1(hash, '.')
for _, out := range out {
t := out.(*rtype)
- fout = append(fout, t)
+ args = append(args, t)
hash = fnv1(hash, byte(t.hash>>24), byte(t.hash>>16), byte(t.hash>>8), byte(t.hash))
}
+ if len(args) > 50 {
+ panic("reflect.FuncOf does not support more than 50 arguments")
+ }
ft.hash = hash
- ft.in = fin
- ft.out = fout
- ft.dotdotdot = variadic
+ ft.inCount = uint16(len(in))
+ ft.outCount = uint16(len(out))
+ if variadic {
+ ft.outCount |= 1 << 15
+ }
// Look in cache.
funcLookupCache.RLock()
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.in() {
if i > 0 {
repr = append(repr, ", "...)
}
- if ft.dotdotdot && i == len(ft.in)-1 {
+ if ft.IsVariadic() && i == int(ft.inCount)-1 {
repr = append(repr, "..."...)
repr = append(repr, (*sliceType)(unsafe.Pointer(t)).elem.string...)
} else {
}
}
repr = append(repr, ')')
- if l := len(ft.out); l == 1 {
+ out := ft.out()
+ if len(out) == 1 {
repr = append(repr, ' ')
- } else if l > 1 {
+ } else if len(out) > 1 {
repr = append(repr, " ("...)
}
- for i, t := range ft.out {
+ for i, t := range out {
if i > 0 {
repr = append(repr, ", "...)
}
repr = append(repr, t.string...)
}
- if len(ft.out) > 1 {
+ if len(out) > 1 {
repr = append(repr, ')')
}
return string(repr)
}
offset += ptrSize
}
- for _, arg := range tt.in {
+ for _, arg := range tt.in() {
offset += -offset & uintptr(arg.align-1)
addTypeBits(ptrmap, offset, arg)
offset += arg.size
}
offset += -offset & (ptrSize - 1)
retOffset = offset
- for _, res := range tt.out {
+ for _, res := range tt.out() {
offset += -offset & uintptr(res.align-1)
addTypeBits(ptrmap, offset, res)
offset += res.size
// Copy argument frame into Values.
ptr := frame
off := uintptr(0)
- in := make([]Value, 0, len(ftyp.in))
- for _, arg := range ftyp.in {
- typ := arg
+ in := make([]Value, 0, int(ftyp.inCount))
+ for _, typ := range ftyp.in() {
off += -off & uintptr(typ.align-1)
addr := unsafe.Pointer(uintptr(ptr) + off)
v := Value{typ, nil, flag(typ.Kind())}
// Call underlying function.
out := f(in)
- if len(out) != len(ftyp.out) {
+ numOut := ftyp.NumOut()
+ if len(out) != numOut {
panic("reflect: wrong return count from function created by MakeFunc")
}
// Copy results back into argument frame.
- if len(ftyp.out) > 0 {
+ if numOut > 0 {
off += -off & (ptrSize - 1)
if runtime.GOARCH == "amd64p32" {
off = align(off, 8)
}
- for i, arg := range ftyp.out {
- typ := arg
+ for i, typ := range ftyp.out() {
v := out[i]
if v.typ != typ {
panic("reflect: function created by MakeFunc using " + funcName(f) +
throw("runtime.SetFinalizer: second argument is " + ftyp._string + ", not a function")
}
ft := (*functype)(unsafe.Pointer(ftyp))
- if ft.dotdotdot || len(ft.in) != 1 {
+ if ft.dotdotdot() {
+ throw("runtime.SetFinalizer: cannot pass " + etyp._string + " to finalizer " + ftyp._string + " because dotdotdot")
+ }
+ if ft.dotdotdot() || ft.inCount != 1 {
throw("runtime.SetFinalizer: cannot pass " + etyp._string + " to finalizer " + ftyp._string)
}
- fint := ft.in[0]
+ fint := ft.in()[0]
switch {
case fint == etyp:
// ok - same type
okarg:
// compute size needed for return parameters
nret := uintptr(0)
- for _, t := range ft.out {
- nret = round(nret, uintptr(t.align)) + t.size
+ for _, t := range ft.out() {
+ nret = round(nret, uintptr(t.align)) + uintptr(t.size)
}
nret = round(nret, sys.PtrSize)
panic("compileCallback: not a function")
}
ft := (*functype)(unsafe.Pointer(fn._type))
- if len(ft.out) != 1 {
+ if len(ft.out()) != 1 {
panic("compileCallback: function must have one output parameter")
}
uintptrSize := unsafe.Sizeof(uintptr(0))
- if ft.out[0].size != uintptrSize {
+ if ft.out()[0].size != uintptrSize {
panic("compileCallback: output parameter size is wrong")
}
argsize := uintptr(0)
- for _, t := range ft.in {
+ for _, t := range ft.in() {
if t.size > uintptrSize {
panic("compileCallback: input parameter size is wrong")
}
return t._string[i+1:]
}
+func (t *functype) in() []*_type {
+ // See funcType in reflect/type.go for details on data layout.
+ uadd := uintptr(unsafe.Sizeof(functype{}))
+ if t.typ.tflag&tflagUncommon != 0 {
+ uadd += unsafe.Sizeof(uncommontype{})
+ }
+ return (*[1 << 20]*_type)(add(unsafe.Pointer(t), uadd))[:t.inCount]
+}
+
+func (t *functype) out() []*_type {
+ // See funcType in reflect/type.go for details on data layout.
+ uadd := uintptr(unsafe.Sizeof(functype{}))
+ if t.typ.tflag&tflagUncommon != 0 {
+ uadd += unsafe.Sizeof(uncommontype{})
+ }
+ outCount := t.outCount & (1<<15 - 1)
+ return (*[1 << 20]*_type)(add(unsafe.Pointer(t), uadd))[t.inCount : t.inCount+outCount]
+}
+
+func (t *functype) dotdotdot() bool {
+ return t.outCount&(1<<15) != 0
+}
+
type method struct {
name *string
pkgpath *string
}
type functype struct {
- typ _type
- dotdotdot bool
- in []*_type
- out []*_type
+ typ _type
+ inCount uint16
+ outCount uint16
}
type ptrtype struct {