github.com/miolini/go@v0.0.0-20160405192216-fca68c8cb408/src/runtime/type.go (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Runtime type representation.
     6  
     7  package runtime
     8  
     9  import (
    10  	"runtime/internal/sys"
    11  	"unsafe"
    12  )
    13  
    14  // tflag is documented in ../reflect/type.go.
    15  type tflag uint8
    16  
    17  const tflagUncommon tflag = 1
    18  
    19  // Needs to be in sync with ../cmd/compile/internal/ld/decodesym.go:/^func.commonsize,
    20  // ../cmd/compile/internal/gc/reflect.go:/^func.dcommontype and
    21  // ../reflect/type.go:/^type.rtype.
    22  type _type struct {
    23  	size       uintptr
    24  	ptrdata    uintptr // size of memory prefix holding all pointers
    25  	hash       uint32
    26  	tflag      tflag
    27  	align      uint8
    28  	fieldalign uint8
    29  	kind       uint8
    30  	alg        *typeAlg
    31  	// gcdata stores the GC type data for the garbage collector.
    32  	// If the KindGCProg bit is set in kind, gcdata is a GC program.
    33  	// Otherwise it is a ptrmask bitmap. See mbitmap.go for details.
    34  	gcdata  *byte
    35  	_string string
    36  }
    37  
    38  func (t *_type) uncommon() *uncommontype {
    39  	if t.tflag&tflagUncommon == 0 {
    40  		return nil
    41  	}
    42  	switch t.kind & kindMask {
    43  	case kindStruct:
    44  		type u struct {
    45  			structtype
    46  			u uncommontype
    47  		}
    48  		return &(*u)(unsafe.Pointer(t)).u
    49  	case kindPtr:
    50  		type u struct {
    51  			ptrtype
    52  			u uncommontype
    53  		}
    54  		return &(*u)(unsafe.Pointer(t)).u
    55  	case kindFunc:
    56  		type u struct {
    57  			functype
    58  			u uncommontype
    59  		}
    60  		return &(*u)(unsafe.Pointer(t)).u
    61  	case kindSlice:
    62  		type u struct {
    63  			slicetype
    64  			u uncommontype
    65  		}
    66  		return &(*u)(unsafe.Pointer(t)).u
    67  	case kindArray:
    68  		type u struct {
    69  			arraytype
    70  			u uncommontype
    71  		}
    72  		return &(*u)(unsafe.Pointer(t)).u
    73  	case kindChan:
    74  		type u struct {
    75  			chantype
    76  			u uncommontype
    77  		}
    78  		return &(*u)(unsafe.Pointer(t)).u
    79  	case kindMap:
    80  		type u struct {
    81  			maptype
    82  			u uncommontype
    83  		}
    84  		return &(*u)(unsafe.Pointer(t)).u
    85  	case kindInterface:
    86  		type u struct {
    87  			interfacetype
    88  			u uncommontype
    89  		}
    90  		return &(*u)(unsafe.Pointer(t)).u
    91  	default:
    92  		type u struct {
    93  			_type
    94  			u uncommontype
    95  		}
    96  		return &(*u)(unsafe.Pointer(t)).u
    97  	}
    98  }
    99  
   100  func hasPrefix(s, prefix string) bool {
   101  	return len(s) >= len(prefix) && s[:len(prefix)] == prefix
   102  }
   103  
   104  func (t *_type) name() string {
   105  	if hasPrefix(t._string, "map[") {
   106  		return ""
   107  	}
   108  	if hasPrefix(t._string, "struct {") {
   109  		return ""
   110  	}
   111  	if hasPrefix(t._string, "chan ") {
   112  		return ""
   113  	}
   114  	if hasPrefix(t._string, "chan<-") {
   115  		return ""
   116  	}
   117  	if hasPrefix(t._string, "func(") {
   118  		return ""
   119  	}
   120  	switch t._string[0] {
   121  	case '[', '*', '<':
   122  		return ""
   123  	}
   124  	i := len(t._string) - 1
   125  	for i >= 0 {
   126  		if t._string[i] == '.' {
   127  			break
   128  		}
   129  		i--
   130  	}
   131  	return t._string[i+1:]
   132  }
   133  
   134  func (t *functype) in() []*_type {
   135  	// See funcType in reflect/type.go for details on data layout.
   136  	uadd := uintptr(unsafe.Sizeof(functype{}))
   137  	if t.typ.tflag&tflagUncommon != 0 {
   138  		uadd += unsafe.Sizeof(uncommontype{})
   139  	}
   140  	return (*[1 << 20]*_type)(add(unsafe.Pointer(t), uadd))[:t.inCount]
   141  }
   142  
   143  func (t *functype) out() []*_type {
   144  	// See funcType in reflect/type.go for details on data layout.
   145  	uadd := uintptr(unsafe.Sizeof(functype{}))
   146  	if t.typ.tflag&tflagUncommon != 0 {
   147  		uadd += unsafe.Sizeof(uncommontype{})
   148  	}
   149  	outCount := t.outCount & (1<<15 - 1)
   150  	return (*[1 << 20]*_type)(add(unsafe.Pointer(t), uadd))[t.inCount : t.inCount+outCount]
   151  }
   152  
   153  func (t *functype) dotdotdot() bool {
   154  	return t.outCount&(1<<15) != 0
   155  }
   156  
   157  type method struct {
   158  	name name
   159  	mtyp *_type
   160  	ifn  unsafe.Pointer
   161  	tfn  unsafe.Pointer
   162  }
   163  
   164  type uncommontype struct {
   165  	pkgpath *string
   166  	mhdr    []method
   167  }
   168  
   169  type imethod struct {
   170  	name  name
   171  	_type *_type
   172  }
   173  
   174  type interfacetype struct {
   175  	typ     _type
   176  	pkgpath *string
   177  	mhdr    []imethod
   178  }
   179  
   180  type maptype struct {
   181  	typ           _type
   182  	key           *_type
   183  	elem          *_type
   184  	bucket        *_type // internal type representing a hash bucket
   185  	hmap          *_type // internal type representing a hmap
   186  	keysize       uint8  // size of key slot
   187  	indirectkey   bool   // store ptr to key instead of key itself
   188  	valuesize     uint8  // size of value slot
   189  	indirectvalue bool   // store ptr to value instead of value itself
   190  	bucketsize    uint16 // size of bucket
   191  	reflexivekey  bool   // true if k==k for all keys
   192  	needkeyupdate bool   // true if we need to update key on an overwrite
   193  }
   194  
   195  type arraytype struct {
   196  	typ   _type
   197  	elem  *_type
   198  	slice *_type
   199  	len   uintptr
   200  }
   201  
   202  type chantype struct {
   203  	typ  _type
   204  	elem *_type
   205  	dir  uintptr
   206  }
   207  
   208  type slicetype struct {
   209  	typ  _type
   210  	elem *_type
   211  }
   212  
   213  type functype struct {
   214  	typ      _type
   215  	inCount  uint16
   216  	outCount uint16
   217  }
   218  
   219  type ptrtype struct {
   220  	typ  _type
   221  	elem *_type
   222  }
   223  
   224  type structfield struct {
   225  	name   name
   226  	typ    *_type
   227  	offset uintptr
   228  }
   229  
   230  type structtype struct {
   231  	typ     _type
   232  	pkgPath *string
   233  	fields  []structfield
   234  }
   235  
   236  // name is an encoded type name with optional extra data.
   237  // See reflect/type.go for details.
   238  type name struct {
   239  	bytes *byte
   240  }
   241  
   242  func (n *name) data(off int) *byte {
   243  	return (*byte)(add(unsafe.Pointer(n.bytes), uintptr(off)))
   244  }
   245  
   246  func (n *name) isExported() bool {
   247  	return (*n.bytes)&(1<<0) != 0
   248  }
   249  
   250  func (n *name) nameLen() int {
   251  	return int(uint16(*n.data(1))<<8 | uint16(*n.data(2)))
   252  }
   253  
   254  func (n *name) tagLen() int {
   255  	if *n.data(0)&(1<<1) == 0 {
   256  		return 0
   257  	}
   258  	off := 3 + n.nameLen()
   259  	return int(uint16(*n.data(off))<<8 | uint16(*n.data(off + 1)))
   260  }
   261  
   262  func (n *name) name() (s string) {
   263  	nl := n.nameLen()
   264  	if nl == 0 {
   265  		return ""
   266  	}
   267  	hdr := (*stringStruct)(unsafe.Pointer(&s))
   268  	hdr.str = unsafe.Pointer(n.data(3))
   269  	hdr.len = nl
   270  	return s
   271  }
   272  
   273  func (n *name) pkgPath() *string {
   274  	if *n.data(0)&(1<<2) == 0 {
   275  		return nil
   276  	}
   277  	off := 3 + n.nameLen()
   278  	if tl := n.tagLen(); tl > 0 {
   279  		off += 2 + tl
   280  	}
   281  	off = int(round(uintptr(off), sys.PtrSize))
   282  	return *(**string)(unsafe.Pointer(n.data(off)))
   283  }