Commit 6a75ece0 authored by Russ Cox's avatar Russ Cox

runtime: delete Type and implementations (use reflect instead)

unsafe: delete Typeof, Reflect, Unreflect, New, NewArray

Part of issue 2955 and issue 2968.

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5650069
parent cbe7d8db
...@@ -764,6 +764,7 @@ EXTERN Pkg* gostringpkg; // fake pkg for Go strings ...@@ -764,6 +764,7 @@ EXTERN Pkg* gostringpkg; // fake pkg for Go strings
EXTERN Pkg* runtimepkg; // package runtime EXTERN Pkg* runtimepkg; // package runtime
EXTERN Pkg* stringpkg; // fake package for C strings EXTERN Pkg* stringpkg; // fake package for C strings
EXTERN Pkg* typepkg; // fake package for runtime type info EXTERN Pkg* typepkg; // fake package for runtime type info
EXTERN Pkg* weaktypepkg; // weak references to runtime type info
EXTERN Pkg* unsafepkg; // package unsafe EXTERN Pkg* unsafepkg; // package unsafe
EXTERN Pkg* phash[128]; EXTERN Pkg* phash[128];
EXTERN int tptr; // either TPTR32 or TPTR64 EXTERN int tptr; // either TPTR32 or TPTR64
......
...@@ -209,6 +209,10 @@ main(int argc, char *argv[]) ...@@ -209,6 +209,10 @@ main(int argc, char *argv[])
typepkg = mkpkg(strlit("type")); typepkg = mkpkg(strlit("type"));
typepkg->name = "type"; typepkg->name = "type";
weaktypepkg = mkpkg(strlit("weak.type"));
weaktypepkg->name = "weak.type";
weaktypepkg->prefix = "weak.type"; // not weak%2etype
unsafepkg = mkpkg(strlit("unsafe")); unsafepkg = mkpkg(strlit("unsafe"));
unsafepkg->name = "unsafe"; unsafepkg->name = "unsafe";
......
...@@ -454,54 +454,17 @@ kinds[] = ...@@ -454,54 +454,17 @@ kinds[] =
[TUNSAFEPTR] = KindUnsafePointer, [TUNSAFEPTR] = KindUnsafePointer,
}; };
static char*
structnames[] =
{
[TINT] = "*runtime.IntType",
[TUINT] = "*runtime.UintType",
[TINT8] = "*runtime.IntType",
[TUINT8] = "*runtime.UintType",
[TINT16] = "*runtime.IntType",
[TUINT16] = "*runtime.UintType",
[TINT32] = "*runtime.IntType",
[TUINT32] = "*runtime.UintType",
[TINT64] = "*runtime.IntType",
[TUINT64] = "*runtime.UintType",
[TUINTPTR] = "*runtime.UintType",
[TCOMPLEX64] = "*runtime.ComplexType",
[TCOMPLEX128] = "*runtime.ComplexType",
[TFLOAT32] = "*runtime.FloatType",
[TFLOAT64] = "*runtime.FloatType",
[TBOOL] = "*runtime.BoolType",
[TSTRING] = "*runtime.StringType",
[TUNSAFEPTR] = "*runtime.UnsafePointerType",
[TPTR32] = "*runtime.PtrType",
[TPTR64] = "*runtime.PtrType",
[TSTRUCT] = "*runtime.StructType",
[TINTER] = "*runtime.InterfaceType",
[TCHAN] = "*runtime.ChanType",
[TMAP] = "*runtime.MapType",
[TARRAY] = "*runtime.ArrayType",
[TFUNC] = "*runtime.FuncType",
};
static Sym* static Sym*
typestruct(Type *t) typestruct(Type *t)
{ {
char *name; // We use a weak reference to the reflect type
int et; // to avoid requiring package reflect in every binary.
// If package reflect is available, the interface{} holding
et = t->etype; // a runtime type will contain a *reflect.commonType.
if(et < 0 || et >= nelem(structnames) || (name = structnames[et]) == nil) { // Otherwise it will use a nil type word but still be usable
fatal("typestruct %lT", t); // by package runtime (because we always use the memory
return nil; // silence gcc // after the interface value, not the interface value itself).
} return pkglookup("*reflect.commonType", weaktypepkg);
if(isslice(t))
name = "*runtime.SliceType";
return pkglookup(name, typepkg);
} }
int int
...@@ -580,7 +543,7 @@ dcommontype(Sym *s, int ot, Type *t) ...@@ -580,7 +543,7 @@ dcommontype(Sym *s, int ot, Type *t)
ot = dsymptr(s, ot, typestruct(t), 0); ot = dsymptr(s, ot, typestruct(t), 0);
ot = dsymptr(s, ot, s, 2*widthptr); ot = dsymptr(s, ot, s, 2*widthptr);
// ../../pkg/runtime/type.go:/commonType // ../../pkg/reflect/type.go:/^type.commonType
// actual type structure // actual type structure
// type commonType struct { // type commonType struct {
// size uintptr; // size uintptr;
...@@ -683,16 +646,9 @@ weaktypesym(Type *t) ...@@ -683,16 +646,9 @@ weaktypesym(Type *t)
{ {
char *p; char *p;
Sym *s; Sym *s;
static Pkg *weak;
if(weak == nil) {
weak = mkpkg(strlit("weak.type"));
weak->name = "weak.type";
weak->prefix = "weak.type"; // not weak%2etype
}
p = smprint("%-T", t); p = smprint("%-T", t);
s = pkglookup(p, weak); s = pkglookup(p, weaktypepkg);
//print("weaktypesym: %s -> %+S\n", p, s); //print("weaktypesym: %s -> %+S\n", p, s);
free(p); free(p);
return s; return s;
......
...@@ -2317,7 +2317,7 @@ dwarfemitdebugsections(void) ...@@ -2317,7 +2317,7 @@ dwarfemitdebugsections(void)
// Needed by the prettyprinter code for interface inspection. // Needed by the prettyprinter code for interface inspection.
defgotype(lookup_or_diag("type.runtime.commonType")); defgotype(lookup_or_diag("type.runtime.commonType"));
defgotype(lookup_or_diag("type.runtime.InterfaceType")); defgotype(lookup_or_diag("type.runtime.interfaceType"));
defgotype(lookup_or_diag("type.runtime.itab")); defgotype(lookup_or_diag("type.runtime.itab"));
genasmsym(defdwsymb); genasmsym(defdwsymb);
......
...@@ -456,7 +456,7 @@ func allocate(rtyp reflect.Type, p uintptr, indir int) uintptr { ...@@ -456,7 +456,7 @@ func allocate(rtyp reflect.Type, p uintptr, indir int) uintptr {
} }
if *(*unsafe.Pointer)(up) == nil { if *(*unsafe.Pointer)(up) == nil {
// Allocate object. // Allocate object.
*(*unsafe.Pointer)(up) = unsafe.New(rtyp) *(*unsafe.Pointer)(up) = unsafe.Pointer(reflect.New(rtyp).Pointer())
} }
return *(*uintptr)(up) return *(*uintptr)(up)
} }
...@@ -609,7 +609,7 @@ func (dec *Decoder) decodeMap(mtyp reflect.Type, state *decoderState, p uintptr, ...@@ -609,7 +609,7 @@ func (dec *Decoder) decodeMap(mtyp reflect.Type, state *decoderState, p uintptr,
// Maps cannot be accessed by moving addresses around the way // Maps cannot be accessed by moving addresses around the way
// that slices etc. can. We must recover a full reflection value for // that slices etc. can. We must recover a full reflection value for
// the iteration. // the iteration.
v := reflect.ValueOf(unsafe.Unreflect(mtyp, unsafe.Pointer(p))) v := reflect.NewAt(mtyp, unsafe.Pointer(p)).Elem()
n := int(state.decodeUint()) n := int(state.decodeUint())
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
key := decodeIntoValue(state, keyOp, keyIndir, allocValue(mtyp.Key()), ovfl) key := decodeIntoValue(state, keyOp, keyIndir, allocValue(mtyp.Key()), ovfl)
...@@ -662,7 +662,7 @@ func (dec *Decoder) decodeSlice(atyp reflect.Type, state *decoderState, p uintpt ...@@ -662,7 +662,7 @@ func (dec *Decoder) decodeSlice(atyp reflect.Type, state *decoderState, p uintpt
// Always write a header at p. // Always write a header at p.
hdrp := (*reflect.SliceHeader)(unsafe.Pointer(p)) hdrp := (*reflect.SliceHeader)(unsafe.Pointer(p))
if hdrp.Cap < n { if hdrp.Cap < n {
hdrp.Data = uintptr(unsafe.NewArray(atyp.Elem(), n)) hdrp.Data = reflect.MakeSlice(atyp, n, n).Pointer()
hdrp.Cap = n hdrp.Cap = n
} }
hdrp.Len = n hdrp.Len = n
...@@ -969,16 +969,16 @@ func (dec *Decoder) gobDecodeOpFor(ut *userTypeInfo) (*decOp, int) { ...@@ -969,16 +969,16 @@ func (dec *Decoder) gobDecodeOpFor(ut *userTypeInfo) (*decOp, int) {
// Caller has gotten us to within one indirection of our value. // Caller has gotten us to within one indirection of our value.
if i.indir > 0 { if i.indir > 0 {
if *(*unsafe.Pointer)(p) == nil { if *(*unsafe.Pointer)(p) == nil {
*(*unsafe.Pointer)(p) = unsafe.New(ut.base) *(*unsafe.Pointer)(p) = unsafe.Pointer(reflect.New(ut.base).Pointer())
} }
} }
// Now p is a pointer to the base type. Do we need to climb out to // Now p is a pointer to the base type. Do we need to climb out to
// get to the receiver type? // get to the receiver type?
var v reflect.Value var v reflect.Value
if ut.decIndir == -1 { if ut.decIndir == -1 {
v = reflect.ValueOf(unsafe.Unreflect(rcvrType, unsafe.Pointer(&p))) v = reflect.NewAt(rcvrType, unsafe.Pointer(&p)).Elem()
} else { } else {
v = reflect.ValueOf(unsafe.Unreflect(rcvrType, p)) v = reflect.NewAt(rcvrType, p).Elem()
} }
state.dec.decodeGobDecoder(state, v) state.dec.decodeGobDecoder(state, v)
} }
......
...@@ -590,7 +590,7 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp ...@@ -590,7 +590,7 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp
// Maps cannot be accessed by moving addresses around the way // Maps cannot be accessed by moving addresses around the way
// that slices etc. can. We must recover a full reflection value for // that slices etc. can. We must recover a full reflection value for
// the iteration. // the iteration.
v := reflect.ValueOf(unsafe.Unreflect(t, unsafe.Pointer(p))) v := reflect.NewAt(t, unsafe.Pointer(p)).Elem()
mv := reflect.Indirect(v) mv := reflect.Indirect(v)
// We send zero-length (but non-nil) maps because the // We send zero-length (but non-nil) maps because the
// receiver might want to use the map. (Maps don't use append.) // receiver might want to use the map. (Maps don't use append.)
...@@ -613,7 +613,7 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp ...@@ -613,7 +613,7 @@ func (enc *Encoder) encOpFor(rt reflect.Type, inProgress map[reflect.Type]*encOp
op = func(i *encInstr, state *encoderState, p unsafe.Pointer) { op = func(i *encInstr, state *encoderState, p unsafe.Pointer) {
// Interfaces transmit the name and contents of the concrete // Interfaces transmit the name and contents of the concrete
// value they contain. // value they contain.
v := reflect.ValueOf(unsafe.Unreflect(t, unsafe.Pointer(p))) v := reflect.NewAt(t, unsafe.Pointer(p)).Elem()
iv := reflect.Indirect(v) iv := reflect.Indirect(v)
if !state.sendZero && (!iv.IsValid() || iv.IsNil()) { if !state.sendZero && (!iv.IsValid() || iv.IsNil()) {
return return
...@@ -645,9 +645,9 @@ func (enc *Encoder) gobEncodeOpFor(ut *userTypeInfo) (*encOp, int) { ...@@ -645,9 +645,9 @@ func (enc *Encoder) gobEncodeOpFor(ut *userTypeInfo) (*encOp, int) {
var v reflect.Value var v reflect.Value
if ut.encIndir == -1 { if ut.encIndir == -1 {
// Need to climb up one level to turn value into pointer. // Need to climb up one level to turn value into pointer.
v = reflect.ValueOf(unsafe.Unreflect(rt, unsafe.Pointer(&p))) v = reflect.NewAt(rt, unsafe.Pointer(&p)).Elem()
} else { } else {
v = reflect.ValueOf(unsafe.Unreflect(rt, p)) v = reflect.NewAt(rt, p).Elem()
} }
if !state.sendZero && isZero(v) { if !state.sendZero && isZero(v) {
return return
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
package reflect package reflect
import ( import (
"runtime"
"strconv" "strconv"
"sync" "sync"
"unsafe" "unsafe"
...@@ -181,7 +180,7 @@ type Type interface { ...@@ -181,7 +180,7 @@ type Type interface {
// It panics if i is not in the range [0, NumOut()). // It panics if i is not in the range [0, NumOut()).
Out(i int) Type Out(i int) Type
runtimeType() *runtime.Type runtimeType() *runtimeType
common() *commonType common() *commonType
uncommon() *uncommonType uncommon() *uncommonType
} }
...@@ -221,128 +220,131 @@ const ( ...@@ -221,128 +220,131 @@ const (
) )
/* /*
* Copy of data structures from ../runtime/type.go. * These data structures are known to the compiler (../../cmd/gc/reflect.c).
* For comments, see the ones in that file. * A few are known to ../runtime/type.go to convey to debuggers.
*
* These data structures are known to the compiler and the runtime.
*
* Putting these types in runtime instead of reflect means that
* reflect doesn't need to be autolinked into every binary, which
* simplifies bootstrapping and package dependencies.
* Unfortunately, it also means that reflect needs its own
* copy in order to access the private fields.
*/ */
// The compiler can only construct empty interface values at
// compile time; non-empty interface values get created
// during initialization. Type is an empty interface
// so that the compiler can lay out references as data.
// The underlying type is *reflect.ArrayType and so on.
type runtimeType interface{}
// commonType is the common implementation of most values. // commonType is the common implementation of most values.
// It is embedded in other, public struct types, but always // It is embedded in other, public struct types, but always
// with a unique tag like `reflect:"array"` or `reflect:"ptr"` // with a unique tag like `reflect:"array"` or `reflect:"ptr"`
// so that code cannot convert from, say, *arrayType to *ptrType. // so that code cannot convert from, say, *arrayType to *ptrType.
type commonType struct { type commonType struct {
size uintptr size uintptr // size in bytes
hash uint32 hash uint32 // hash of type; avoids computation in hash tables
_ uint8 _ uint8 // unused/padding
align uint8 align uint8 // alignment of variable with this type
fieldAlign uint8 fieldAlign uint8 // alignment of struct field with this type
kind uint8 kind uint8 // enumeration for C
alg *uintptr alg *uintptr // algorithm table (../runtime/runtime.h:/Alg)
string *string string *string // string form; unnecessary but undeniably useful
*uncommonType *uncommonType // (relatively) uncommon fields
ptrToThis *runtime.Type ptrToThis *runtimeType // pointer to this type, if used in binary or has methods
} }
// Method on non-interface type
type method struct { type method struct {
name *string name *string // name of method
pkgPath *string pkgPath *string // nil for exported Names; otherwise import path
mtyp *runtime.Type mtyp *runtimeType // method type (without receiver)
typ *runtime.Type typ *runtimeType // .(*FuncType) underneath (with receiver)
ifn unsafe.Pointer ifn unsafe.Pointer // fn used in interface call (one-word receiver)
tfn unsafe.Pointer tfn unsafe.Pointer // fn used for normal method call
} }
// uncommonType is present only for types with names or methods
// (if T is a named type, the uncommonTypes for T and *T have methods).
// Using a pointer to this struct reduces the overall size required
// to describe an unnamed type with no methods.
type uncommonType struct { type uncommonType struct {
name *string name *string // name of type
pkgPath *string pkgPath *string // import path; nil for built-in types like int, string
methods []method methods []method // methods associated with type
} }
// ChanDir represents a channel type's direction. // ChanDir represents a channel type's direction.
type ChanDir int type ChanDir int
const ( const (
RecvDir ChanDir = 1 << iota RecvDir ChanDir = 1 << iota // <-chan
SendDir SendDir // chan<-
BothDir = RecvDir | SendDir BothDir = RecvDir | SendDir // chan
) )
// arrayType represents a fixed array type. // arrayType represents a fixed array type.
type arrayType struct { type arrayType struct {
commonType `reflect:"array"` commonType `reflect:"array"`
elem *runtime.Type elem *runtimeType // array element type
slice *runtime.Type slice *runtimeType // slice type
len uintptr len uintptr
} }
// chanType represents a channel type. // chanType represents a channel type.
type chanType struct { type chanType struct {
commonType `reflect:"chan"` commonType `reflect:"chan"`
elem *runtime.Type elem *runtimeType // channel element type
dir uintptr dir uintptr // channel direction (ChanDir)
} }
// funcType represents a function type. // funcType represents a function type.
type funcType struct { type funcType struct {
commonType `reflect:"func"` commonType `reflect:"func"`
dotdotdot bool dotdotdot bool // last input parameter is ...
in []*runtime.Type in []*runtimeType // input parameter types
out []*runtime.Type out []*runtimeType // output parameter types
} }
// imethod represents a method on an interface type // imethod represents a method on an interface type
type imethod struct { type imethod struct {
name *string name *string // name of method
pkgPath *string pkgPath *string // nil for exported Names; otherwise import path
typ *runtime.Type typ *runtimeType // .(*FuncType) underneath
} }
// interfaceType represents an interface type. // interfaceType represents an interface type.
type interfaceType struct { type interfaceType struct {
commonType `reflect:"interface"` commonType `reflect:"interface"`
methods []imethod methods []imethod // sorted by hash
} }
// mapType represents a map type. // mapType represents a map type.
type mapType struct { type mapType struct {
commonType `reflect:"map"` commonType `reflect:"map"`
key *runtime.Type key *runtimeType // map key type
elem *runtime.Type elem *runtimeType // map element (value) type
} }
// ptrType represents a pointer type. // ptrType represents a pointer type.
type ptrType struct { type ptrType struct {
commonType `reflect:"ptr"` commonType `reflect:"ptr"`
elem *runtime.Type elem *runtimeType // pointer element (pointed at) type
} }
// sliceType represents a slice type. // sliceType represents a slice type.
type sliceType struct { type sliceType struct {
commonType `reflect:"slice"` commonType `reflect:"slice"`
elem *runtime.Type elem *runtimeType // slice element type
} }
// Struct field // Struct field
type structField struct { type structField struct {
name *string name *string // nil for embedded fields
pkgPath *string pkgPath *string // nil for exported Names; otherwise import path
typ *runtime.Type typ *runtimeType // type of field
tag *string tag *string // nil if no tag
offset uintptr offset uintptr // byte offset of field within struct
} }
// structType represents a struct type. // structType represents a struct type.
type structType struct { type structType struct {
commonType `reflect:"struct"` commonType `reflect:"struct"`
fields []structField fields []structField // sorted by offset
} }
/* /*
...@@ -909,23 +911,18 @@ func (t *structType) FieldByNameFunc(match func(string) bool) (f StructField, pr ...@@ -909,23 +911,18 @@ func (t *structType) FieldByNameFunc(match func(string) bool) (f StructField, pr
} }
// Convert runtime type to reflect type. // Convert runtime type to reflect type.
func toCommonType(p *runtime.Type) *commonType { func toCommonType(p *runtimeType) *commonType {
if p == nil { if p == nil {
return nil return nil
} }
type hdr struct { return (*p).(*commonType)
x interface{}
t commonType
}
x := unsafe.Pointer(p)
return &(*hdr)(x).t
} }
func toType(p *runtime.Type) Type { func toType(p *runtimeType) Type {
if p == nil { if p == nil {
return nil return nil
} }
return toCommonType(p).toType() return (*p).(*commonType)
} }
// TypeOf returns the reflection Type of the value in the interface{}. // TypeOf returns the reflection Type of the value in the interface{}.
...@@ -940,14 +937,14 @@ var ptrMap struct { ...@@ -940,14 +937,14 @@ var ptrMap struct {
m map[*commonType]*ptrType m map[*commonType]*ptrType
} }
func (t *commonType) runtimeType() *runtime.Type { func (t *commonType) runtimeType() *runtimeType {
// The runtime.Type always precedes the commonType in memory. // The runtimeType always precedes the commonType in memory.
// Adjust pointer to find it. // Adjust pointer to find it.
var rt struct { var rt struct {
i runtime.Type i runtimeType
ct commonType ct commonType
} }
return (*runtime.Type)(unsafe.Pointer(uintptr(unsafe.Pointer(t)) - unsafe.Offsetof(rt.ct))) return (*runtimeType)(unsafe.Pointer(uintptr(unsafe.Pointer(t)) - unsafe.Offsetof(rt.ct)))
} }
// PtrTo returns the pointer type with element t. // PtrTo returns the pointer type with element t.
...@@ -986,16 +983,15 @@ func (ct *commonType) ptrTo() *commonType { ...@@ -986,16 +983,15 @@ func (ct *commonType) ptrTo() *commonType {
} }
var rt struct { var rt struct {
i runtime.Type i runtimeType
ptrType ptrType
} }
rt.i = (*runtime.PtrType)(unsafe.Pointer(&rt.ptrType)) rt.i = &rt.commonType
// initialize p using *byte's ptrType as a prototype. // initialize p using *byte's ptrType as a prototype.
// have to do assignment as ptrType, not runtime.PtrType,
// in order to write to unexported fields.
p = &rt.ptrType p = &rt.ptrType
bp := (*ptrType)(unsafe.Pointer(unsafe.Typeof((*byte)(nil)).(*runtime.PtrType))) var ibyte interface{} = (*byte)(nil)
bp := (*ptrType)(unsafe.Pointer((**(**runtimeType)(unsafe.Pointer(&ibyte))).(*commonType)))
*p = *bp *p = *bp
s := "*" + *ct.string s := "*" + *ct.string
...@@ -1010,7 +1006,7 @@ func (ct *commonType) ptrTo() *commonType { ...@@ -1010,7 +1006,7 @@ func (ct *commonType) ptrTo() *commonType {
p.uncommonType = nil p.uncommonType = nil
p.ptrToThis = nil p.ptrToThis = nil
p.elem = (*runtime.Type)(unsafe.Pointer(uintptr(unsafe.Pointer(ct)) - unsafe.Offsetof(rt.ptrType))) p.elem = (*runtimeType)(unsafe.Pointer(uintptr(unsafe.Pointer(ct)) - unsafe.Offsetof(rt.ptrType)))
ptrMap.m[ct] = p ptrMap.m[ct] = p
ptrMap.Unlock() ptrMap.Unlock()
......
...@@ -207,7 +207,7 @@ func storeIword(p unsafe.Pointer, w iword, n uintptr) { ...@@ -207,7 +207,7 @@ func storeIword(p unsafe.Pointer, w iword, n uintptr) {
// emptyInterface is the header for an interface{} value. // emptyInterface is the header for an interface{} value.
type emptyInterface struct { type emptyInterface struct {
typ *runtime.Type typ *runtimeType
word iword word iword
} }
...@@ -215,8 +215,8 @@ type emptyInterface struct { ...@@ -215,8 +215,8 @@ type emptyInterface struct {
type nonEmptyInterface struct { type nonEmptyInterface struct {
// see ../runtime/iface.c:/Itab // see ../runtime/iface.c:/Itab
itab *struct { itab *struct {
ityp *runtime.Type // static interface type ityp *runtimeType // static interface type
typ *runtime.Type // dynamic concrete type typ *runtimeType // dynamic concrete type
link unsafe.Pointer link unsafe.Pointer
bad int32 bad int32
unused int32 unused int32
...@@ -1606,6 +1606,10 @@ func Copy(dst, src Value) int { ...@@ -1606,6 +1606,10 @@ func Copy(dst, src Value) int {
* constructors * constructors
*/ */
// implemented in package runtime
func unsafe_New(Type) unsafe.Pointer
func unsafe_NewArray(Type, int) unsafe.Pointer
// MakeSlice creates a new zero-initialized slice value // MakeSlice creates a new zero-initialized slice value
// for the specified slice type, length, and capacity. // for the specified slice type, length, and capacity.
func MakeSlice(typ Type, len, cap int) Value { func MakeSlice(typ Type, len, cap int) Value {
...@@ -1618,7 +1622,7 @@ func MakeSlice(typ Type, len, cap int) Value { ...@@ -1618,7 +1622,7 @@ func MakeSlice(typ Type, len, cap int) Value {
// Reinterpret as *SliceHeader to edit. // Reinterpret as *SliceHeader to edit.
s := (*SliceHeader)(unsafe.Pointer(&x)) s := (*SliceHeader)(unsafe.Pointer(&x))
s.Data = uintptr(unsafe.NewArray(typ.Elem(), cap)) s.Data = uintptr(unsafe_NewArray(typ.Elem(), cap))
s.Len = len s.Len = len
s.Cap = cap s.Cap = cap
...@@ -1697,7 +1701,7 @@ func Zero(typ Type) Value { ...@@ -1697,7 +1701,7 @@ func Zero(typ Type) Value {
if t.size <= ptrSize { if t.size <= ptrSize {
return Value{t, nil, fl} return Value{t, nil, fl}
} }
return Value{t, unsafe.New(typ), fl | flagIndir} return Value{t, unsafe_New(typ), fl | flagIndir}
} }
// New returns a Value representing a pointer to a new zero value // New returns a Value representing a pointer to a new zero value
...@@ -1706,11 +1710,18 @@ func New(typ Type) Value { ...@@ -1706,11 +1710,18 @@ func New(typ Type) Value {
if typ == nil { if typ == nil {
panic("reflect: New(nil)") panic("reflect: New(nil)")
} }
ptr := unsafe.New(typ) ptr := unsafe_New(typ)
fl := flag(Ptr) << flagKindShift fl := flag(Ptr) << flagKindShift
return Value{typ.common().ptrTo(), ptr, fl} return Value{typ.common().ptrTo(), ptr, fl}
} }
// NewAt returns a Value representing a pointer to a value of the
// specified type, using p as that pointer.
func NewAt(typ Type, p unsafe.Pointer) Value {
fl := flag(Ptr) << flagKindShift
return Value{typ.common().ptrTo(), p, fl}
}
// assignTo returns a value v that can be assigned directly to typ. // assignTo returns a value v that can be assigned directly to typ.
// It panics if v is not assignable to typ. // It panics if v is not assignable to typ.
// For a conversion to an interface type, target is a suggested scratch space to use. // For a conversion to an interface type, target is a suggested scratch space to use.
...@@ -1749,20 +1760,20 @@ func (v Value) assignTo(context string, dst *commonType, target *interface{}) Va ...@@ -1749,20 +1760,20 @@ func (v Value) assignTo(context string, dst *commonType, target *interface{}) Va
func chancap(ch iword) int32 func chancap(ch iword) int32
func chanclose(ch iword) func chanclose(ch iword)
func chanlen(ch iword) int32 func chanlen(ch iword) int32
func chanrecv(t *runtime.Type, ch iword, nb bool) (val iword, selected, received bool) func chanrecv(t *runtimeType, ch iword, nb bool) (val iword, selected, received bool)
func chansend(t *runtime.Type, ch iword, val iword, nb bool) bool func chansend(t *runtimeType, ch iword, val iword, nb bool) bool
func makechan(typ *runtime.Type, size uint32) (ch iword) func makechan(typ *runtimeType, size uint32) (ch iword)
func makemap(t *runtime.Type) (m iword) func makemap(t *runtimeType) (m iword)
func mapaccess(t *runtime.Type, m iword, key iword) (val iword, ok bool) func mapaccess(t *runtimeType, m iword, key iword) (val iword, ok bool)
func mapassign(t *runtime.Type, m iword, key, val iword, ok bool) func mapassign(t *runtimeType, m iword, key, val iword, ok bool)
func mapiterinit(t *runtime.Type, m iword) *byte func mapiterinit(t *runtimeType, m iword) *byte
func mapiterkey(it *byte) (key iword, ok bool) func mapiterkey(it *byte) (key iword, ok bool)
func mapiternext(it *byte) func mapiternext(it *byte)
func maplen(m iword) int32 func maplen(m iword) int32
func call(fn, arg unsafe.Pointer, n uint32) func call(fn, arg unsafe.Pointer, n uint32)
func ifaceE2I(t *runtime.Type, src interface{}, dst unsafe.Pointer) func ifaceE2I(t *runtimeType, src interface{}, dst unsafe.Pointer)
// Dummy annotation marking that the value x escapes, // Dummy annotation marking that the value x escapes,
// for use in cases where the reflect code is so clever that // for use in cases where the reflect code is so clever that
......
...@@ -17,9 +17,6 @@ type Error interface { ...@@ -17,9 +17,6 @@ type Error interface {
// A TypeAssertionError explains a failed type assertion. // A TypeAssertionError explains a failed type assertion.
type TypeAssertionError struct { type TypeAssertionError struct {
interfaceType Type // interface had this type
concreteType Type // concrete value had this type
assertedType Type // asserted type
interfaceString string interfaceString string
concreteString string concreteString string
assertedString string assertedString string
...@@ -33,7 +30,7 @@ func (e *TypeAssertionError) Error() string { ...@@ -33,7 +30,7 @@ func (e *TypeAssertionError) Error() string {
if inter == "" { if inter == "" {
inter = "interface" inter = "interface"
} }
if e.concreteType == nil { if e.concreteString == "" {
return "interface conversion: " + inter + " is nil, not " + e.assertedString return "interface conversion: " + inter + " is nil, not " + e.assertedString
} }
if e.missingMethod == "" { if e.missingMethod == "" {
...@@ -44,40 +41,10 @@ func (e *TypeAssertionError) Error() string { ...@@ -44,40 +41,10 @@ func (e *TypeAssertionError) Error() string {
": missing method " + e.missingMethod ": missing method " + e.missingMethod
} }
// Concrete returns the type of the concrete value in the failed type assertion.
// If the interface value was nil, Concrete returns nil.
func (e *TypeAssertionError) Concrete() Type {
return e.concreteType
}
// Asserted returns the type incorrectly asserted by the type assertion.
func (e *TypeAssertionError) Asserted() Type {
return e.assertedType
}
// If the type assertion is to an interface type, MissingMethod returns the
// name of a method needed to satisfy that interface type but not implemented
// by Concrete. If there are multiple such methods,
// MissingMethod returns one; which one is unspecified.
// If the type assertion is not to an interface type, MissingMethod returns an empty string.
func (e *TypeAssertionError) MissingMethod() string {
return e.missingMethod
}
// For calling from C. // For calling from C.
func newTypeAssertionError(pt1, pt2, pt3 *Type, ps1, ps2, ps3 *string, pmeth *string, ret *interface{}) { func newTypeAssertionError(ps1, ps2, ps3 *string, pmeth *string, ret *interface{}) {
var t1, t2, t3 Type
var s1, s2, s3, meth string var s1, s2, s3, meth string
if pt1 != nil {
t1 = *pt1
}
if pt2 != nil {
t2 = *pt2
}
if pt3 != nil {
t3 = *pt3
}
if ps1 != nil { if ps1 != nil {
s1 = *ps1 s1 = *ps1
} }
...@@ -90,7 +57,7 @@ func newTypeAssertionError(pt1, pt2, pt3 *Type, ps1, ps2, ps3 *string, pmeth *st ...@@ -90,7 +57,7 @@ func newTypeAssertionError(pt1, pt2, pt3 *Type, ps1, ps2, ps3 *string, pmeth *st
if pmeth != nil { if pmeth != nil {
meth = *pmeth meth = *pmeth
} }
*ret = &TypeAssertionError{t1, t2, t3, s1, s2, s3, meth} *ret = &TypeAssertionError{s1, s2, s3, meth}
} }
// An errorString represents a runtime error described by a single string. // An errorString represents a runtime error described by a single string.
......
...@@ -7,14 +7,6 @@ ...@@ -7,14 +7,6 @@
#include "type.h" #include "type.h"
#include "malloc.h" #include "malloc.h"
enum
{
// If an empty interface has these bits set in its type
// pointer, it was copied from a reflect.Value and is
// not a valid empty interface.
reflectFlags = 3,
};
void void
runtime·printiface(Iface i) runtime·printiface(Iface i)
{ {
...@@ -127,7 +119,7 @@ search: ...@@ -127,7 +119,7 @@ search:
if(!canfail) { if(!canfail) {
throw: throw:
// didn't find method // didn't find method
runtime·newTypeAssertionError(nil, type, inter, runtime·newTypeAssertionError(
nil, type->string, inter->string, nil, type->string, inter->string,
iname, &err); iname, &err);
if(locked) if(locked)
...@@ -243,13 +235,13 @@ assertI2Tret(Type *t, Iface i, byte *ret) ...@@ -243,13 +235,13 @@ assertI2Tret(Type *t, Iface i, byte *ret)
tab = i.tab; tab = i.tab;
if(tab == nil) { if(tab == nil) {
runtime·newTypeAssertionError(nil, nil, t, runtime·newTypeAssertionError(
nil, nil, t->string, nil, nil, t->string,
nil, &err); nil, &err);
runtime·panic(err); runtime·panic(err);
} }
if(tab->type != t) { if(tab->type != t) {
runtime·newTypeAssertionError(tab->inter, tab->type, t, runtime·newTypeAssertionError(
tab->inter->string, tab->type->string, t->string, tab->inter->string, tab->type->string, t->string,
nil, &err); nil, &err);
runtime·panic(err); runtime·panic(err);
...@@ -289,8 +281,6 @@ runtime·assertE2T(Type *t, Eface e, ...) ...@@ -289,8 +281,6 @@ runtime·assertE2T(Type *t, Eface e, ...)
{ {
byte *ret; byte *ret;
if(((uintptr)e.type&reflectFlags) != 0)
runtime·throw("invalid interface value");
ret = (byte*)(&e+1); ret = (byte*)(&e+1);
assertE2Tret(t, e, ret); assertE2Tret(t, e, ret);
} }
...@@ -300,16 +290,14 @@ assertE2Tret(Type *t, Eface e, byte *ret) ...@@ -300,16 +290,14 @@ assertE2Tret(Type *t, Eface e, byte *ret)
{ {
Eface err; Eface err;
if(((uintptr)e.type&reflectFlags) != 0)
runtime·throw("invalid interface value");
if(e.type == nil) { if(e.type == nil) {
runtime·newTypeAssertionError(nil, nil, t, runtime·newTypeAssertionError(
nil, nil, t->string, nil, nil, t->string,
nil, &err); nil, &err);
runtime·panic(err); runtime·panic(err);
} }
if(e.type != t) { if(e.type != t) {
runtime·newTypeAssertionError(nil, e.type, t, runtime·newTypeAssertionError(
nil, e.type->string, t->string, nil, e.type->string, t->string,
nil, &err); nil, &err);
runtime·panic(err); runtime·panic(err);
...@@ -326,8 +314,6 @@ runtime·assertE2T2(Type *t, Eface e, ...) ...@@ -326,8 +314,6 @@ runtime·assertE2T2(Type *t, Eface e, ...)
bool *ok; bool *ok;
int32 wid; int32 wid;
if(((uintptr)e.type&reflectFlags) != 0)
runtime·throw("invalid interface value");
ret = (byte*)(&e+1); ret = (byte*)(&e+1);
wid = t->size; wid = t->size;
ok = (bool*)(ret + wid); ok = (bool*)(ret + wid);
...@@ -366,7 +352,7 @@ runtime·assertI2E(InterfaceType* inter, Iface i, Eface ret) ...@@ -366,7 +352,7 @@ runtime·assertI2E(InterfaceType* inter, Iface i, Eface ret)
tab = i.tab; tab = i.tab;
if(tab == nil) { if(tab == nil) {
// explicit conversions require non-nil interface value. // explicit conversions require non-nil interface value.
runtime·newTypeAssertionError(nil, nil, inter, runtime·newTypeAssertionError(
nil, nil, inter->string, nil, nil, inter->string,
nil, &err); nil, &err);
runtime·panic(err); runtime·panic(err);
...@@ -421,7 +407,7 @@ runtime·ifaceI2I(InterfaceType *inter, Iface i, Iface *ret) ...@@ -421,7 +407,7 @@ runtime·ifaceI2I(InterfaceType *inter, Iface i, Iface *ret)
tab = i.tab; tab = i.tab;
if(tab == nil) { if(tab == nil) {
// explicit conversions require non-nil interface value. // explicit conversions require non-nil interface value.
runtime·newTypeAssertionError(nil, nil, inter, runtime·newTypeAssertionError(
nil, nil, inter->string, nil, nil, inter->string,
nil, &err); nil, &err);
runtime·panic(err); runtime·panic(err);
...@@ -463,12 +449,10 @@ runtime·ifaceE2I(InterfaceType *inter, Eface e, Iface *ret) ...@@ -463,12 +449,10 @@ runtime·ifaceE2I(InterfaceType *inter, Eface e, Iface *ret)
Type *t; Type *t;
Eface err; Eface err;
if(((uintptr)e.type&reflectFlags) != 0)
runtime·throw("invalid interface value");
t = e.type; t = e.type;
if(t == nil) { if(t == nil) {
// explicit conversions require non-nil interface value. // explicit conversions require non-nil interface value.
runtime·newTypeAssertionError(nil, nil, inter, runtime·newTypeAssertionError(
nil, nil, inter->string, nil, nil, inter->string,
nil, &err); nil, &err);
runtime·panic(err); runtime·panic(err);
...@@ -496,8 +480,6 @@ runtime·assertE2I(InterfaceType* inter, Eface e, Iface ret) ...@@ -496,8 +480,6 @@ runtime·assertE2I(InterfaceType* inter, Eface e, Iface ret)
void void
runtime·assertE2I2(InterfaceType *inter, Eface e, Iface ret, bool ok) runtime·assertE2I2(InterfaceType *inter, Eface e, Iface ret, bool ok)
{ {
if(((uintptr)e.type&reflectFlags) != 0)
runtime·throw("invalid interface value");
if(e.type == nil) { if(e.type == nil) {
ok = 0; ok = 0;
ret.data = nil; ret.data = nil;
...@@ -520,12 +502,10 @@ runtime·assertE2E(InterfaceType* inter, Eface e, Eface ret) ...@@ -520,12 +502,10 @@ runtime·assertE2E(InterfaceType* inter, Eface e, Eface ret)
Type *t; Type *t;
Eface err; Eface err;
if(((uintptr)e.type&reflectFlags) != 0)
runtime·throw("invalid interface value");
t = e.type; t = e.type;
if(t == nil) { if(t == nil) {
// explicit conversions require non-nil interface value. // explicit conversions require non-nil interface value.
runtime·newTypeAssertionError(nil, nil, inter, runtime·newTypeAssertionError(
nil, nil, inter->string, nil, nil, inter->string,
nil, &err); nil, &err);
runtime·panic(err); runtime·panic(err);
...@@ -538,8 +518,6 @@ runtime·assertE2E(InterfaceType* inter, Eface e, Eface ret) ...@@ -538,8 +518,6 @@ runtime·assertE2E(InterfaceType* inter, Eface e, Eface ret)
void void
runtime·assertE2E2(InterfaceType* inter, Eface e, Eface ret, bool ok) runtime·assertE2E2(InterfaceType* inter, Eface e, Eface ret, bool ok)
{ {
if(((uintptr)e.type&reflectFlags) != 0)
runtime·throw("invalid interface value");
USED(inter); USED(inter);
ret = e; ret = e;
ok = e.type != nil; ok = e.type != nil;
...@@ -626,10 +604,6 @@ runtime·ifaceeq_c(Iface i1, Iface i2) ...@@ -626,10 +604,6 @@ runtime·ifaceeq_c(Iface i1, Iface i2)
bool bool
runtime·efaceeq_c(Eface e1, Eface e2) runtime·efaceeq_c(Eface e1, Eface e2)
{ {
if(((uintptr)e1.type&reflectFlags) != 0)
runtime·throw("invalid interface value");
if(((uintptr)e2.type&reflectFlags) != 0)
runtime·throw("invalid interface value");
if(e1.type != e2.type) if(e1.type != e2.type)
return false; return false;
if(e1.type == nil) if(e1.type == nil)
...@@ -672,8 +646,6 @@ runtime·efacethash(Eface e1, uint32 ret) ...@@ -672,8 +646,6 @@ runtime·efacethash(Eface e1, uint32 ret)
{ {
Type *t; Type *t;
if(((uintptr)e1.type&reflectFlags) != 0)
runtime·throw("invalid interface value");
ret = 0; ret = 0;
t = e1.type; t = e1.type;
if(t != nil) if(t != nil)
...@@ -682,10 +654,8 @@ runtime·efacethash(Eface e1, uint32 ret) ...@@ -682,10 +654,8 @@ runtime·efacethash(Eface e1, uint32 ret)
} }
void void
unsafe·Typeof(Eface e, Eface ret) reflect·unsafe_Typeof(Eface e, Eface ret)
{ {
if(((uintptr)e.type&reflectFlags) != 0)
runtime·throw("invalid interface value");
if(e.type == nil) { if(e.type == nil) {
ret.type = nil; ret.type = nil;
ret.data = nil; ret.data = nil;
...@@ -696,73 +666,10 @@ unsafe·Typeof(Eface e, Eface ret) ...@@ -696,73 +666,10 @@ unsafe·Typeof(Eface e, Eface ret)
} }
void void
unsafe·Reflect(Eface e, Eface rettype, void *retaddr) reflect·unsafe_New(Eface typ, void *ret)
{
uintptr *p;
uintptr x;
if(((uintptr)e.type&reflectFlags) != 0)
runtime·throw("invalid interface value");
if(e.type == nil) {
rettype.type = nil;
rettype.data = nil;
retaddr = 0;
} else {
rettype = *(Eface*)e.type;
if(e.type->size <= sizeof(uintptr)) {
// Copy data into x ...
x = 0;
e.type->alg->copy(e.type->size, &x, &e.data);
// but then build pointer to x so that Reflect
// always returns pointer to data.
p = runtime·mal(sizeof(uintptr));
*p = x;
} else {
// Already a pointer, but still make a copy,
// to preserve value semantics for interface data.
p = runtime·mal(e.type->size);
e.type->alg->copy(e.type->size, p, e.data);
}
retaddr = p;
}
FLUSH(&rettype);
FLUSH(&retaddr);
}
void
unsafe·Unreflect(Eface typ, void *addr, Eface e)
{
if(((uintptr)typ.type&reflectFlags) != 0)
runtime·throw("invalid interface value");
// Reflect library has reinterpreted typ
// as its own kind of type structure.
// We know that the pointer to the original
// type structure sits before the data pointer.
e.type = (Type*)((Eface*)typ.data-1);
// Interface holds either pointer to data
// or copy of original data.
if(e.type->size <= sizeof(uintptr))
e.type->alg->copy(e.type->size, &e.data, addr);
else {
// Easier: already a pointer to data.
// TODO(rsc): Should this make a copy?
e.data = addr;
}
FLUSH(&e);
}
void
unsafe·New(Eface typ, void *ret)
{ {
Type *t; Type *t;
if(((uintptr)typ.type&reflectFlags) != 0)
runtime·throw("invalid interface value");
// Reflect library has reinterpreted typ // Reflect library has reinterpreted typ
// as its own kind of type structure. // as its own kind of type structure.
// We know that the pointer to the original // We know that the pointer to the original
...@@ -777,14 +684,11 @@ unsafe·New(Eface typ, void *ret) ...@@ -777,14 +684,11 @@ unsafe·New(Eface typ, void *ret)
} }
void void
unsafe·NewArray(Eface typ, uint32 n, void *ret) reflect·unsafe_NewArray(Eface typ, uint32 n, void *ret)
{ {
uint64 size; uint64 size;
Type *t; Type *t;
if(((uintptr)typ.type&reflectFlags) != 0)
runtime·throw("invalid interface value");
// Reflect library has reinterpreted typ // Reflect library has reinterpreted typ
// as its own kind of type structure. // as its own kind of type structure.
// We know that the pointer to the original // We know that the pointer to the original
......
...@@ -674,7 +674,7 @@ void runtime·panicslice(void); ...@@ -674,7 +674,7 @@ void runtime·panicslice(void);
*/ */
void runtime·newError(String, Eface*); void runtime·newError(String, Eface*);
void runtime·printany(Eface); void runtime·printany(Eface);
void runtime·newTypeAssertionError(Type*, Type*, Type*, String*, String*, String*, String*, Eface*); void runtime·newTypeAssertionError(String*, String*, String*, String*, Eface*);
void runtime·newErrorString(String, Eface*); void runtime·newErrorString(String, Eface*);
void runtime·fadd64c(uint64, uint64, uint64*); void runtime·fadd64c(uint64, uint64, uint64*);
void runtime·fsub64c(uint64, uint64, uint64*); void runtime·fsub64c(uint64, uint64, uint64*);
......
...@@ -4,206 +4,51 @@ ...@@ -4,206 +4,51 @@
/* /*
* Runtime type representation. * Runtime type representation.
* * This file exists only to provide types that 6l can turn into
* The following files know the exact layout of these * DWARF information for use by gdb. Nothing else uses these.
* data structures and must be kept in sync with this file: * They should match the same types in ../reflect/type.go.
* * For comments see ../reflect/type.go.
* ../../cmd/gc/reflect.c
* ../../cmd/ld/dwarf.c decodetype_*
* ../reflect/type.go
* type.h
*/ */
package runtime package runtime
import "unsafe" import "unsafe"
// The compiler can only construct empty interface values at
// compile time; non-empty interface values get created
// during initialization. Type is an empty interface
// so that the compiler can lay out references as data.
type Type interface{}
// All types begin with a few common fields needed for
// the interface runtime.
type commonType struct { type commonType struct {
size uintptr // size in bytes size uintptr
hash uint32 // hash of type; avoids computation in hash tables hash uint32
_ uint8 // unused _ uint8
align uint8 // alignment of variable with this type align uint8
fieldAlign uint8 // alignment of struct field with this type fieldAlign uint8
kind uint8 // enumeration for C kind uint8
alg *uintptr // algorithm table (../runtime/runtime.h:/Alg) alg *uintptr
string *string // string form; unnecessary but undeniably useful string *string
*uncommonType // (relatively) uncommon fields *uncommonType
ptrToThis *Type // pointer to this type, if used in binary or has methods ptrToThis *interface{}
} }
// Values for commonType.kind. type _method struct {
const ( name *string
kindBool = 1 + iota pkgPath *string
kindInt mtyp *interface{}
kindInt8 typ *interface{}
kindInt16 ifn unsafe.Pointer
kindInt32 tfn unsafe.Pointer
kindInt64
kindUint
kindUint8
kindUint16
kindUint32
kindUint64
kindUintptr
kindFloat32
kindFloat64
kindComplex64
kindComplex128
kindArray
kindChan
kindFunc
kindInterface
kindMap
kindPtr
kindSlice
kindString
kindStruct
kindUnsafePointer
kindNoPointers = 1 << 7 // OR'ed into kind
)
// Method on non-interface type
type _method struct { // underscore is to avoid collision with C
name *string // name of method
pkgPath *string // nil for exported Names; otherwise import path
mtyp *Type // method type (without receiver)
typ *Type // .(*FuncType) underneath (with receiver)
ifn unsafe.Pointer // fn used in interface call (one-word receiver)
tfn unsafe.Pointer // fn used for normal method call
} }
// uncommonType is present only for types with names or methods
// (if T is a named type, the uncommonTypes for T and *T have methods).
// Using a pointer to this struct reduces the overall size required
// to describe an unnamed type with no methods.
type uncommonType struct { type uncommonType struct {
name *string // name of type name *string
pkgPath *string // import path; nil for built-in types like int, string pkgPath *string
methods []_method // methods associated with type methods []_method
}
// BoolType represents a boolean type.
type BoolType commonType
// FloatType represents a float type.
type FloatType commonType
// ComplexType represents a complex type.
type ComplexType commonType
// IntType represents an int type.
type IntType commonType
// UintType represents a uint type.
type UintType commonType
// StringType represents a string type.
type StringType commonType
// UintptrType represents a uintptr type.
type UintptrType commonType
// UnsafePointerType represents an unsafe.Pointer type.
type UnsafePointerType commonType
// ArrayType represents a fixed array type.
type ArrayType struct {
commonType
elem *Type // array element type
slice *Type // slice type
len uintptr
}
// SliceType represents a slice type.
type SliceType struct {
commonType
elem *Type // slice element type
}
// ChanDir represents a channel type's direction.
type ChanDir int
const (
RecvDir ChanDir = 1 << iota // <-chan
SendDir // chan<-
BothDir = RecvDir | SendDir // chan
)
// ChanType represents a channel type.
type ChanType struct {
commonType
elem *Type // channel element type
dir uintptr // channel direction (ChanDir)
}
// FuncType represents a function type.
type FuncType struct {
commonType
dotdotdot bool // last input parameter is ...
in []*Type // input parameter types
out []*Type // output parameter types
} }
// Method on interface type type _imethod struct {
type _imethod struct { // underscore is to avoid collision with C name *string
name *string // name of method pkgPath *string
pkgPath *string // nil for exported Names; otherwise import path typ *interface{}
typ *Type // .(*FuncType) underneath
} }
// InterfaceType represents an interface type. type interfaceType struct {
type InterfaceType struct {
commonType commonType
methods []_imethod // sorted by hash methods []_imethod
}
// MapType represents a map type.
type MapType struct {
commonType
key *Type // map key type
elem *Type // map element (value) type
}
// PtrType represents a pointer type.
type PtrType struct {
commonType
elem *Type // pointer element (pointed at) type
}
// Struct field
type structField struct {
name *string // nil for embedded fields
pkgPath *string // nil for exported Names; otherwise import path
typ *Type // type of field
tag *string // nil if no tag
offset uintptr // byte offset of field within struct
}
// StructType represents a struct type.
type StructType struct {
commonType
fields []structField // sorted by offset
}
/*
* Must match iface.c:/Itab and compilers.
* NOTE: this is the version used by the reflection code, there is another
* one in iface_defs.go that is closer to the original C version.
*/
type Itable struct {
Itype *Type // (*tab.inter).(*InterfaceType) is the interface type
Type *Type
link *Itable
bad int32
unused int32
Fn [100000]uintptr // bigger than we'll ever see
} }
...@@ -35,27 +35,3 @@ func Offsetof(v ArbitraryType) uintptr ...@@ -35,27 +35,3 @@ func Offsetof(v ArbitraryType) uintptr
// that the address of a variable with the type of v will always always be zero mod m. // that the address of a variable with the type of v will always always be zero mod m.
// If v is of the form structValue.field, it returns the alignment of field f within struct object obj. // If v is of the form structValue.field, it returns the alignment of field f within struct object obj.
func Alignof(v ArbitraryType) uintptr func Alignof(v ArbitraryType) uintptr
// Typeof returns the type of an interface value, a runtime.Type.
func Typeof(i interface{}) (typ interface{})
// Reflect unpacks an interface value into its type and the address of a copy of the
// internal value.
func Reflect(i interface{}) (typ interface{}, addr Pointer)
// Unreflect inverts Reflect: Given a type and a pointer to a value, it returns an
// empty interface value with contents the type and the value (not the pointer to
// the value). The typ is assumed to contain a pointer to a runtime type; the type
// information in the interface{} is ignored, so that, for example, both
// *reflect.structType and *runtime.StructType can be passed for typ.
func Unreflect(typ interface{}, addr Pointer) (ret interface{})
// New allocates and returns a pointer to memory for a new value of the given type.
// The typ is assumed to hold a pointer to a runtime type.
// Callers should use reflect.New or reflect.Zero instead of invoking unsafe.New directly.
func New(typ interface{}) Pointer
// NewArray allocates and returns a pointer to an array of n elements of the given type.
// The typ is assumed to hold a pointer to a runtime type.
// Callers should use reflect.MakeSlice instead of invoking unsafe.NewArray directly.
func NewArray(typ interface{}, n int) Pointer
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment