From b768a1fbb5cbe8423465b79ad8f82055f79eb5fa Mon Sep 17 00:00:00 2001 From: David Chase Date: Wed, 19 Apr 2023 13:49:04 -0400 Subject: [PATCH] reflect: move funcType to abi/type.go Change-Id: I381229ba67a39487cdcc60da1c73d33b0a7d494a Reviewed-on: https://go-review.googlesource.com/c/go/+/487556 Reviewed-by: Keith Randall Reviewed-by: Keith Randall TryBot-Result: Gopher Robot Run-TryBot: David Chase --- src/reflect/abi.go | 12 ++-- src/reflect/makefunc.go | 2 +- src/reflect/type.go | 120 ++++++++++++++++------------------------ src/reflect/value.go | 37 +++++++------ 4 files changed, 74 insertions(+), 97 deletions(-) diff --git a/src/reflect/abi.go b/src/reflect/abi.go index 21c435ae0b..8ae8964bfe 100644 --- a/src/reflect/abi.go +++ b/src/reflect/abi.go @@ -416,10 +416,10 @@ func newAbiDesc(t *funcType, rcvr *rtype) abiDesc { spill += goarch.PtrSize } } - for i, arg := range t.in() { - stkStep := in.addArg(arg) + for i, arg := range t.InSlice() { + stkStep := in.addArg(toRType(arg)) if stkStep != nil { - addTypeBits(stackPtrs, stkStep.stkOff, arg) + addTypeBits(stackPtrs, stkStep.stkOff, toRType(arg)) } else { spill = align(spill, uintptr(arg.Align())) spill += arg.Size() @@ -449,10 +449,10 @@ func newAbiDesc(t *funcType, rcvr *rtype) abiDesc { // Fake it by artificially extending stackBytes by // the return offset. out.stackBytes = retOffset - for i, res := range t.out() { - stkStep := out.addArg(res) + for i, res := range t.OutSlice() { + stkStep := out.addArg(toRType(res)) if stkStep != nil { - addTypeBits(stackPtrs, stkStep.stkOff, res) + addTypeBits(stackPtrs, stkStep.stkOff, toRType(res)) } else { for _, st := range out.stepsForValue(i) { if st.kind == abiStepPointer { diff --git a/src/reflect/makefunc.go b/src/reflect/makefunc.go index ee0729903e..6e8aeafabe 100644 --- a/src/reflect/makefunc.go +++ b/src/reflect/makefunc.go @@ -126,7 +126,7 @@ func makeMethodValue(op string, v Value) Value { // but we want Interface() and other operations to fail early. methodReceiver(op, fv.rcvr, fv.method) - return Value{&ftyp.rtype, unsafe.Pointer(fv), v.flag&flagRO | flag(Func)} + return Value{toRType(&ftyp.Type), unsafe.Pointer(fv), v.flag&flagRO | flag(Func)} } func methodValueCallCodePtr() uintptr { diff --git a/src/reflect/type.go b/src/reflect/type.go index c9da9197f6..618204780a 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -315,11 +315,7 @@ type chanType = abi.ChanType // 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 { @@ -582,14 +578,14 @@ func (t *rtype) Method(i int) (m Method) { 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 @@ -671,18 +667,10 @@ func (t *rtype) ChanDir() ChanDir { 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)) } @@ -740,14 +728,6 @@ func (t *rtype) FieldByNameFunc(match func(string) bool) (StructField, bool) { 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()) @@ -772,51 +752,44 @@ func (t *rtype) NumField() int { 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. @@ -1437,12 +1410,12 @@ func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool { 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 } } @@ -1792,8 +1765,8 @@ func FuncOf(in, out []Type, variadic bool) Type { 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 { @@ -1803,7 +1776,7 @@ func FuncOf(in, out []Type, variadic bool) Type { // 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 } } @@ -1814,7 +1787,7 @@ func FuncOf(in, out []Type, variadic bool) Type { 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 } } @@ -1832,22 +1805,25 @@ func FuncOf(in, out []Type, variadic bool) Type { // 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, ", "...) } @@ -1855,11 +1831,11 @@ func funcStr(ft *funcType) string { 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 { @@ -1869,7 +1845,7 @@ func funcStr(ft *funcType) string { if i > 0 { repr = append(repr, ", "...) } - repr = append(repr, t.String()...) + repr = append(repr, stringFor(t)...) } if len(out) > 1 { repr = append(repr, ')') @@ -2802,8 +2778,8 @@ var layoutCache sync.Map // map[layoutKey]layoutType // 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()) @@ -2833,9 +2809,9 @@ func funcLayout(t *funcType, rcvr *rtype) (frametype *rtype, framePool *sync.Poo 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)) diff --git a/src/reflect/value.go b/src/reflect/value.go index 3997afaacb..c46d3865da 100644 --- a/src/reflect/value.go +++ b/src/reflect/value.go @@ -438,15 +438,15 @@ func (v Value) call(op string, in []Value) []Value { } } 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) { @@ -486,7 +486,7 @@ func (v Value) call(op string, in []Value) []Value { frameSize := frametype.Size() if debugReflectCall { - println("reflect.call", t.String()) + println("reflect.call", stringFor(&t.Type)) abid.dump() } @@ -517,7 +517,7 @@ func (v Value) call(op string, in []Value) []Value { // 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. @@ -611,7 +611,7 @@ func (v Value) call(op string, in []Value) []Value { 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) @@ -620,7 +620,7 @@ func (v Value) call(op string, in []Value) []Value { // 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 @@ -629,14 +629,14 @@ func (v Value) call(op string, in []Value) []Value { } // 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 } @@ -649,7 +649,7 @@ func (v Value) call(op string, in []Value) []Value { // 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: @@ -667,7 +667,7 @@ func (v Value) call(op string, in []Value) []Value { 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())} } } @@ -711,7 +711,8 @@ func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer, retValid *bool, regs // 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 @@ -777,7 +778,7 @@ func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer, retValid *bool, regs // 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) + @@ -805,7 +806,7 @@ func callReflect(ctxt *makeFuncImpl, frame unsafe.Pointer, retValid *bool, regs // 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 { @@ -991,7 +992,7 @@ func callMethod(ctxt *methodValue, frame unsafe.Pointer, retValid *bool, regs *a } // 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) @@ -1020,7 +1021,7 @@ func callMethod(ctxt *methodValue, frame unsafe.Pointer, retValid *bool, regs *a 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 -- 2.50.0