mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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
This commit is contained in:
parent
cbe7d8db24
commit
6a75ece01c
13 changed files with 170 additions and 510 deletions
|
|
@ -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[])
|
||||||
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[] =
|
||||||
[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)
|
||||||
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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
|
|
||||||
// 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 {
|
||||||
}
|
}
|
||||||
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,
|
||||||
// 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
|
||||||
// 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) {
|
||||||
// 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
|
||||||
// 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
|
||||||
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) {
|
||||||
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 @@
|
||||||
package reflect
|
package reflect
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"runtime"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
@ -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 (
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 {
|
||||||
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 {
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
||||||
|
|
||||||
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) {
|
||||||
|
|
||||||
// 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 {
|
||||||
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 {
|
||||||
* 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 {
|
||||||
|
|
||||||
// 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 {
|
||||||
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 {
|
||||||
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
|
||||||
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 {
|
||||||
|
|
||||||
// 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 {
|
||||||
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 {
|
||||||
": 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
|
||||||
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 @@
|
||||||
#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:
|
||||||
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)
|
||||||
|
|
||||||
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, ...)
|
||||||
{
|
{
|
||||||
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)
|
||||||
{
|
{
|
||||||
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, ...)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
*/
|
*/
|
||||||
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 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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 _imethod struct {
|
||||||
type BoolType commonType
|
name *string
|
||||||
|
pkgPath *string
|
||||||
|
typ *interface{}
|
||||||
|
}
|
||||||
|
|
||||||
// FloatType represents a float type.
|
type interfaceType struct {
|
||||||
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
|
commonType
|
||||||
elem *Type // array element type
|
methods []_imethod
|
||||||
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 { // underscore is to avoid collision with C
|
|
||||||
name *string // name of method
|
|
||||||
pkgPath *string // nil for exported Names; otherwise import path
|
|
||||||
typ *Type // .(*FuncType) underneath
|
|
||||||
}
|
|
||||||
|
|
||||||
// InterfaceType represents an interface type.
|
|
||||||
type InterfaceType struct {
|
|
||||||
commonType
|
|
||||||
methods []_imethod // sorted by hash
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
||||||
// 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
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue