]> Cypherpunks repositories - gostls13.git/commitdiff
reflect: add ArrayOf, ChanOf, MapOf, SliceOf
authorRuss Cox <rsc@golang.org>
Tue, 13 Nov 2012 18:06:29 +0000 (13:06 -0500)
committerRuss Cox <rsc@golang.org>
Tue, 13 Nov 2012 18:06:29 +0000 (13:06 -0500)
In order to add these, we need to be able to find references
to such types that already exist in the binary. To do that, introduce
a new linker section holding a list of the types corresponding to
arrays, chans, maps, and slices.

To offset the storage cost of this list, and to simplify the code,
remove the interface{} header from the representation of a
runtime type. It was used in early versions of the code but was
made obsolete by the kind field: a switch on kind is more efficient
than a type switch.

In the godoc binary, removing the interface{} header cuts two
words from each of about 10,000 types. Adding back the list of pointers
to array, chan, map, and slice types reintroduces one word for
each of about 500 types. On a 64-bit machine, then, this CL *removes*
a net 156 kB of read-only data from the binary.

This CL does not include the needed support for precise garbage
collection. I have created issue 4375 to track that.

This CL also does not set the 'algorithm' - specifically the equality
and copy functions - for a new array correctly, so I have unexported
ArrayOf for now. That is also part of issue 4375.

Fixes #2339.

R=r, remyoudompheng, mirtchovski, iant
CC=golang-dev
https://golang.org/cl/6572043

19 files changed:
src/cmd/gc/go.h
src/cmd/gc/lex.c
src/cmd/gc/reflect.c
src/cmd/ld/data.c
src/cmd/ld/decodesym.c
src/cmd/ld/dwarf.c
src/cmd/ld/go.c
src/cmd/ld/lib.h
src/cmd/ld/symtab.c
src/pkg/reflect/all_test.go
src/pkg/reflect/export_test.go
src/pkg/reflect/makefunc.go
src/pkg/reflect/type.go
src/pkg/reflect/value.go
src/pkg/runtime/iface.c
src/pkg/runtime/runtime-gdb.py
src/pkg/runtime/type.go
src/pkg/runtime/type.h
src/pkg/runtime/typekind.h

index 22718889a7c488b38163aa885364e1bd95983c0a..a60018be0f000ed1bda1111c0ecd0597c94949a2 100644 (file)
@@ -852,7 +852,8 @@ EXTERN      Pkg*    itabpkg;        // fake pkg for itab cache
 EXTERN Pkg*    runtimepkg;     // package runtime
 EXTERN Pkg*    racepkg;        // package runtime/race
 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 (headers)
+EXTERN Pkg*    typelinkpkg;    // fake package for runtime type info (data)
 EXTERN Pkg*    weaktypepkg;    // weak references to runtime type info
 EXTERN Pkg*    unsafepkg;      // package unsafe
 EXTERN Pkg*    trackpkg;       // fake package for field tracking
index d31395c1d0c3e10755d61125e12f443113a590f2..1031320a0126df756ad4982b6157623547ae12e4 100644 (file)
@@ -224,6 +224,10 @@ main(int argc, char *argv[])
        weaktypepkg = mkpkg(strlit("go.weak.type"));
        weaktypepkg->name = "go.weak.type";
        weaktypepkg->prefix = "go.weak.type";  // not go%2eweak%2etype
+       
+       typelinkpkg = mkpkg(strlit("go.typelink"));
+       typelinkpkg->name = "go.typelink";
+       typelinkpkg->prefix = "go.typelink"; // not go%2etypelink
 
        trackpkg = mkpkg(strlit("go.track"));
        trackpkg->name = "go.track";
index 00d6f5fe76bd340013f449528fd1486d862a0618..89ded4bd409f0337ecb6b78f711332e13190c5eb 100644 (file)
@@ -467,20 +467,6 @@ kinds[] =
        [TUNSAFEPTR]    = KindUnsafePointer,
 };
 
-static Sym*
-typestruct(Type *t)
-{
-       // We use a weak reference to the reflect type
-       // to avoid requiring package reflect in every binary.
-       // If package reflect is available, the interface{} holding
-       // a runtime type will contain a *reflect.commonType.
-       // Otherwise it will use a nil type word but still be usable
-       // by package runtime (because we always use the memory
-       // after the interface value, not the interface value itself).
-       USED(t);
-       return pkglookup("*reflect.commonType", weaktypepkg);
-}
-
 int
 haspointers(Type *t)
 {
@@ -535,6 +521,9 @@ dcommontype(Sym *s, int ot, Type *t)
        Sym *sptr, *algsym;
        static Sym *algarray;
        char *p;
+       
+       if(ot != 0)
+               fatal("dcommontype %d", ot);
 
        sizeofAlg = 4*widthptr;
        if(algarray == nil)
@@ -550,13 +539,6 @@ dcommontype(Sym *s, int ot, Type *t)
        else
                sptr = weaktypesym(ptrto(t));
 
-       // empty interface pointing at this type.
-       // all the references that we emit are *interface{};
-       // they point here.
-       ot = rnd(ot, widthptr);
-       ot = dsymptr(s, ot, typestruct(t), 0);
-       ot = dsymptr(s, ot, s, 2*widthptr);
-
        // ../../pkg/reflect/type.go:/^type.commonType
        // actual type structure
        //      type commonType struct {
@@ -636,6 +618,27 @@ tracksym(Type *t)
        return s;
 }
 
+Sym*
+typelinksym(Type *t)
+{
+       char *p;
+       Sym *s;
+
+       // %-uT is what the generated Type's string field says.
+       // It uses (ambiguous) package names instead of import paths.
+       // %-T is the complete, unambiguous type name.
+       // We want the types to end up sorted by string field,
+       // so use that first in the name, and then add :%-T to
+       // disambiguate. The names are a little long but they are
+       // discarded by the linker and do not end up in the symbol
+       // table of the final binary.
+       p = smprint("%-uT/%-T", t, t);
+       s = pkglookup(p, typelinkpkg);
+       //print("typelinksym: %s -> %+S\n", p, s);
+       free(p);
+       return s;
+}
+
 Sym*
 typesymprefix(char *prefix, Type *t)
 {
@@ -697,7 +700,7 @@ static Sym*
 dtypesym(Type *t)
 {
        int ot, xt, n, isddd, dupok;
-       Sym *s, *s1, *s2;
+       Sym *s, *s1, *s2, *slink;
        Sig *a, *m;
        Type *t1, *tbase, *t2;
 
@@ -893,6 +896,23 @@ ok:
        }
        ot = dextratype(s, ot, t, xt);
        ggloblsym(s, ot, dupok, 1);
+
+       // generate typelink.foo pointing at s = type.foo.
+       // The linker will leave a table of all the typelinks for
+       // types in the binary, so reflect can find them.
+       // We only need the link for unnamed composites that
+       // we want be able to find.
+       if(t->sym == S) {
+               switch(t->etype) {
+               case TARRAY:
+               case TCHAN:
+               case TMAP:
+                       slink = typelinksym(t);
+                       dsymptr(slink, 0, s, 0);
+                       ggloblsym(slink, widthptr, dupok, 1);
+               }
+       }
+
        return s;
 }
 
index 8fe1773047b19d8d0543dcfbad62b7bf5b81a239..51a46e8f47d07e3d3c66854073e1c1dcd6bde2ff 100644 (file)
@@ -1079,7 +1079,7 @@ dodata(void)
        sect->vaddr = 0;
        datsize = 0;
        s = datap;
-       for(; s != nil && s->type < SGCDATA; s = s->next) {
+       for(; s != nil && s->type < STYPELINK; s = s->next) {
                if(s->align != 0)
                        datsize = rnd(datsize, s->align);
                s->type = SRODATA;
@@ -1089,6 +1089,17 @@ dodata(void)
        sect->len = datsize - sect->vaddr;
        datsize = rnd(datsize, PtrSize);
 
+       /* type */
+       sect = addsection(&segtext, ".typelink", 04);
+       sect->vaddr = datsize;
+       for(; s != nil && s->type == STYPELINK; s = s->next) {
+               s->type = SRODATA;
+               s->value = datsize;
+               datsize += s->size;
+       }
+       sect->len = datsize - sect->vaddr;
+       datsize = rnd(datsize, PtrSize);
+       
        /* gcdata */
        sect = addsection(&segtext, ".gcdata", 04);
        sect->vaddr = datsize;
@@ -1194,7 +1205,7 @@ void
 address(void)
 {
        Section *s, *text, *data, *rodata, *symtab, *pclntab, *noptr, *bss, *noptrbss;
-       Section *gcdata, *gcbss;
+       Section *gcdata, *gcbss, *typelink;
        Sym *sym, *sub;
        uvlong va;
 
@@ -1241,7 +1252,8 @@ address(void)
 
        text = segtext.sect;
        rodata = text->next;
-       gcdata = rodata->next;
+       typelink = rodata->next;
+       gcdata = typelink->next;
        gcbss = gcdata->next;
        symtab = gcbss->next;
        pclntab = symtab->next;
@@ -1260,6 +1272,8 @@ address(void)
        xdefine("etext", STEXT, text->vaddr + text->len);
        xdefine("rodata", SRODATA, rodata->vaddr);
        xdefine("erodata", SRODATA, rodata->vaddr + rodata->len);
+       xdefine("typelink", SRODATA, typelink->vaddr);
+       xdefine("etypelink", SRODATA, typelink->vaddr + typelink->len);
        xdefine("gcdata", SGCDATA, gcdata->vaddr);
        xdefine("egcdata", SGCDATA, gcdata->vaddr + gcdata->len);
        xdefine("gcbss", SGCBSS, gcbss->vaddr);
index 347835f8ca2a7ec89a90546131bd4a1192a1a385..ab3f4fbd55a0565ff9dd662c0c85d4b6a82fb005 100644 (file)
@@ -71,21 +71,21 @@ decode_inuxi(uchar* p, int sz)
 uint8
 decodetype_kind(Sym *s)
 {
-       return s->p[3*PtrSize + 7] & ~KindNoPointers;   //  0x13 / 0x1f
+       return s->p[1*PtrSize + 7] & ~KindNoPointers;   //  0x13 / 0x1f
 }
 
 // Type.commonType.size
 vlong
 decodetype_size(Sym *s)
 {
-       return decode_inuxi(s->p + 2*PtrSize, PtrSize);  // 0x8 / 0x10
+       return decode_inuxi(s->p, PtrSize);      // 0x8 / 0x10
 }
 
 // Type.commonType.gc
 Sym*
 decodetype_gc(Sym *s)
 {
-       return decode_reloc_sym(s, 3*PtrSize + 8 + 1*PtrSize);
+       return decode_reloc_sym(s, 1*PtrSize + 8 + 1*PtrSize);
 }
 
 // Type.ArrayType.elem and Type.SliceType.Elem
index 2cf450eda92c6fb07eadd7fd725298f90c65c7f6..9c72f25db73b119b517685008cdec64b4d5139f4 100644 (file)
@@ -2082,7 +2082,7 @@ dwarfemitdebugsections(void)
        newattr(die, DW_AT_byte_size, DW_CLS_CONSTANT, PtrSize, 0);
 
        // Needed by the prettyprinter code for interface inspection.
-       defgotype(lookup_or_diag("type.runtime.commonType"));
+       defgotype(lookup_or_diag("type.runtime.rtype"));
        defgotype(lookup_or_diag("type.runtime.interfaceType"));
        defgotype(lookup_or_diag("type.runtime.itab"));
 
index 81ae71d73627a5be78ae107af538ad1c75d6db97..be5b6d33e64e4ad62426565a3e9210e17152a850 100644 (file)
@@ -740,6 +740,12 @@ deadcode(void)
 
        markflood();
        
+       // keep each beginning with 'typelink.' if the symbol it points at is being kept.
+       for(s = allsym; s != S; s = s->allsym) {
+               if(strncmp(s->name, "go.typelink.", 12) == 0)
+                       s->reachable = s->nr==1 && s->r[0].sym->reachable;
+       }
+
        // remove dead text but keep file information (z symbols).
        last = nil;
        z = nil;
@@ -771,7 +777,7 @@ deadcode(void)
                        s->reachable = 1;
                        s->hide = 1;
                }
-
+       
        // record field tracking references
        fmtstrinit(&fmt);
        for(s = allsym; s != S; s = s->allsym) {
index c2bac601023bf4601498f7104583bc80848792d8..cf334a4bf712cda6204ff9a5da4efef7b535ab40 100644 (file)
@@ -39,6 +39,7 @@ enum
        SSTRING,
        SGOSTRING,
        SRODATA,
+       STYPELINK,
        SGCDATA,
        SGCBSS,
        SSYMTAB,
index 7513ff570df5471edd29c960921172466cbf9cff..a27b181edc3ebbd40ad74e72cb755c42014c4ffc 100644 (file)
@@ -337,6 +337,8 @@ symtab(void)
        // data.c:/^address will provide the actual values.
        xdefine("text", STEXT, 0);
        xdefine("etext", STEXT, 0);
+       xdefine("typelink", SRODATA, 0);
+       xdefine("etypelink", SRODATA, 0);
        xdefine("rodata", SRODATA, 0);
        xdefine("erodata", SRODATA, 0);
        xdefine("gcdata", SGCDATA, 0);
@@ -382,6 +384,10 @@ symtab(void)
                        s->type = STYPE;
                        s->hide = 1;
                }
+               if(strncmp(s->name, "go.typelink.", 12) == 0) {
+                       s->type = STYPELINK;
+                       s->hide = 1;
+               }
                if(strncmp(s->name, "go.string.", 10) == 0) {
                        s->type = SGOSTRING;
                        s->hide = 1;
index d3646c65c9542ad4c81f73a5a371d413b09cff3b..1cfab81fe52d593d2dbeb45a139b481fa372b274 100644 (file)
@@ -2703,6 +2703,88 @@ func TestOverflow(t *testing.T) {
        }
 }
 
+func checkSameType(t *testing.T, x, y interface{}) {
+       if TypeOf(x) != TypeOf(y) {
+               t.Errorf("did not find preexisting type for %s (vs %s)", TypeOf(x), TypeOf(y))
+       }
+}
+
+func TestArrayOf(t *testing.T) {
+       // check construction and use of type not in binary
+       type T int
+       at := ArrayOf(10, TypeOf(T(1)))
+       v := New(at).Elem()
+       for i := 0; i < v.Len(); i++ {
+               v.Index(i).Set(ValueOf(T(i)))
+       }
+       s := fmt.Sprint(v.Interface())
+       want := "[0 1 2 3 4 5 6 7 8 9]"
+       if s != want {
+               t.Errorf("constructed array = %s, want %s", s, want)
+       }
+
+       // check that type already in binary is found
+       checkSameType(t, Zero(ArrayOf(5, TypeOf(T(1)))).Interface(), [5]T{})
+}
+
+func TestSliceOf(t *testing.T) {
+       // check construction and use of type not in binary
+       type T int
+       st := SliceOf(TypeOf(T(1)))
+       v := MakeSlice(st, 10, 10)
+       for i := 0; i < v.Len(); i++ {
+               v.Index(i).Set(ValueOf(T(i)))
+       }
+       s := fmt.Sprint(v.Interface())
+       want := "[0 1 2 3 4 5 6 7 8 9]"
+       if s != want {
+               t.Errorf("constructed slice = %s, want %s", s, want)
+       }
+
+       // check that type already in binary is found
+       type T1 int
+       checkSameType(t, Zero(SliceOf(TypeOf(T1(1)))).Interface(), []T1{})
+}
+
+func TestChanOf(t *testing.T) {
+       // check construction and use of type not in binary
+       type T string
+       ct := ChanOf(BothDir, TypeOf(T("")))
+       v := MakeChan(ct, 2)
+       v.Send(ValueOf(T("hello")))
+       v.Send(ValueOf(T("world")))
+
+       sv1, _ := v.Recv()
+       sv2, _ := v.Recv()
+       s1 := sv1.String()
+       s2 := sv2.String()
+       if s1 != "hello" || s2 != "world" {
+               t.Errorf("constructed chan: have %q, %q, want %q, %q", s1, s2, "hello", "world")
+       }
+
+       // check that type already in binary is found
+       type T1 int
+       checkSameType(t, Zero(ChanOf(BothDir, TypeOf(T1(1)))).Interface(), (chan T1)(nil))
+}
+
+func TestMapOf(t *testing.T) {
+       // check construction and use of type not in binary
+       type K string
+       type V float64
+
+       v := MakeMap(MapOf(TypeOf(K("")), TypeOf(V(0))))
+       v.SetMapIndex(ValueOf(K("a")), ValueOf(V(1)))
+
+       s := fmt.Sprint(v.Interface())
+       want := "map[a:1]"
+       if s != want {
+               t.Errorf("constructed map = %s, want %s", s, want)
+       }
+
+       // check that type already in binary is found
+       checkSameType(t, Zero(MapOf(TypeOf(V(0)), TypeOf(K("")))).Interface(), map[V]K(nil))
+}
+
 type B1 struct {
        X int
        Y int
index 6e0d8a3e0bc965df1ed35196580b106406b55e00..cd8cf2cf2c98b98768dddad971348839fbb855b6 100644 (file)
@@ -14,3 +14,5 @@ func MakeRO(v Value) Value {
 func IsRO(v Value) bool {
        return v.flag&flagRO != 0
 }
+
+var ArrayOf = arrayOf
index 98b6efd5c7105eb31fadbeacf7c53d64a4ea2477..2e767eef7e654642fb22fb5815a09232f640c22c 100644 (file)
@@ -17,7 +17,7 @@ type makeFuncImpl struct {
        // References visible to the garbage collector.
        // The code array below contains the same references
        // embedded in the machine code.
-       typ *commonType
+       typ *rtype
        fn  func([]Value) []Value
 
        // code is the actual machine code invoked for the closure.
index 3a2146ce8dfe39732b59d5295d00991c917c48d3..0b029d78c21a4b56d3fb74095fef0421cc277276 100644 (file)
@@ -184,8 +184,7 @@ type Type interface {
        // It panics if i is not in the range [0, NumOut()).
        Out(i int) Type
 
-       runtimeType() *runtimeType
-       common() *commonType
+       common() *rtype
        uncommon() *uncommonType
 }
 
@@ -229,37 +228,30 @@ const (
        UnsafePointer
 )
 
-// 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.
+// rtype is the common implementation of most values.
 // It is embedded in other, public struct types, but always
 // with a unique tag like `reflect:"array"` or `reflect:"ptr"`
 // so that code cannot convert from, say, *arrayType to *ptrType.
-type commonType struct {
-       size          uintptr      // size in bytes
-       hash          uint32       // hash of type; avoids computation in hash tables
-       _             uint8        // unused/padding
-       align         uint8        // alignment of variable with this type
-       fieldAlign    uint8        // alignment of struct field with this type
-       kind          uint8        // enumeration for C
-       alg           *uintptr     // algorithm table (../runtime/runtime.h:/Alg)
-       gc            uintptr      // garbage collection data
-       string        *string      // string form; unnecessary but undeniably useful
-       *uncommonType              // (relatively) uncommon fields
-       ptrToThis     *runtimeType // pointer to this type, if used in binary or has methods
+type rtype struct {
+       size          uintptr  // size in bytes
+       hash          uint32   // hash of type; avoids computation in hash tables
+       _             uint8    // unused/padding
+       align         uint8    // alignment of variable with this type
+       fieldAlign    uint8    // alignment of struct field with this type
+       kind          uint8    // enumeration for C
+       alg           *uintptr // algorithm table (../runtime/runtime.h:/Alg)
+       gc            uintptr  // garbage collection data
+       string        *string  // string form; unnecessary but undeniably useful
+       *uncommonType          // (relatively) uncommon fields
+       ptrToThis     *rtype   // type for pointer to this type, if used in binary or has methods
 }
 
 // Method on non-interface type
 type method struct {
        name    *string        // name of method
        pkgPath *string        // nil for exported Names; otherwise import path
-       mtyp    *runtimeType   // method type (without receiver)
-       typ     *runtimeType   // .(*FuncType) underneath (with receiver)
+       mtyp    *rtype         // method type (without receiver)
+       typ     *rtype         // .(*FuncType) underneath (with receiver)
        ifn     unsafe.Pointer // fn used in interface call (one-word receiver)
        tfn     unsafe.Pointer // fn used for normal method call
 }
@@ -285,72 +277,72 @@ const (
 
 // arrayType represents a fixed array type.
 type arrayType struct {
-       commonType `reflect:"array"`
-       elem       *runtimeType // array element type
-       slice      *runtimeType // slice type
-       len        uintptr
+       rtype `reflect:"array"`
+       elem  *rtype // array element type
+       slice *rtype // slice type
+       len   uintptr
 }
 
 // chanType represents a channel type.
 type chanType struct {
-       commonType `reflect:"chan"`
-       elem       *runtimeType // channel element type
-       dir        uintptr      // channel direction (ChanDir)
+       rtype `reflect:"chan"`
+       elem  *rtype  // channel element type
+       dir   uintptr // channel direction (ChanDir)
 }
 
 // funcType represents a function type.
 type funcType struct {
-       commonType `reflect:"func"`
-       dotdotdot  bool           // last input parameter is ...
-       in         []*runtimeType // input parameter types
-       out        []*runtimeType // output parameter types
+       rtype     `reflect:"func"`
+       dotdotdot bool     // last input parameter is ...
+       in        []*rtype // input parameter types
+       out       []*rtype // output parameter types
 }
 
 // imethod represents a method on an interface type
 type imethod struct {
-       name    *string      // name of method
-       pkgPath *string      // nil for exported Names; otherwise import path
-       typ     *runtimeType // .(*FuncType) underneath
+       name    *string // name of method
+       pkgPath *string // nil for exported Names; otherwise import path
+       typ     *rtype  // .(*FuncType) underneath
 }
 
 // interfaceType represents an interface type.
 type interfaceType struct {
-       commonType `reflect:"interface"`
-       methods    []imethod // sorted by hash
+       rtype   `reflect:"interface"`
+       methods []imethod // sorted by hash
 }
 
 // mapType represents a map type.
 type mapType struct {
-       commonType `reflect:"map"`
-       key        *runtimeType // map key type
-       elem       *runtimeType // map element (value) type
+       rtype `reflect:"map"`
+       key   *rtype // map key type
+       elem  *rtype // map element (value) type
 }
 
 // ptrType represents a pointer type.
 type ptrType struct {
-       commonType `reflect:"ptr"`
-       elem       *runtimeType // pointer element (pointed at) type
+       rtype `reflect:"ptr"`
+       elem  *rtype // pointer element (pointed at) type
 }
 
 // sliceType represents a slice type.
 type sliceType struct {
-       commonType `reflect:"slice"`
-       elem       *runtimeType // slice element type
+       rtype `reflect:"slice"`
+       elem  *rtype // slice element type
 }
 
 // Struct field
 type structField struct {
-       name    *string      // nil for embedded fields
-       pkgPath *string      // nil for exported Names; otherwise import path
-       typ     *runtimeType // type of field
-       tag     *string      // nil if no tag
-       offset  uintptr      // byte offset of field within struct
+       name    *string // nil for embedded fields
+       pkgPath *string // nil for exported Names; otherwise import path
+       typ     *rtype  // 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 `reflect:"struct"`
-       fields     []structField // sorted by offset
+       rtype  `reflect:"struct"`
+       fields []structField // sorted by offset
 }
 
 /*
@@ -433,18 +425,11 @@ func (t *uncommonType) Name() string {
        return *t.name
 }
 
-func (t *commonType) toType() Type {
-       if t == nil {
-               return nil
-       }
-       return t
-}
+func (t *rtype) String() string { return *t.string }
 
-func (t *commonType) String() string { return *t.string }
+func (t *rtype) Size() uintptr { return t.size }
 
-func (t *commonType) Size() uintptr { return t.size }
-
-func (t *commonType) Bits() int {
+func (t *rtype) Bits() int {
        if t == nil {
                panic("reflect: Bits of nil Type")
        }
@@ -455,13 +440,13 @@ func (t *commonType) Bits() int {
        return int(t.size) * 8
 }
 
-func (t *commonType) Align() int { return int(t.align) }
+func (t *rtype) Align() int { return int(t.align) }
 
-func (t *commonType) FieldAlign() int { return int(t.fieldAlign) }
+func (t *rtype) FieldAlign() int { return int(t.fieldAlign) }
 
-func (t *commonType) Kind() Kind { return Kind(t.kind & kindMask) }
+func (t *rtype) Kind() Kind { return Kind(t.kind & kindMask) }
 
-func (t *commonType) common() *commonType { return t }
+func (t *rtype) common() *rtype { return t }
 
 func (t *uncommonType) Method(i int) (m Method) {
        if t == nil || i < 0 || i >= len(t.methods) {
@@ -476,7 +461,7 @@ func (t *uncommonType) Method(i int) (m Method) {
                m.PkgPath = *p.pkgPath
                fl |= flagRO
        }
-       mt := toCommonType(p.typ)
+       mt := p.typ
        m.Type = mt
        fn := p.tfn
        m.Func = Value{mt, fn, fl}
@@ -507,8 +492,8 @@ func (t *uncommonType) MethodByName(name string) (m Method, ok bool) {
 
 // TODO(rsc): 6g supplies these, but they are not
 // as efficient as they could be: they have commonType
-// as the receiver instead of *commonType.
-func (t *commonType) NumMethod() int {
+// as the receiver instead of *rtype.
+func (t *rtype) NumMethod() int {
        if t.Kind() == Interface {
                tt := (*interfaceType)(unsafe.Pointer(t))
                return tt.NumMethod()
@@ -516,7 +501,7 @@ func (t *commonType) NumMethod() int {
        return t.uncommonType.NumMethod()
 }
 
-func (t *commonType) Method(i int) (m Method) {
+func (t *rtype) Method(i int) (m Method) {
        if t.Kind() == Interface {
                tt := (*interfaceType)(unsafe.Pointer(t))
                return tt.Method(i)
@@ -524,7 +509,7 @@ func (t *commonType) Method(i int) (m Method) {
        return t.uncommonType.Method(i)
 }
 
-func (t *commonType) MethodByName(name string) (m Method, ok bool) {
+func (t *rtype) MethodByName(name string) (m Method, ok bool) {
        if t.Kind() == Interface {
                tt := (*interfaceType)(unsafe.Pointer(t))
                return tt.MethodByName(name)
@@ -532,15 +517,15 @@ func (t *commonType) MethodByName(name string) (m Method, ok bool) {
        return t.uncommonType.MethodByName(name)
 }
 
-func (t *commonType) PkgPath() string {
+func (t *rtype) PkgPath() string {
        return t.uncommonType.PkgPath()
 }
 
-func (t *commonType) Name() string {
+func (t *rtype) Name() string {
        return t.uncommonType.Name()
 }
 
-func (t *commonType) ChanDir() ChanDir {
+func (t *rtype) ChanDir() ChanDir {
        if t.Kind() != Chan {
                panic("reflect: ChanDir of non-chan type")
        }
@@ -548,7 +533,7 @@ func (t *commonType) ChanDir() ChanDir {
        return ChanDir(tt.dir)
 }
 
-func (t *commonType) IsVariadic() bool {
+func (t *rtype) IsVariadic() bool {
        if t.Kind() != Func {
                panic("reflect: IsVariadic of non-func type")
        }
@@ -556,7 +541,7 @@ func (t *commonType) IsVariadic() bool {
        return tt.dotdotdot
 }
 
-func (t *commonType) Elem() Type {
+func (t *rtype) Elem() Type {
        switch t.Kind() {
        case Array:
                tt := (*arrayType)(unsafe.Pointer(t))
@@ -577,7 +562,7 @@ func (t *commonType) Elem() Type {
        panic("reflect: Elem of invalid type")
 }
 
-func (t *commonType) Field(i int) StructField {
+func (t *rtype) Field(i int) StructField {
        if t.Kind() != Struct {
                panic("reflect: Field of non-struct type")
        }
@@ -585,7 +570,7 @@ func (t *commonType) Field(i int) StructField {
        return tt.Field(i)
 }
 
-func (t *commonType) FieldByIndex(index []int) StructField {
+func (t *rtype) FieldByIndex(index []int) StructField {
        if t.Kind() != Struct {
                panic("reflect: FieldByIndex of non-struct type")
        }
@@ -593,7 +578,7 @@ func (t *commonType) FieldByIndex(index []int) StructField {
        return tt.FieldByIndex(index)
 }
 
-func (t *commonType) FieldByName(name string) (StructField, bool) {
+func (t *rtype) FieldByName(name string) (StructField, bool) {
        if t.Kind() != Struct {
                panic("reflect: FieldByName of non-struct type")
        }
@@ -601,7 +586,7 @@ func (t *commonType) FieldByName(name string) (StructField, bool) {
        return tt.FieldByName(name)
 }
 
-func (t *commonType) FieldByNameFunc(match func(string) bool) (StructField, bool) {
+func (t *rtype) FieldByNameFunc(match func(string) bool) (StructField, bool) {
        if t.Kind() != Struct {
                panic("reflect: FieldByNameFunc of non-struct type")
        }
@@ -609,7 +594,7 @@ func (t *commonType) FieldByNameFunc(match func(string) bool) (StructField, bool
        return tt.FieldByNameFunc(match)
 }
 
-func (t *commonType) In(i int) Type {
+func (t *rtype) In(i int) Type {
        if t.Kind() != Func {
                panic("reflect: In of non-func type")
        }
@@ -617,7 +602,7 @@ func (t *commonType) In(i int) Type {
        return toType(tt.in[i])
 }
 
-func (t *commonType) Key() Type {
+func (t *rtype) Key() Type {
        if t.Kind() != Map {
                panic("reflect: Key of non-map type")
        }
@@ -625,7 +610,7 @@ func (t *commonType) Key() Type {
        return toType(tt.key)
 }
 
-func (t *commonType) Len() int {
+func (t *rtype) Len() int {
        if t.Kind() != Array {
                panic("reflect: Len of non-array type")
        }
@@ -633,7 +618,7 @@ func (t *commonType) Len() int {
        return int(tt.len)
 }
 
-func (t *commonType) NumField() int {
+func (t *rtype) NumField() int {
        if t.Kind() != Struct {
                panic("reflect: NumField of non-struct type")
        }
@@ -641,7 +626,7 @@ func (t *commonType) NumField() int {
        return len(tt.fields)
 }
 
-func (t *commonType) NumIn() int {
+func (t *rtype) NumIn() int {
        if t.Kind() != Func {
                panic("reflect: NumIn of non-func type")
        }
@@ -649,7 +634,7 @@ func (t *commonType) NumIn() int {
        return len(tt.in)
 }
 
-func (t *commonType) NumOut() int {
+func (t *rtype) NumOut() int {
        if t.Kind() != Func {
                panic("reflect: NumOut of non-func type")
        }
@@ -657,7 +642,7 @@ func (t *commonType) NumOut() int {
        return len(tt.out)
 }
 
-func (t *commonType) Out(i int) Type {
+func (t *rtype) Out(i int) Type {
        if t.Kind() != Func {
                panic("reflect: Out of non-func type")
        }
@@ -827,7 +812,7 @@ func (t *structType) Field(i int) (f StructField) {
 
 // FieldByIndex returns the nested field corresponding to index.
 func (t *structType) FieldByIndex(index []int) (f StructField) {
-       f.Type = Type(t.toType())
+       f.Type = toType(&t.rtype)
        for i, x := range index {
                if i > 0 {
                        ft := f.Type
@@ -898,13 +883,13 @@ func (t *structType) FieldByNameFunc(match func(string) bool) (result StructFiel
                                f := &t.fields[i]
                                // Find name and type for field f.
                                var fname string
-                               var ntyp *commonType
+                               var ntyp *rtype
                                if f.name != nil {
                                        fname = *f.name
                                } else {
                                        // Anonymous field of type T or *T.
                                        // Name taken from type.
-                                       ntyp = toCommonType(f.typ)
+                                       ntyp = f.typ
                                        if ntyp.Kind() == Ptr {
                                                ntyp = ntyp.Elem().common()
                                        }
@@ -977,21 +962,6 @@ func (t *structType) FieldByName(name string) (f StructField, present bool) {
        return t.FieldByNameFunc(func(s string) bool { return s == name })
 }
 
-// Convert runtime type to reflect type.
-func toCommonType(p *runtimeType) *commonType {
-       if p == nil {
-               return nil
-       }
-       return (*p).(*commonType)
-}
-
-func toType(p *runtimeType) Type {
-       if p == nil {
-               return nil
-       }
-       return (*p).(*commonType)
-}
-
 // TypeOf returns the reflection Type of the value in the interface{}.
 // TypeOf(nil) returns nil.
 func TypeOf(i interface{}) Type {
@@ -1002,28 +972,18 @@ func TypeOf(i interface{}) Type {
 // ptrMap is the cache for PtrTo.
 var ptrMap struct {
        sync.RWMutex
-       m map[*commonType]*ptrType
-}
-
-func (t *commonType) runtimeType() *runtimeType {
-       // The runtimeType always precedes the commonType in memory.
-       // Adjust pointer to find it.
-       var rt struct {
-               i  runtimeType
-               ct commonType
-       }
-       return (*runtimeType)(unsafe.Pointer(uintptr(unsafe.Pointer(t)) - unsafe.Offsetof(rt.ct)))
+       m map[*rtype]*ptrType
 }
 
 // PtrTo returns the pointer type with element t.
 // For example, if t represents type Foo, PtrTo(t) represents *Foo.
 func PtrTo(t Type) Type {
-       return t.(*commonType).ptrTo()
+       return t.(*rtype).ptrTo()
 }
 
-func (ct *commonType) ptrTo() *commonType {
-       if p := ct.ptrToThis; p != nil {
-               return toCommonType(p)
+func (t *rtype) ptrTo() *rtype {
+       if p := t.ptrToThis; p != nil {
+               return p
        }
 
        // Otherwise, synthesize one.
@@ -1033,36 +993,31 @@ func (ct *commonType) ptrTo() *commonType {
        // the type structures in read-only memory.
        ptrMap.RLock()
        if m := ptrMap.m; m != nil {
-               if p := m[ct]; p != nil {
+               if p := m[t]; p != nil {
                        ptrMap.RUnlock()
-                       return &p.commonType
+                       return &p.rtype
                }
        }
        ptrMap.RUnlock()
        ptrMap.Lock()
        if ptrMap.m == nil {
-               ptrMap.m = make(map[*commonType]*ptrType)
+               ptrMap.m = make(map[*rtype]*ptrType)
        }
-       p := ptrMap.m[ct]
+       p := ptrMap.m[t]
        if p != nil {
                // some other goroutine won the race and created it
                ptrMap.Unlock()
-               return &p.commonType
+               return &p.rtype
        }
 
-       var rt struct {
-               i runtimeType
-               ptrType
-       }
-       rt.i = &rt.commonType
+       // Create a new ptrType starting with the description
+       // of an *unsafe.Pointer.
+       p = new(ptrType)
+       var iptr interface{} = (*unsafe.Pointer)(nil)
+       prototype := *(**ptrType)(unsafe.Pointer(&iptr))
+       *p = *prototype
 
-       // initialize p using *byte's ptrType as a prototype.
-       p = &rt.ptrType
-       var ibyte interface{} = (*byte)(nil)
-       bp := (*ptrType)(unsafe.Pointer((**(**runtimeType)(unsafe.Pointer(&ibyte))).(*commonType)))
-       *p = *bp
-
-       s := "*" + *ct.string
+       s := "*" + *t.string
        p.string = &s
 
        // For the type structures linked into the binary, the
@@ -1070,45 +1025,53 @@ func (ct *commonType) ptrTo() *commonType {
        // Create a good hash for the new string by using
        // the FNV-1 hash's mixing function to combine the
        // old hash and the new "*".
-       p.hash = ct.hash*16777619 ^ '*'
+       p.hash = fnv1(t.hash, '*')
 
        p.uncommonType = nil
        p.ptrToThis = nil
-       p.elem = (*runtimeType)(unsafe.Pointer(uintptr(unsafe.Pointer(ct)) - unsafe.Offsetof(rt.ptrType)))
+       p.elem = t
 
-       ptrMap.m[ct] = p
+       ptrMap.m[t] = p
        ptrMap.Unlock()
-       return &p.commonType
+       return &p.rtype
+}
+
+// fnv1 incorporates the list of bytes into the hash x using the FNV-1 hash function.
+func fnv1(x uint32, list ...byte) uint32 {
+       for _, b := range list {
+               x = x*16777619 ^ uint32(b)
+       }
+       return x
 }
 
-func (t *commonType) Implements(u Type) bool {
+func (t *rtype) Implements(u Type) bool {
        if u == nil {
                panic("reflect: nil type passed to Type.Implements")
        }
        if u.Kind() != Interface {
                panic("reflect: non-interface type passed to Type.Implements")
        }
-       return implements(u.(*commonType), t)
+       return implements(u.(*rtype), t)
 }
 
-func (t *commonType) AssignableTo(u Type) bool {
+func (t *rtype) AssignableTo(u Type) bool {
        if u == nil {
                panic("reflect: nil type passed to Type.AssignableTo")
        }
-       uu := u.(*commonType)
+       uu := u.(*rtype)
        return directlyAssignable(uu, t) || implements(uu, t)
 }
 
-func (t *commonType) ConvertibleTo(u Type) bool {
+func (t *rtype) ConvertibleTo(u Type) bool {
        if u == nil {
                panic("reflect: nil type passed to Type.ConvertibleTo")
        }
-       uu := u.(*commonType)
+       uu := u.(*rtype)
        return convertOp(uu, t) != nil
 }
 
 // implements returns true if the type V implements the interface type T.
-func implements(T, V *commonType) bool {
+func implements(T, V *rtype) bool {
        if T.Kind() != Interface {
                return false
        }
@@ -1166,7 +1129,7 @@ func implements(T, V *commonType) bool {
 // http://golang.org/doc/go_spec.html#Assignability
 // Ignoring the interface rules (implemented elsewhere)
 // and the ideal constant rules (no ideal constants at run time).
-func directlyAssignable(T, V *commonType) bool {
+func directlyAssignable(T, V *rtype) bool {
        // x's type V is identical to T?
        if T == V {
                return true
@@ -1182,7 +1145,7 @@ func directlyAssignable(T, V *commonType) bool {
        return haveIdenticalUnderlyingType(T, V)
 }
 
-func haveIdenticalUnderlyingType(T, V *commonType) bool {
+func haveIdenticalUnderlyingType(T, V *rtype) bool {
        if T == V {
                return true
        }
@@ -1278,3 +1241,295 @@ func haveIdenticalUnderlyingType(T, V *commonType) bool {
 
        return false
 }
+
+// typelinks is implemented in package runtime.
+// It retuns a slice of all the 'typelink' information in the binary,
+// which is to say a slice of known types, sorted by string.
+// Note that strings are not unique identifiers for types:
+// there can be more than one with a given string.
+// Only types we might want to look up are included:
+// channels, maps, slices, and arrays.
+func typelinks() []*rtype
+
+// typesByString returns the subslice of typelinks() whose elements have
+// the given string representation.
+// It may be empty (no known types with that string) or may have
+// multiple elements (multiple types with that string).
+func typesByString(s string) []*rtype {
+       typ := typelinks()
+
+       // We are looking for the first index i where the string becomes >= s.
+       // This is a copy of sort.Search, with f(h) replaced by (*typ[h].string >= s).
+       i, j := 0, len(typ)
+       for i < j {
+               h := i + (j-i)/2 // avoid overflow when computing h
+               // i ≤ h < j
+               if !(*typ[h].string >= s) {
+                       i = h + 1 // preserves f(i-1) == false
+               } else {
+                       j = h // preserves f(j) == true
+               }
+       }
+       // i == j, f(i-1) == false, and f(j) (= f(i)) == true  =>  answer is i.
+
+       // Having found the first, linear scan forward to find the last.
+       // We could do a second binary search, but the caller is going
+       // to do a linear scan anyway.
+       j = i
+       for j < len(typ) && *typ[j].string == s {
+               j++
+       }
+
+       // This slice will be empty if the string is not found.
+       return typ[i:j]
+}
+
+// The lookupCache caches ChanOf, MapOf, and SliceOf lookups.
+var lookupCache struct {
+       sync.RWMutex
+       m map[cacheKey]*rtype
+}
+
+// A cacheKey is the key for use in the lookupCache.
+// Four values describe any of the types we are looking for:
+// type kind, one or two subtypes, and an extra integer.
+type cacheKey struct {
+       kind  Kind
+       t1    *rtype
+       t2    *rtype
+       extra uintptr
+}
+
+// cacheGet looks for a type under the key k in the lookupCache.
+// If it finds one, it returns that type.
+// If not, it returns nil with the cache locked.
+// The caller is expected to use cachePut to unlock the cache.
+func cacheGet(k cacheKey) Type {
+       lookupCache.RLock()
+       t := lookupCache.m[k]
+       lookupCache.RUnlock()
+       if t != nil {
+               return t
+       }
+
+       lookupCache.Lock()
+       t = lookupCache.m[k]
+       if t != nil {
+               lookupCache.Unlock()
+               return t
+       }
+
+       if lookupCache.m == nil {
+               lookupCache.m = make(map[cacheKey]*rtype)
+       }
+
+       return nil
+}
+
+// cachePut stores the given type in the cache, unlocks the cache,
+// and returns the type. It is expected that the cache is locked
+// because cacheGet returned nil.
+func cachePut(k cacheKey, t *rtype) Type {
+       lookupCache.m[k] = t
+       lookupCache.Unlock()
+       return t
+}
+
+// ChanOf returns the channel type with the given direction and and element type.
+// For example, if t represents int, ChanOf(RecvDir, t) represents <-chan int.
+//
+// The gc runtime imposes a limit of 64 kB on channel element types.
+// If t's size is equal to or exceeds this limit, ChanOf panics.
+func ChanOf(dir ChanDir, t Type) Type {
+       typ := t.(*rtype)
+
+       // Look in cache.
+       ckey := cacheKey{Chan, typ, nil, uintptr(dir)}
+       if ch := cacheGet(ckey); ch != nil {
+               return ch
+       }
+
+       // This restriction is imposed by the gc compiler and the runtime.
+       if typ.size >= 1<<16 {
+               lookupCache.Unlock()
+               panic("reflect.ChanOf: element size too large")
+       }
+
+       // Look in known types.
+       // TODO: Precedence when constructing string.
+       var s string
+       switch dir {
+       default:
+               lookupCache.Unlock()
+               panic("reflect.ChanOf: invalid dir")
+       case SendDir:
+               s = "chan<- " + *typ.string
+       case RecvDir:
+               s = "<-chan " + *typ.string
+       case BothDir:
+               s = "chan " + *typ.string
+       }
+       for _, tt := range typesByString(s) {
+               ch := (*chanType)(unsafe.Pointer(tt))
+               if ch.elem == typ && ch.dir == uintptr(dir) {
+                       return cachePut(ckey, tt)
+               }
+       }
+
+       // Make a channel type.
+       var ichan interface{} = (chan unsafe.Pointer)(nil)
+       prototype := *(**chanType)(unsafe.Pointer(&ichan))
+       ch := new(chanType)
+       *ch = *prototype
+       ch.string = &s
+       ch.hash = fnv1(typ.hash, 'c', byte(dir))
+       ch.elem = typ
+       ch.uncommonType = nil
+       ch.ptrToThis = nil
+
+       return cachePut(ckey, &ch.rtype)
+}
+
+// MapOf returns the map type with the given key and element types.
+// For example, if k represents int and e represents string,
+// MapOf(k, e) represents map[int]string.
+//
+// If the key type is not a valid map key type (that is, if it does
+// not implement Go's == operator), MapOf panics. TODO(rsc).
+func MapOf(key, elem Type) Type {
+       ktyp := key.(*rtype)
+       etyp := elem.(*rtype)
+
+       // TODO: Check for invalid key types.
+
+       // Look in cache.
+       ckey := cacheKey{Map, ktyp, etyp, 0}
+       if mt := cacheGet(ckey); mt != nil {
+               return mt
+       }
+
+       // Look in known types.
+       s := "map[" + *ktyp.string + "]" + *etyp.string
+       for _, tt := range typesByString(s) {
+               mt := (*mapType)(unsafe.Pointer(tt))
+               if mt.key == ktyp && mt.elem == etyp {
+                       return cachePut(ckey, tt)
+               }
+       }
+
+       // Make a map type.
+       var imap interface{} = (map[unsafe.Pointer]unsafe.Pointer)(nil)
+       prototype := *(**mapType)(unsafe.Pointer(&imap))
+       mt := new(mapType)
+       *mt = *prototype
+       mt.string = &s
+       mt.hash = fnv1(etyp.hash, 'm', byte(ktyp.hash>>24), byte(ktyp.hash>>16), byte(ktyp.hash>>8), byte(ktyp.hash))
+       mt.key = ktyp
+       mt.elem = etyp
+       mt.uncommonType = nil
+       mt.ptrToThis = nil
+
+       return cachePut(ckey, &mt.rtype)
+}
+
+// SliceOf returns the slice type with element type t.
+// For example, if t represents int, SliceOf(t) represents []int.
+func SliceOf(t Type) Type {
+       typ := t.(*rtype)
+
+       // Look in cache.
+       ckey := cacheKey{Slice, typ, nil, 0}
+       if slice := cacheGet(ckey); slice != nil {
+               return slice
+       }
+
+       // Look in known types.
+       s := "[]" + *typ.string
+       for _, tt := range typesByString(s) {
+               slice := (*sliceType)(unsafe.Pointer(tt))
+               if slice.elem == typ {
+                       return cachePut(ckey, tt)
+               }
+       }
+
+       // Make a slice type.
+       var islice interface{} = ([]unsafe.Pointer)(nil)
+       prototype := *(**sliceType)(unsafe.Pointer(&islice))
+       slice := new(sliceType)
+       *slice = *prototype
+       slice.string = &s
+       slice.hash = fnv1(typ.hash, '[')
+       slice.elem = typ
+       slice.uncommonType = nil
+       slice.ptrToThis = nil
+
+       return cachePut(ckey, &slice.rtype)
+}
+
+// ArrayOf returns the array type with the given count and element type.
+// For example, if t represents int, ArrayOf(5, t) represents [5]int.
+//
+// If the resulting type would be larger than the available address space,
+// ArrayOf panics.
+//
+// TODO(rsc): Unexported for now. Export once the alg field is set correctly
+// for the type. This may require significant work.
+func arrayOf(count int, elem Type) Type {
+       typ := elem.(*rtype)
+       slice := SliceOf(elem)
+
+       // Look in cache.
+       ckey := cacheKey{Array, typ, nil, uintptr(count)}
+       if slice := cacheGet(ckey); slice != nil {
+               return slice
+       }
+
+       // Look in known types.
+       s := "[" + strconv.Itoa(count) + "]" + *typ.string
+       for _, tt := range typesByString(s) {
+               slice := (*sliceType)(unsafe.Pointer(tt))
+               if slice.elem == typ {
+                       return cachePut(ckey, tt)
+               }
+       }
+
+       // Make an array type.
+       var iarray interface{} = [1]unsafe.Pointer{}
+       prototype := *(**arrayType)(unsafe.Pointer(&iarray))
+       array := new(arrayType)
+       *array = *prototype
+       array.string = &s
+       array.hash = fnv1(typ.hash, '[')
+       for n := uint32(count); n > 0; n >>= 8 {
+               array.hash = fnv1(array.hash, byte(n))
+       }
+       array.hash = fnv1(array.hash, ']')
+       array.elem = typ
+       max := ^uintptr(0) / typ.size
+       if uintptr(count) > max {
+               panic("reflect.ArrayOf: array size would exceed virtual address space")
+       }
+       array.size = typ.size * uintptr(count)
+       array.align = typ.align
+       array.fieldAlign = typ.fieldAlign
+       // TODO: array.alg
+       // TODO: array.gc
+       array.uncommonType = nil
+       array.ptrToThis = nil
+       array.len = uintptr(count)
+       array.slice = slice.(*rtype)
+
+       return cachePut(ckey, &array.rtype)
+}
+
+// toType converts from a *rtype to a Type that can be returned
+// to the client of package reflect. In gc, the only concern is that
+// a nil *rtype must be replaced by a nil Type, but in gccgo this
+// function takes care of ensuring that multiple *rtype for the same
+// type are coalesced into a single Type.
+func toType(t *rtype) Type {
+       if t == nil {
+               return nil
+       }
+       return t
+}
index b629b58cc11272e2df2d9fa480826f0b955a8892..93401fea52fca0250fa41faa6da151c6620bd493 100644 (file)
@@ -60,7 +60,7 @@ func memmove(adst, asrc unsafe.Pointer, n uintptr) {
 // direct operations.
 type Value struct {
        // typ holds the type of the value represented by a Value.
-       typ *commonType
+       typ *rtype
 
        // val holds the 1-word representation of the value.
        // If flag's flagIndir bit is set, then val is a pointer to the data.
@@ -211,7 +211,7 @@ func storeIword(p unsafe.Pointer, w iword, n uintptr) {
 
 // emptyInterface is the header for an interface{} value.
 type emptyInterface struct {
-       typ  *runtimeType
+       typ  *rtype
        word iword
 }
 
@@ -219,8 +219,8 @@ type emptyInterface struct {
 type nonEmptyInterface struct {
        // see ../runtime/iface.c:/Itab
        itab *struct {
-               ityp   *runtimeType // static interface type
-               typ    *runtimeType // dynamic concrete type
+               ityp   *rtype // static interface type
+               typ    *rtype // dynamic concrete type
                link   unsafe.Pointer
                bad    int32
                unused int32
@@ -376,7 +376,7 @@ func (v Value) call(method string, in []Value) []Value {
                        if m.pkgPath != nil {
                                panic(method + " of unexported method")
                        }
-                       t = toCommonType(m.typ)
+                       t = m.typ
                        iface := (*nonEmptyInterface)(v.val)
                        if iface.itab == nil {
                                panic(method + " of method on nil interface value")
@@ -393,7 +393,7 @@ func (v Value) call(method string, in []Value) []Value {
                                panic(method + " of unexported method")
                        }
                        fn = m.ifn
-                       t = toCommonType(m.mtyp)
+                       t = m.mtyp
                        rcvr = v.iword()
                }
        } else if v.flag&flagIndir != 0 {
@@ -513,7 +513,7 @@ func (v Value) call(method string, in []Value) []Value {
        }
        for i, v := range in {
                v.mustBeExported()
-               targ := t.In(i).(*commonType)
+               targ := t.In(i).(*rtype)
                a := uintptr(targ.align)
                off = (off + a - 1) &^ (a - 1)
                n := targ.size
@@ -561,7 +561,7 @@ func callReflect(ftyp *funcType, f func([]Value) []Value, frame unsafe.Pointer)
        off := uintptr(0)
        in := make([]Value, 0, len(ftyp.in))
        for _, arg := range ftyp.in {
-               typ := toCommonType(arg)
+               typ := arg
                off += -off & uintptr(typ.align-1)
                v := Value{typ, nil, flag(typ.Kind()) << flagKindShift}
                if typ.size <= ptrSize {
@@ -590,7 +590,7 @@ func callReflect(ftyp *funcType, f func([]Value) []Value, frame unsafe.Pointer)
        if len(ftyp.out) > 0 {
                off += -off & (ptrSize - 1)
                for i, arg := range ftyp.out {
-                       typ := toCommonType(arg)
+                       typ := arg
                        v := out[i]
                        if v.typ != typ {
                                panic("reflect: function created by MakeFunc using " + funcName(f) +
@@ -673,7 +673,7 @@ func (v Value) Elem() Value {
        switch k {
        case Interface:
                var (
-                       typ *commonType
+                       typ *rtype
                        val unsafe.Pointer
                )
                if v.typ.NumMethod() == 0 {
@@ -682,7 +682,7 @@ func (v Value) Elem() Value {
                                // nil interface value
                                return Value{}
                        }
-                       typ = toCommonType(eface.typ)
+                       typ = eface.typ
                        val = unsafe.Pointer(eface.word)
                } else {
                        iface := (*nonEmptyInterface)(v.val)
@@ -690,7 +690,7 @@ func (v Value) Elem() Value {
                                // nil interface value
                                return Value{}
                        }
-                       typ = toCommonType(iface.itab.typ)
+                       typ = iface.itab.typ
                        val = unsafe.Pointer(iface.word)
                }
                fl := v.flag & flagRO
@@ -710,7 +710,7 @@ func (v Value) Elem() Value {
                        return Value{}
                }
                tt := (*ptrType)(unsafe.Pointer(v.typ))
-               typ := toCommonType(tt.elem)
+               typ := tt.elem
                fl := v.flag&flagRO | flagIndir | flagAddr
                fl |= flag(typ.Kind() << flagKindShift)
                return Value{typ, val, fl}
@@ -727,7 +727,7 @@ func (v Value) Field(i int) Value {
                panic("reflect: Field index out of range")
        }
        field := &tt.fields[i]
-       typ := toCommonType(field.typ)
+       typ := field.typ
 
        // Inherit permission bits from v.
        fl := v.flag & (flagRO | flagIndir | flagAddr)
@@ -810,7 +810,7 @@ func (v Value) Float() float64 {
        panic(&ValueError{"reflect.Value.Float", k})
 }
 
-var uint8Type = TypeOf(uint8(0)).(*commonType)
+var uint8Type = TypeOf(uint8(0)).(*rtype)
 
 // Index returns v's i'th element.
 // It panics if v's Kind is not Array, Slice, or String or i is out of range.
@@ -822,7 +822,7 @@ func (v Value) Index(i int) Value {
                if i < 0 || i > int(tt.len) {
                        panic("reflect: array index out of range")
                }
-               typ := toCommonType(tt.elem)
+               typ := tt.elem
                fl := v.flag & (flagRO | flagIndir | flagAddr) // bits same as overall array
                fl |= flag(typ.Kind()) << flagKindShift
                offset := uintptr(i) * typ.size
@@ -850,7 +850,7 @@ func (v Value) Index(i int) Value {
                        panic("reflect: slice index out of range")
                }
                tt := (*sliceType)(unsafe.Pointer(v.typ))
-               typ := toCommonType(tt.elem)
+               typ := tt.elem
                fl |= flag(typ.Kind()) << flagKindShift
                val := unsafe.Pointer(s.Data + uintptr(i)*typ.size)
                return Value{typ, val, fl}
@@ -944,7 +944,7 @@ func valueInterface(v Value, safe bool) interface{} {
 
        // Non-interface value.
        var eface emptyInterface
-       eface.typ = v.typ.runtimeType()
+       eface.typ = v.typ
        eface.word = v.iword()
 
        if v.flag&flagIndir != 0 && v.typ.size > ptrSize {
@@ -1045,13 +1045,13 @@ func (v Value) MapIndex(key Value) Value {
        // considered unexported.  This is consistent with the
        // behavior for structs, which allow read but not write
        // of unexported fields.
-       key = key.assignTo("reflect.Value.MapIndex", toCommonType(tt.key), nil)
+       key = key.assignTo("reflect.Value.MapIndex", tt.key, nil)
 
-       word, ok := mapaccess(v.typ.runtimeType(), v.iword(), key.iword())
+       word, ok := mapaccess(v.typ, v.iword(), key.iword())
        if !ok {
                return Value{}
        }
-       typ := toCommonType(tt.elem)
+       typ := tt.elem
        fl := (v.flag | key.flag) & flagRO
        if typ.size > ptrSize {
                fl |= flagIndir
@@ -1067,7 +1067,7 @@ func (v Value) MapIndex(key Value) Value {
 func (v Value) MapKeys() []Value {
        v.mustBe(Map)
        tt := (*mapType)(unsafe.Pointer(v.typ))
-       keyType := toCommonType(tt.key)
+       keyType := tt.key
 
        fl := v.flag & flagRO
        fl |= flag(keyType.Kind()) << flagKindShift
@@ -1080,7 +1080,7 @@ func (v Value) MapKeys() []Value {
        if m != nil {
                mlen = maplen(m)
        }
-       it := mapiterinit(v.typ.runtimeType(), m)
+       it := mapiterinit(v.typ, m)
        a := make([]Value, mlen)
        var i int
        for i = 0; i < len(a); i++ {
@@ -1249,9 +1249,9 @@ func (v Value) recv(nb bool) (val Value, ok bool) {
        if ChanDir(tt.dir)&RecvDir == 0 {
                panic("recv on send-only channel")
        }
-       word, selected, ok := chanrecv(v.typ.runtimeType(), v.iword(), nb)
+       word, selected, ok := chanrecv(v.typ, v.iword(), nb)
        if selected {
-               typ := toCommonType(tt.elem)
+               typ := tt.elem
                fl := flag(typ.Kind()) << flagKindShift
                if typ.size > ptrSize {
                        fl |= flagIndir
@@ -1278,8 +1278,8 @@ func (v Value) send(x Value, nb bool) (selected bool) {
                panic("send on recv-only channel")
        }
        x.mustBeExported()
-       x = x.assignTo("reflect.Value.Send", toCommonType(tt.elem), nil)
-       return chansend(v.typ.runtimeType(), v.iword(), x.iword(), nb)
+       x = x.assignTo("reflect.Value.Send", tt.elem, nil)
+       return chansend(v.typ, v.iword(), x.iword(), nb)
 }
 
 // Set assigns x to the value v.
@@ -1401,12 +1401,12 @@ func (v Value) SetMapIndex(key, val Value) {
        v.mustBeExported()
        key.mustBeExported()
        tt := (*mapType)(unsafe.Pointer(v.typ))
-       key = key.assignTo("reflect.Value.SetMapIndex", toCommonType(tt.key), nil)
+       key = key.assignTo("reflect.Value.SetMapIndex", tt.key, nil)
        if val.typ != nil {
                val.mustBeExported()
-               val = val.assignTo("reflect.Value.SetMapIndex", toCommonType(tt.elem), nil)
+               val = val.assignTo("reflect.Value.SetMapIndex", tt.elem, nil)
        }
-       mapassign(v.typ.runtimeType(), v.iword(), key.iword(), val.iword(), val.typ != nil)
+       mapassign(v.typ, v.iword(), key.iword(), val.iword(), val.typ != nil)
 }
 
 // SetUint sets v's underlying value to x.
@@ -1465,7 +1465,7 @@ func (v Value) Slice(beg, end int) Value {
                }
                tt := (*arrayType)(unsafe.Pointer(v.typ))
                cap = int(tt.len)
-               typ = (*sliceType)(unsafe.Pointer(toCommonType(tt.slice)))
+               typ = (*sliceType)(unsafe.Pointer(tt.slice))
                base = v.val
 
        case Slice:
@@ -1495,7 +1495,7 @@ func (v Value) Slice(beg, end int) Value {
 
        // Reinterpret as *SliceHeader to edit.
        s := (*SliceHeader)(unsafe.Pointer(&x))
-       s.Data = uintptr(base) + uintptr(beg)*toCommonType(typ.elem).Size()
+       s.Data = uintptr(base) + uintptr(beg)*typ.elem.Size()
        s.Len = end - beg
        s.Cap = cap - beg
 
@@ -1561,7 +1561,7 @@ func (v Value) Type() Type {
                        panic("reflect: broken Value")
                }
                m := &tt.methods[i]
-               return toCommonType(m.typ)
+               return m.typ
        }
        // Method on concrete type.
        ut := v.typ.uncommon()
@@ -1569,7 +1569,7 @@ func (v Value) Type() Type {
                panic("reflect: broken Value")
        }
        m := &ut.methods[i]
-       return toCommonType(m.mtyp)
+       return m.mtyp
 }
 
 // Uint returns v's underlying value, as a uint64.
@@ -1743,10 +1743,10 @@ func Copy(dst, src Value) int {
 // A runtimeSelect is a single case passed to rselect.
 // This must match ../runtime/chan.c:/runtimeSelect
 type runtimeSelect struct {
-       dir uintptr      // 0, SendDir, or RecvDir
-       typ *runtimeType // channel type
-       ch  iword        // interface word for channel
-       val iword        // interface word for value (for SendDir)
+       dir uintptr // 0, SendDir, or RecvDir
+       typ *rtype  // channel type
+       ch  iword   // interface word for channel
+       val iword   // interface word for value (for SendDir)
 }
 
 // rselect runs a select. It returns the index of the chosen case,
@@ -1833,13 +1833,13 @@ func Select(cases []SelectCase) (chosen int, recv Value, recvOK bool) {
                                panic("reflect.Select: SendDir case using recv-only channel")
                        }
                        rc.ch = ch.iword()
-                       rc.typ = tt.runtimeType()
+                       rc.typ = &tt.rtype
                        v := c.Send
                        if !v.IsValid() {
                                panic("reflect.Select: SendDir case missing Send value")
                        }
                        v.mustBeExported()
-                       v = v.assignTo("reflect.Select", toCommonType(tt.elem), nil)
+                       v = v.assignTo("reflect.Select", tt.elem, nil)
                        rc.val = v.iword()
 
                case SelectRecv:
@@ -1853,7 +1853,7 @@ func Select(cases []SelectCase) (chosen int, recv Value, recvOK bool) {
                        ch.mustBe(Chan)
                        ch.mustBeExported()
                        tt := (*chanType)(unsafe.Pointer(ch.typ))
-                       rc.typ = tt.runtimeType()
+                       rc.typ = &tt.rtype
                        if ChanDir(tt.dir)&RecvDir == 0 {
                                panic("reflect.Select: RecvDir case using send-only channel")
                        }
@@ -1863,8 +1863,8 @@ func Select(cases []SelectCase) (chosen int, recv Value, recvOK bool) {
 
        chosen, word, recvOK := rselect(runcases)
        if runcases[chosen].dir == uintptr(SelectRecv) {
-               tt := (*chanType)(unsafe.Pointer(toCommonType(runcases[chosen].typ)))
-               typ := toCommonType(tt.elem)
+               tt := (*chanType)(unsafe.Pointer(runcases[chosen].typ))
+               typ := tt.elem
                fl := flag(typ.Kind()) << flagKindShift
                if typ.size > ptrSize {
                        fl |= flagIndir
@@ -1879,8 +1879,8 @@ func Select(cases []SelectCase) (chosen int, recv Value, recvOK bool) {
  */
 
 // implemented in package runtime
-func unsafe_New(Type) unsafe.Pointer
-func unsafe_NewArray(Type, int) unsafe.Pointer
+func unsafe_New(*rtype) unsafe.Pointer
+func unsafe_NewArray(*rtype, int) unsafe.Pointer
 
 // MakeSlice creates a new zero-initialized slice value
 // for the specified slice type, length, and capacity.
@@ -1903,7 +1903,7 @@ func MakeSlice(typ Type, len, cap int) Value {
 
        // Reinterpret as *SliceHeader to edit.
        s := (*SliceHeader)(unsafe.Pointer(&x))
-       s.Data = uintptr(unsafe_NewArray(typ.Elem(), cap))
+       s.Data = uintptr(unsafe_NewArray(typ.Elem().(*rtype), cap))
        s.Len = len
        s.Cap = cap
 
@@ -1921,7 +1921,7 @@ func MakeChan(typ Type, buffer int) Value {
        if typ.ChanDir() != BothDir {
                panic("reflect.MakeChan: unidirectional channel type")
        }
-       ch := makechan(typ.runtimeType(), uint64(buffer))
+       ch := makechan(typ.(*rtype), uint64(buffer))
        return Value{typ.common(), unsafe.Pointer(ch), flag(Chan) << flagKindShift}
 }
 
@@ -1930,7 +1930,7 @@ func MakeMap(typ Type) Value {
        if typ.Kind() != Map {
                panic("reflect.MakeMap of non-map type")
        }
-       m := makemap(typ.runtimeType())
+       m := makemap(typ.(*rtype))
        return Value{typ.common(), unsafe.Pointer(m), flag(Map) << flagKindShift}
 }
 
@@ -1961,7 +1961,7 @@ func ValueOf(i interface{}) Value {
        // For an interface value with the noAddr bit set,
        // the representation is identical to an empty interface.
        eface := *(*emptyInterface)(unsafe.Pointer(&i))
-       typ := toCommonType(eface.typ)
+       typ := eface.typ
        fl := flag(typ.Kind()) << flagKindShift
        if typ.size > ptrSize {
                fl |= flagIndir
@@ -1983,7 +1983,7 @@ func Zero(typ Type) Value {
        if t.size <= ptrSize {
                return Value{t, nil, fl}
        }
-       return Value{t, unsafe_New(typ), fl | flagIndir}
+       return Value{t, unsafe_New(typ.(*rtype)), fl | flagIndir}
 }
 
 // New returns a Value representing a pointer to a new zero value
@@ -1992,7 +1992,7 @@ func New(typ Type) Value {
        if typ == nil {
                panic("reflect: New(nil)")
        }
-       ptr := unsafe_New(typ)
+       ptr := unsafe_New(typ.(*rtype))
        fl := flag(Ptr) << flagKindShift
        return Value{typ.common().ptrTo(), ptr, fl}
 }
@@ -2007,7 +2007,7 @@ func NewAt(typ Type, p unsafe.Pointer) Value {
 // assignTo returns a value v that can be assigned directly 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.
-func (v Value) assignTo(context string, dst *commonType, target *interface{}) Value {
+func (v Value) assignTo(context string, dst *rtype, target *interface{}) Value {
        if v.flag&flagMethod != 0 {
                panic(context + ": cannot assign method value to type " + dst.String())
        }
@@ -2029,7 +2029,7 @@ func (v Value) assignTo(context string, dst *commonType, target *interface{}) Va
                if dst.NumMethod() == 0 {
                        *target = x
                } else {
-                       ifaceE2I(dst.runtimeType(), x, unsafe.Pointer(target))
+                       ifaceE2I(dst, x, unsafe.Pointer(target))
                }
                return Value{dst, unsafe.Pointer(target), flagIndir | flag(Interface)<<flagKindShift}
        }
@@ -2054,7 +2054,7 @@ func (v Value) Convert(t Type) Value {
 
 // convertOp returns the function to convert a value of type src
 // to a value of type dst. If the conversion is illegal, convertOp returns nil.
-func convertOp(dst, src *commonType) func(Value, Type) Value {
+func convertOp(dst, src *rtype) func(Value, Type) Value {
        switch src.Kind() {
        case Int, Int8, Int16, Int32, Int64:
                switch dst.Kind() {
@@ -2141,7 +2141,7 @@ func makeInt(f flag, bits uint64, t Type) Value {
        typ := t.common()
        if typ.size > ptrSize {
                // Assume ptrSize >= 4, so this must be uint64.
-               ptr := unsafe_New(t)
+               ptr := unsafe_New(typ)
                *(*uint64)(unsafe.Pointer(ptr)) = bits
                return Value{typ, ptr, f | flag(typ.Kind())<<flagKindShift}
        }
@@ -2165,7 +2165,7 @@ func makeFloat(f flag, v float64, t Type) Value {
        typ := t.common()
        if typ.size > ptrSize {
                // Assume ptrSize >= 4, so this must be float64.
-               ptr := unsafe_New(t)
+               ptr := unsafe_New(typ)
                *(*float64)(unsafe.Pointer(ptr)) = v
                return Value{typ, ptr, f | flag(typ.Kind())<<flagKindShift}
        }
@@ -2185,7 +2185,7 @@ func makeFloat(f flag, v float64, t Type) Value {
 func makeComplex(f flag, v complex128, t Type) Value {
        typ := t.common()
        if typ.size > ptrSize {
-               ptr := unsafe_New(t)
+               ptr := unsafe_New(typ)
                switch typ.size {
                case 8:
                        *(*complex64)(unsafe.Pointer(ptr)) = complex64(v)
@@ -2319,7 +2319,7 @@ func cvtT2I(v Value, typ Type) Value {
        if typ.NumMethod() == 0 {
                *target = x
        } else {
-               ifaceE2I(typ.runtimeType(), x, unsafe.Pointer(target))
+               ifaceE2I(typ.(*rtype), x, unsafe.Pointer(target))
        }
        return Value{typ.common(), unsafe.Pointer(target), v.flag&flagRO | flagIndir | flag(Interface)<<flagKindShift}
 }
@@ -2338,20 +2338,20 @@ func cvtI2I(v Value, typ Type) Value {
 func chancap(ch iword) int
 func chanclose(ch iword)
 func chanlen(ch iword) int
-func chanrecv(t *runtimeType, ch iword, nb bool) (val iword, selected, received bool)
-func chansend(t *runtimeType, ch iword, val iword, nb bool) bool
-
-func makechan(typ *runtimeType, size uint64) (ch iword)
-func makemap(t *runtimeType) (m iword)
-func mapaccess(t *runtimeType, m iword, key iword) (val iword, ok bool)
-func mapassign(t *runtimeType, m iword, key, val iword, ok bool)
-func mapiterinit(t *runtimeType, m iword) *byte
+func chanrecv(t *rtype, ch iword, nb bool) (val iword, selected, received bool)
+func chansend(t *rtype, ch iword, val iword, nb bool) bool
+
+func makechan(typ *rtype, size uint64) (ch iword)
+func makemap(t *rtype) (m iword)
+func mapaccess(t *rtype, m iword, key iword) (val iword, ok bool)
+func mapassign(t *rtype, m iword, key, val iword, ok bool)
+func mapiterinit(t *rtype, m iword) *byte
 func mapiterkey(it *byte) (key iword, ok bool)
 func mapiternext(it *byte)
 func maplen(m iword) int
 
 func call(fn, arg unsafe.Pointer, n uint32)
-func ifaceE2I(t *runtimeType, src interface{}, dst unsafe.Pointer)
+func ifaceE2I(t *rtype, src interface{}, dst unsafe.Pointer)
 
 // Dummy annotation marking that the value x escapes,
 // for use in cases where the reflect code is so clever that
index f12ff7626d7e671397c81cb47d7dad4abbb25005..3a7c45fd140f576fcf559c40b1e035476c41d7cc 100644 (file)
@@ -686,17 +686,10 @@ reflect·unsafe_Typeof(Eface e, Eface ret)
 }
 
 void
-reflect·unsafe_New(Eface typ, void *ret)
+reflect·unsafe_New(Type *t, void *ret)
 {
-       Type *t;
        uint32 flag;
 
-       // 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.
-       t = (Type*)((Eface*)typ.data-1);
-
        flag = t->kind&KindNoPointers ? FlagNoPointers : 0;
        ret = runtime·mallocgc(t->size, flag, 1, 1);
 
@@ -711,16 +704,9 @@ reflect·unsafe_New(Eface typ, void *ret)
 }
 
 void
-reflect·unsafe_NewArray(Eface typ, intgo n, void *ret)
+reflect·unsafe_NewArray(Type *t, intgo n, void *ret)
 {
        uint64 size;
-       Type *t;
-
-       // 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.
-       t = (Type*)((Eface*)typ.data-1);
 
        size = n*t->size;
        if(size == 0)
@@ -740,3 +726,14 @@ reflect·unsafe_NewArray(Eface typ, intgo n, void *ret)
 
        FLUSH(&ret);
 }
+
+void
+reflect·typelinks(Slice ret)
+{
+       extern Type *typelink[], *etypelink[];
+       static int32 first = 1;
+       ret.array = (byte*)typelink;
+       ret.len = etypelink - typelink;
+       ret.cap = ret.len;
+       FLUSH(&ret);
+}
index 629c39e98d0ba2a9c511ffeed06e5768c05f0a18..b32a670e2673f1c31437004f7e3b02c2abe46cff 100644 (file)
@@ -149,8 +149,8 @@ goobjfile.pretty_printers.extend([makematcher(k) for k in vars().values() if has
 
 #
 #  For reference, this is what we're trying to do:
-#  eface: p *(*(struct 'runtime.commonType'*)'main.e'->type_->data)->string
-#  iface: p *(*(struct 'runtime.commonType'*)'main.s'->tab->Type->data)->string
+#  eface: p *(*(struct 'runtime.rtype'*)'main.e'->type_->data)->string
+#  iface: p *(*(struct 'runtime.rtype'*)'main.s'->tab->Type->data)->string
 #
 # interface types can't be recognized by their name, instead we check
 # if they have the expected fields.  Unfortunately the mapping of
@@ -186,8 +186,7 @@ def lookup_type(name):
        except:
                pass
 
-_rctp_type = gdb.lookup_type("struct runtime.commonType").pointer()
-_rtp_type = gdb.lookup_type("struct runtime._type").pointer()
+_rctp_type = gdb.lookup_type("struct runtime.rtype").pointer()
 
 def iface_commontype(obj):
        if is_iface(obj):
@@ -196,18 +195,13 @@ def iface_commontype(obj):
                go_type_ptr = obj['_type']
        else:
                return
-
-       # sanity check: reflection type description ends in a loop.
-       tt = go_type_ptr['_type'].cast(_rtp_type).dereference()['_type']
-       if tt != tt.cast(_rtp_type).dereference()['_type']:
-               return
        
-       return go_type_ptr['ptr'].cast(_rctp_type).dereference()
+       return go_type_ptr.cast(_rctp_type).dereference()
        
 
 def iface_dtype(obj):
        "Decode type of the data field of an eface or iface struct."
-       # known issue: dtype_name decoded from runtime.commonType is "nested.Foo"
+       # known issue: dtype_name decoded from runtime.rtype is "nested.Foo"
        # but the dwarf table lists it as "full/path/to/nested.Foo"
 
        dynamic_go_type = iface_commontype(obj)
index 8ec850f9bf363e9a4dd421fcba261435472c72d5..374754afaf410de8a6e21059f3a58a4fc0d24c47 100644 (file)
@@ -14,7 +14,7 @@ package runtime
 
 import "unsafe"
 
-type commonType struct {
+type rtype struct {
        size       uintptr
        hash       uint32
        _          uint8
@@ -25,14 +25,14 @@ type commonType struct {
        gc         unsafe.Pointer
        string     *string
        *uncommonType
-       ptrToThis *interface{}
+       ptrToThis *rtype
 }
 
 type _method struct {
        name    *string
        pkgPath *string
-       mtyp    *interface{}
-       typ     *interface{}
+       mtyp    *rtype
+       typ     *rtype
        ifn     unsafe.Pointer
        tfn     unsafe.Pointer
 }
@@ -46,10 +46,10 @@ type uncommonType struct {
 type _imethod struct {
        name    *string
        pkgPath *string
-       typ     *interface{}
+       typ     *rtype
 }
 
 type interfaceType struct {
-       commonType
+       rtype
        methods []_imethod
 }
index dc636902f76136b6b5e56a1dd371b6ee435070a5..769a8071b73534b4c95d846a5aebaf0297511a69 100644 (file)
@@ -5,13 +5,10 @@
 /*
  * Runtime type representation; master is type.go
  *
- * The *Types here correspond 1-1 to type.go's *Type's, but are
- * prefixed with an extra header of 2 pointers, corresponding to the
- * interface{} structure, which itself is called type Type again on
- * the Go side.
+ * The Type*s here correspond 1-1 to type.go's *rtype.
  */
 
-typedef struct CommonType CommonType;
+typedef struct Type Type;
 typedef struct UncommonType UncommonType;
 typedef struct InterfaceType InterfaceType;
 typedef struct Method Method;
@@ -21,7 +18,7 @@ typedef struct FuncType FuncType;
 typedef struct PtrType PtrType;
 
 // Needs to be in sync with typekind.h/CommonSize
-struct CommonType
+struct Type
 {
        uintptr size;
        uint32 hash;
@@ -54,13 +51,6 @@ struct UncommonType
        Method m[];
 };
 
-struct Type
-{
-       void *type;     // interface{} value
-       void *ptr;
-       CommonType;
-};
-
 struct IMethod
 {
        String *name;
index 97cb0a5a2dbc5f759fe269b0c5905edfed0a2bad..9bae2a8710c31edc96d0caff86ac60304bfd4a1e 100644 (file)
@@ -35,7 +35,7 @@ enum {
 
        KindNoPointers = 1<<7,
 
-       // size of Type interface header + CommonType structure.
-       CommonSize = 2*PtrSize + 6*PtrSize + 8,
+       // size of Type structure.
+       CommonSize = 6*PtrSize + 8,
 };