diff --git a/decode.go b/decode.go index e84570e..e5c4064 100644 --- a/decode.go +++ b/decode.go @@ -37,7 +37,7 @@ func unmarshal(data []byte, v interface{}) error { src := make([]byte, len(data)+1) // append nul byte to the end copy(src, data) - header := (*interfaceHeader)(unsafe.Pointer(&v)) + header := (*emptyInterface)(unsafe.Pointer(&v)) if err := validateType(header.typ, uintptr(header.ptr)); err != nil { return err @@ -56,7 +56,7 @@ func unmarshalNoEscape(data []byte, v interface{}) error { src := make([]byte, len(data)+1) // append nul byte to the end copy(src, data) - header := (*interfaceHeader)(unsafe.Pointer(&v)) + header := (*emptyInterface)(unsafe.Pointer(&v)) if err := validateType(header.typ, uintptr(header.ptr)); err != nil { return err @@ -129,7 +129,7 @@ func (d *Decoder) prepareForDecode() error { // See the documentation for Unmarshal for details about // the conversion of JSON into a Go value. func (d *Decoder) Decode(v interface{}) error { - header := (*interfaceHeader)(unsafe.Pointer(&v)) + header := (*emptyInterface)(unsafe.Pointer(&v)) typ := header.typ ptr := uintptr(header.ptr) typeptr := uintptr(unsafe.Pointer(typ)) diff --git a/decode_interface.go b/decode_interface.go index 20f5ad5..744b821 100644 --- a/decode_interface.go +++ b/decode_interface.go @@ -202,7 +202,7 @@ func (d *interfaceDecoder) decodeStreamEmptyInterface(s *stream, depth int64, p } func (d *interfaceDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer) error { - runtimeInterfaceValue := *(*interface{})(unsafe.Pointer(&interfaceHeader{ + runtimeInterfaceValue := *(*interface{})(unsafe.Pointer(&emptyInterface{ typ: d.typ, ptr: p, })) @@ -217,7 +217,7 @@ func (d *interfaceDecoder) decodeStream(s *stream, depth int64, p unsafe.Pointer return d.errUnmarshalType(rv.Type(), s.totalOffset()) } iface := rv.Interface() - ifaceHeader := (*interfaceHeader)(unsafe.Pointer(&iface)) + ifaceHeader := (*emptyInterface)(unsafe.Pointer(&iface)) typ := ifaceHeader.typ if ifaceHeader.ptr == nil || d.typ == typ || typ == nil { // concrete type is empty interface @@ -252,7 +252,7 @@ func (d *interfaceDecoder) errUnmarshalType(typ reflect.Type, offset int64) *Unm } func (d *interfaceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Pointer) (int64, error) { - runtimeInterfaceValue := *(*interface{})(unsafe.Pointer(&interfaceHeader{ + runtimeInterfaceValue := *(*interface{})(unsafe.Pointer(&emptyInterface{ typ: d.typ, ptr: p, })) @@ -268,7 +268,7 @@ func (d *interfaceDecoder) decode(buf []byte, cursor, depth int64, p unsafe.Poin } iface := rv.Interface() - ifaceHeader := (*interfaceHeader)(unsafe.Pointer(&iface)) + ifaceHeader := (*emptyInterface)(unsafe.Pointer(&iface)) typ := ifaceHeader.typ if ifaceHeader.ptr == nil || d.typ == typ || typ == nil { // concrete type is empty interface diff --git a/decode_unmarshal_json.go b/decode_unmarshal_json.go index 1767c1f..faa593b 100644 --- a/decode_unmarshal_json.go +++ b/decode_unmarshal_json.go @@ -38,7 +38,7 @@ func (d *unmarshalJSONDecoder) decodeStream(s *stream, depth int64, p unsafe.Poi dst := make([]byte, len(src)) copy(dst, src) - v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ + v := *(*interface{})(unsafe.Pointer(&emptyInterface{ typ: d.typ, ptr: p, })) @@ -60,7 +60,7 @@ func (d *unmarshalJSONDecoder) decode(buf []byte, cursor, depth int64, p unsafe. dst := make([]byte, len(src)) copy(dst, src) - v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ + v := *(*interface{})(unsafe.Pointer(&emptyInterface{ typ: d.typ, ptr: p, })) diff --git a/decode_unmarshal_text.go b/decode_unmarshal_text.go index 7b560af..cd30e16 100644 --- a/decode_unmarshal_text.go +++ b/decode_unmarshal_text.go @@ -77,7 +77,7 @@ func (d *unmarshalTextDecoder) decodeStream(s *stream, depth int64, p unsafe.Poi if b, ok := unquoteBytes(dst); ok { dst = b } - v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ + v := *(*interface{})(unsafe.Pointer(&emptyInterface{ typ: d.typ, ptr: p, })) @@ -127,7 +127,7 @@ func (d *unmarshalTextDecoder) decode(buf []byte, cursor, depth int64, p unsafe. if s, ok := unquoteBytes(src); ok { src = s } - v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ + v := *(*interface{})(unsafe.Pointer(&emptyInterface{ typ: d.typ, ptr: *(*unsafe.Pointer)(unsafe.Pointer(&p)), })) diff --git a/encode.go b/encode.go index 2d51c57..cb52b07 100644 --- a/encode.go +++ b/encode.go @@ -195,7 +195,7 @@ func encode(ctx *encodeRuntimeContext, v interface{}, opt EncodeOption) ([]byte, b = encodeComma(b) return b, nil } - header := (*interfaceHeader)(unsafe.Pointer(&v)) + header := (*emptyInterface)(unsafe.Pointer(&v)) typ := header.typ typeptr := uintptr(unsafe.Pointer(typ)) @@ -225,7 +225,7 @@ func encodeNoEscape(ctx *encodeRuntimeContext, v interface{}, opt EncodeOption) b = encodeComma(b) return b, nil } - header := (*interfaceHeader)(unsafe.Pointer(&v)) + header := (*emptyInterface)(unsafe.Pointer(&v)) typ := header.typ typeptr := uintptr(unsafe.Pointer(typ)) @@ -252,7 +252,7 @@ func encodeIndent(ctx *encodeRuntimeContext, v interface{}, prefix, indent strin b = encodeIndentComma(b) return b, nil } - header := (*interfaceHeader)(unsafe.Pointer(&v)) + header := (*emptyInterface)(unsafe.Pointer(&v)) typ := header.typ typeptr := uintptr(unsafe.Pointer(typ)) diff --git a/encode_opcode_test.go b/encode_opcode_test.go index 919a688..96d3a3d 100644 --- a/encode_opcode_test.go +++ b/encode_opcode_test.go @@ -7,7 +7,7 @@ import ( func TestDumpOpcode(t *testing.T) { var v interface{} = 1 - header := (*interfaceHeader)(unsafe.Pointer(&v)) + header := (*emptyInterface)(unsafe.Pointer(&v)) typ := header.typ typeptr := uintptr(unsafe.Pointer(typ)) codeSet, err := encodeCompileToGetCodeSet(typeptr) diff --git a/encode_vm.go b/encode_vm.go index 950e5a3..510f105 100644 --- a/encode_vm.go +++ b/encode_vm.go @@ -37,14 +37,14 @@ func ptrToUnsafePtr(p uintptr) unsafe.Pointer { return *(*unsafe.Pointer)(unsafe.Pointer(&p)) } func ptrToInterface(code *opcode, p uintptr) interface{} { - return *(*interface{})(unsafe.Pointer(&interfaceHeader{ + return *(*interface{})(unsafe.Pointer(&emptyInterface{ typ: code.typ, ptr: *(*unsafe.Pointer)(unsafe.Pointer(&p)), })) } func errUnsupportedValue(code *opcode, ptr uintptr) *UnsupportedValueError { - v := *(*interface{})(unsafe.Pointer(&interfaceHeader{ + v := *(*interface{})(unsafe.Pointer(&emptyInterface{ typ: code.typ, ptr: *(*unsafe.Pointer)(unsafe.Pointer(&ptr)), })) @@ -163,7 +163,7 @@ func encodeRun(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, opt Enco } } ctx.seenPtr = append(ctx.seenPtr, ptr) - iface := (*interfaceHeader)(ptrToUnsafePtr(ptr)) + iface := (*emptyInterface)(ptrToUnsafePtr(ptr)) if iface == nil || iface.ptr == nil { b = encodeNull(b) b = encodeComma(b) diff --git a/encode_vm_escaped.go b/encode_vm_escaped.go index 82c1953..81dfc77 100644 --- a/encode_vm_escaped.go +++ b/encode_vm_escaped.go @@ -104,7 +104,7 @@ func encodeRunEscaped(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, o } } ctx.seenPtr = append(ctx.seenPtr, ptr) - iface := (*interfaceHeader)(ptrToUnsafePtr(ptr)) + iface := (*emptyInterface)(ptrToUnsafePtr(ptr)) if iface == nil || iface.ptr == nil { b = encodeNull(b) b = encodeComma(b) diff --git a/encode_vm_escaped_indent.go b/encode_vm_escaped_indent.go index 7776930..3e31da6 100644 --- a/encode_vm_escaped_indent.go +++ b/encode_vm_escaped_indent.go @@ -95,7 +95,7 @@ func encodeRunEscapedIndent(ctx *encodeRuntimeContext, b []byte, codeSet *opcode } } ctx.seenPtr = append(ctx.seenPtr, ptr) - iface := (*interfaceHeader)(ptrToUnsafePtr(ptr)) + iface := (*emptyInterface)(ptrToUnsafePtr(ptr)) if iface == nil || iface.ptr == nil { b = encodeNull(b) b = encodeIndentComma(b) diff --git a/encode_vm_indent.go b/encode_vm_indent.go index 8d7653e..3612dc8 100644 --- a/encode_vm_indent.go +++ b/encode_vm_indent.go @@ -95,7 +95,7 @@ func encodeRunIndent(ctx *encodeRuntimeContext, b []byte, codeSet *opcodeSet, op } } ctx.seenPtr = append(ctx.seenPtr, ptr) - iface := (*interfaceHeader)(ptrToUnsafePtr(ptr)) + iface := (*emptyInterface)(ptrToUnsafePtr(ptr)) if iface == nil || iface.ptr == nil { b = encodeNull(b) b = encodeIndentComma(b) diff --git a/internal/runtime/rtype.go b/internal/runtime/rtype.go new file mode 100644 index 0000000..c73223d --- /dev/null +++ b/internal/runtime/rtype.go @@ -0,0 +1,262 @@ +package runtime + +import ( + "reflect" + "unsafe" +) + +// Type representing reflect.rtype for noescape trick +type Type struct{} + +//go:linkname rtype_Align reflect.(*rtype).Align +//go:noescape +func rtype_Align(*Type) int + +func (t *Type) Align() int { + return rtype_Align(t) +} + +//go:linkname rtype_FieldAlign reflect.(*rtype).FieldAlign +//go:noescape +func rtype_FieldAlign(*Type) int + +func (t *Type) FieldAlign() int { + return rtype_FieldAlign(t) +} + +//go:linkname rtype_Method reflect.(*rtype).Method +//go:noescape +func rtype_Method(*Type, int) reflect.Method + +func (t *Type) Method(a0 int) reflect.Method { + return rtype_Method(t, a0) +} + +//go:linkname rtype_MethodByName reflect.(*rtype).MethodByName +//go:noescape +func rtype_MethodByName(*Type, string) (reflect.Method, bool) + +func (t *Type) MethodByName(a0 string) (reflect.Method, bool) { + return rtype_MethodByName(t, a0) +} + +//go:linkname rtype_NumMethod reflect.(*rtype).NumMethod +//go:noescape +func rtype_NumMethod(*Type) int + +func (t *Type) NumMethod() int { + return rtype_NumMethod(t) +} + +//go:linkname rtype_Name reflect.(*rtype).Name +//go:noescape +func rtype_Name(*Type) string + +func (t *Type) Name() string { + return rtype_Name(t) +} + +//go:linkname rtype_PkgPath reflect.(*rtype).PkgPath +//go:noescape +func rtype_PkgPath(*Type) string + +func (t *Type) PkgPath() string { + return rtype_PkgPath(t) +} + +//go:linkname rtype_Size reflect.(*rtype).Size +//go:noescape +func rtype_Size(*Type) uintptr + +func (t *Type) Size() uintptr { + return rtype_Size(t) +} + +//go:linkname rtype_String reflect.(*rtype).String +//go:noescape +func rtype_String(*Type) string + +func (t *Type) String() string { + return rtype_String(t) +} + +//go:linkname rtype_Kind reflect.(*rtype).Kind +//go:noescape +func rtype_Kind(*Type) reflect.Kind + +func (t *Type) Kind() reflect.Kind { + return rtype_Kind(t) +} + +//go:linkname rtype_Implements reflect.(*rtype).Implements +//go:noescape +func rtype_Implements(*Type, reflect.Type) bool + +func (t *Type) Implements(u reflect.Type) bool { + return rtype_Implements(t, u) +} + +//go:linkname rtype_AssignableTo reflect.(*rtype).AssignableTo +//go:noescape +func rtype_AssignableTo(*Type, reflect.Type) bool + +func (t *Type) AssignableTo(u reflect.Type) bool { + return rtype_AssignableTo(t, u) +} + +//go:linkname rtype_ConvertibleTo reflect.(*rtype).ConvertibleTo +//go:noescape +func rtype_ConvertibleTo(*Type, reflect.Type) bool + +func (t *Type) ConvertibleTo(u reflect.Type) bool { + return rtype_ConvertibleTo(t, u) +} + +//go:linkname rtype_Comparable reflect.(*rtype).Comparable +//go:noescape +func rtype_Comparable(*Type) bool + +func (t *Type) Comparable() bool { + return rtype_Comparable(t) +} + +//go:linkname rtype_Bits reflect.(*rtype).Bits +//go:noescape +func rtype_Bits(*Type) int + +func (t *Type) Bits() int { + return rtype_Bits(t) +} + +//go:linkname rtype_ChanDir reflect.(*rtype).ChanDir +//go:noescape +func rtype_ChanDir(*Type) reflect.ChanDir + +func (t *Type) ChanDir() reflect.ChanDir { + return rtype_ChanDir(t) +} + +//go:linkname rtype_IsVariadic reflect.(*rtype).IsVariadic +//go:noescape +func rtype_IsVariadic(*Type) bool + +func (t *Type) IsVariadic() bool { + return rtype_IsVariadic(t) +} + +//go:linkname rtype_Elem reflect.(*rtype).Elem +//go:noescape +func rtype_Elem(*Type) reflect.Type + +func (t *Type) Elem() *Type { + return Type2RType(rtype_Elem(t)) +} + +//go:linkname rtype_Field reflect.(*rtype).Field +//go:noescape +func rtype_Field(*Type, int) reflect.StructField + +func (t *Type) Field(i int) reflect.StructField { + return rtype_Field(t, i) +} + +//go:linkname rtype_FieldByIndex reflect.(*rtype).FieldByIndex +//go:noescape +func rtype_FieldByIndex(*Type, []int) reflect.StructField + +func (t *Type) FieldByIndex(index []int) reflect.StructField { + return rtype_FieldByIndex(t, index) +} + +//go:linkname rtype_FieldByName reflect.(*rtype).FieldByName +//go:noescape +func rtype_FieldByName(*Type, string) (reflect.StructField, bool) + +func (t *Type) FieldByName(name string) (reflect.StructField, bool) { + return rtype_FieldByName(t, name) +} + +//go:linkname rtype_FieldByNameFunc reflect.(*rtype).FieldByNameFunc +//go:noescape +func rtype_FieldByNameFunc(*Type, func(string) bool) (reflect.StructField, bool) + +func (t *Type) FieldByNameFunc(match func(string) bool) (reflect.StructField, bool) { + return rtype_FieldByNameFunc(t, match) +} + +//go:linkname rtype_In reflect.(*rtype).In +//go:noescape +func rtype_In(*Type, int) reflect.Type + +func (t *Type) In(i int) reflect.Type { + return rtype_In(t, i) +} + +//go:linkname rtype_Key reflect.(*rtype).Key +//go:noescape +func rtype_Key(*Type) reflect.Type + +func (t *Type) Key() *Type { + return Type2RType(rtype_Key(t)) +} + +//go:linkname rtype_Len reflect.(*rtype).Len +//go:noescape +func rtype_Len(*Type) int + +func (t *Type) Len() int { + return rtype_Len(t) +} + +//go:linkname rtype_NumField reflect.(*rtype).NumField +//go:noescape +func rtype_NumField(*Type) int + +func (t *Type) NumField() int { + return rtype_NumField(t) +} + +//go:linkname rtype_NumIn reflect.(*rtype).NumIn +//go:noescape +func rtype_NumIn(*Type) int + +func (t *Type) NumIn() int { + return rtype_NumIn(t) +} + +//go:linkname rtype_NumOut reflect.(*rtype).NumOut +//go:noescape +func rtype_NumOut(*Type) int + +func (t *Type) NumOut() int { + return rtype_NumOut(t) +} + +//go:linkname rtype_Out reflect.(*rtype).Out +//go:noescape +func rtype_Out(*Type, int) reflect.Type + +//go:linkname PtrTo reflect.(*rtype).ptrTo +//go:noescape +func PtrTo(*Type) *Type + +func (t *Type) Out(i int) reflect.Type { + return rtype_Out(t, i) +} + +//go:linkname IfaceIndir reflect.ifaceIndir +//go:noescape +func IfaceIndir(*Type) bool + +//go:linkname RType2Type reflect.toType +//go:noescape +func RType2Type(t *Type) reflect.Type + +type emptyInterface struct { + typ *Type + ptr unsafe.Pointer +} + +func Type2RType(t reflect.Type) *Type { + return (*Type)(((*emptyInterface)(unsafe.Pointer(&t))).ptr) +} diff --git a/rtype.go b/rtype.go index e505528..6d06865 100644 --- a/rtype.go +++ b/rtype.go @@ -3,260 +3,29 @@ package json import ( "reflect" "unsafe" + + "github.com/goccy/go-json/internal/runtime" ) -// rtype representing reflect.rtype for noescape trick -type rtype struct{} +type rtype = runtime.Type -//go:linkname rtype_Align reflect.(*rtype).Align -//go:noescape -func rtype_Align(*rtype) int - -func (t *rtype) Align() int { - return rtype_Align(t) -} - -//go:linkname rtype_FieldAlign reflect.(*rtype).FieldAlign -//go:noescape -func rtype_FieldAlign(*rtype) int - -func (t *rtype) FieldAlign() int { - return rtype_FieldAlign(t) -} - -//go:linkname rtype_Method reflect.(*rtype).Method -//go:noescape -func rtype_Method(*rtype, int) reflect.Method - -func (t *rtype) Method(a0 int) reflect.Method { - return rtype_Method(t, a0) -} - -//go:linkname rtype_MethodByName reflect.(*rtype).MethodByName -//go:noescape -func rtype_MethodByName(*rtype, string) (reflect.Method, bool) - -func (t *rtype) MethodByName(a0 string) (reflect.Method, bool) { - return rtype_MethodByName(t, a0) -} - -//go:linkname rtype_NumMethod reflect.(*rtype).NumMethod -//go:noescape -func rtype_NumMethod(*rtype) int - -func (t *rtype) NumMethod() int { - return rtype_NumMethod(t) -} - -//go:linkname rtype_Name reflect.(*rtype).Name -//go:noescape -func rtype_Name(*rtype) string - -func (t *rtype) Name() string { - return rtype_Name(t) -} - -//go:linkname rtype_PkgPath reflect.(*rtype).PkgPath -//go:noescape -func rtype_PkgPath(*rtype) string - -func (t *rtype) PkgPath() string { - return rtype_PkgPath(t) -} - -//go:linkname rtype_Size reflect.(*rtype).Size -//go:noescape -func rtype_Size(*rtype) uintptr - -func (t *rtype) Size() uintptr { - return rtype_Size(t) -} - -//go:linkname rtype_String reflect.(*rtype).String -//go:noescape -func rtype_String(*rtype) string - -func (t *rtype) String() string { - return rtype_String(t) -} - -//go:linkname rtype_Kind reflect.(*rtype).Kind -//go:noescape -func rtype_Kind(*rtype) reflect.Kind - -func (t *rtype) Kind() reflect.Kind { - return rtype_Kind(t) -} - -//go:linkname rtype_Implements reflect.(*rtype).Implements -//go:noescape -func rtype_Implements(*rtype, reflect.Type) bool - -func (t *rtype) Implements(u reflect.Type) bool { - return rtype_Implements(t, u) -} - -//go:linkname rtype_AssignableTo reflect.(*rtype).AssignableTo -//go:noescape -func rtype_AssignableTo(*rtype, reflect.Type) bool - -func (t *rtype) AssignableTo(u reflect.Type) bool { - return rtype_AssignableTo(t, u) -} - -//go:linkname rtype_ConvertibleTo reflect.(*rtype).ConvertibleTo -//go:noescape -func rtype_ConvertibleTo(*rtype, reflect.Type) bool - -func (t *rtype) ConvertibleTo(u reflect.Type) bool { - return rtype_ConvertibleTo(t, u) -} - -//go:linkname rtype_Comparable reflect.(*rtype).Comparable -//go:noescape -func rtype_Comparable(*rtype) bool - -func (t *rtype) Comparable() bool { - return rtype_Comparable(t) -} - -//go:linkname rtype_Bits reflect.(*rtype).Bits -//go:noescape -func rtype_Bits(*rtype) int - -func (t *rtype) Bits() int { - return rtype_Bits(t) -} - -//go:linkname rtype_ChanDir reflect.(*rtype).ChanDir -//go:noescape -func rtype_ChanDir(*rtype) reflect.ChanDir - -func (t *rtype) ChanDir() reflect.ChanDir { - return rtype_ChanDir(t) -} - -//go:linkname rtype_IsVariadic reflect.(*rtype).IsVariadic -//go:noescape -func rtype_IsVariadic(*rtype) bool - -func (t *rtype) IsVariadic() bool { - return rtype_IsVariadic(t) -} - -//go:linkname rtype_Elem reflect.(*rtype).Elem -//go:noescape -func rtype_Elem(*rtype) reflect.Type - -func (t *rtype) Elem() *rtype { - return type2rtype(rtype_Elem(t)) -} - -//go:linkname rtype_Field reflect.(*rtype).Field -//go:noescape -func rtype_Field(*rtype, int) reflect.StructField - -func (t *rtype) Field(i int) reflect.StructField { - return rtype_Field(t, i) -} - -//go:linkname rtype_FieldByIndex reflect.(*rtype).FieldByIndex -//go:noescape -func rtype_FieldByIndex(*rtype, []int) reflect.StructField - -func (t *rtype) FieldByIndex(index []int) reflect.StructField { - return rtype_FieldByIndex(t, index) -} - -//go:linkname rtype_FieldByName reflect.(*rtype).FieldByName -//go:noescape -func rtype_FieldByName(*rtype, string) (reflect.StructField, bool) - -func (t *rtype) FieldByName(name string) (reflect.StructField, bool) { - return rtype_FieldByName(t, name) -} - -//go:linkname rtype_FieldByNameFunc reflect.(*rtype).FieldByNameFunc -//go:noescape -func rtype_FieldByNameFunc(*rtype, func(string) bool) (reflect.StructField, bool) - -func (t *rtype) FieldByNameFunc(match func(string) bool) (reflect.StructField, bool) { - return rtype_FieldByNameFunc(t, match) -} - -//go:linkname rtype_In reflect.(*rtype).In -//go:noescape -func rtype_In(*rtype, int) reflect.Type - -func (t *rtype) In(i int) reflect.Type { - return rtype_In(t, i) -} - -//go:linkname rtype_Key reflect.(*rtype).Key -//go:noescape -func rtype_Key(*rtype) reflect.Type - -func (t *rtype) Key() *rtype { - return type2rtype(rtype_Key(t)) -} - -//go:linkname rtype_Len reflect.(*rtype).Len -//go:noescape -func rtype_Len(*rtype) int - -func (t *rtype) Len() int { - return rtype_Len(t) -} - -//go:linkname rtype_NumField reflect.(*rtype).NumField -//go:noescape -func rtype_NumField(*rtype) int - -func (t *rtype) NumField() int { - return rtype_NumField(t) -} - -//go:linkname rtype_NumIn reflect.(*rtype).NumIn -//go:noescape -func rtype_NumIn(*rtype) int - -func (t *rtype) NumIn() int { - return rtype_NumIn(t) -} - -//go:linkname rtype_NumOut reflect.(*rtype).NumOut -//go:noescape -func rtype_NumOut(*rtype) int - -func (t *rtype) NumOut() int { - return rtype_NumOut(t) -} - -//go:linkname rtype_Out reflect.(*rtype).Out -//go:noescape -func rtype_Out(*rtype, int) reflect.Type - -//go:linkname rtype_ptrTo reflect.(*rtype).ptrTo -//go:noescape -func rtype_ptrTo(*rtype) *rtype - -func (t *rtype) Out(i int) reflect.Type { - return rtype_Out(t, i) -} - -//go:linkname ifaceIndir reflect.ifaceIndir -//go:noescape -func ifaceIndir(*rtype) bool - -//go:linkname rtype2type reflect.toType -//go:noescape -func rtype2type(t *rtype) reflect.Type - -type interfaceHeader struct { +type emptyInterface struct { typ *rtype ptr unsafe.Pointer } -func type2rtype(t reflect.Type) *rtype { - return (*rtype)(((*interfaceHeader)(unsafe.Pointer(&t))).ptr) +func rtype_ptrTo(t *rtype) *rtype { + return runtime.PtrTo(t) +} + +func ifaceIndir(t *rtype) bool { + return runtime.IfaceIndir(t) +} + +func rtype2type(t *rtype) reflect.Type { + return runtime.RType2Type(t) +} + +func type2rtype(t reflect.Type) *rtype { + return runtime.Type2RType(t) }