golang.org/toolchain@v0.0.1-go1.9rc2.windows-amd64/src/runtime/iface.go (about)

     1  // Copyright 2014 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  package runtime
     6  
     7  import (
     8  	"runtime/internal/atomic"
     9  	"runtime/internal/sys"
    10  	"unsafe"
    11  )
    12  
    13  const (
    14  	hashSize = 1009
    15  )
    16  
    17  var (
    18  	ifaceLock mutex // lock for accessing hash
    19  	hash      [hashSize]*itab
    20  )
    21  
    22  func itabhash(inter *interfacetype, typ *_type) uint32 {
    23  	// compiler has provided some good hash codes for us.
    24  	h := inter.typ.hash
    25  	h += 17 * typ.hash
    26  	// TODO(rsc): h += 23 * x.mhash ?
    27  	return h % hashSize
    28  }
    29  
    30  func getitab(inter *interfacetype, typ *_type, canfail bool) *itab {
    31  	if len(inter.mhdr) == 0 {
    32  		throw("internal error - misuse of itab")
    33  	}
    34  
    35  	// easy case
    36  	if typ.tflag&tflagUncommon == 0 {
    37  		if canfail {
    38  			return nil
    39  		}
    40  		name := inter.typ.nameOff(inter.mhdr[0].name)
    41  		panic(&TypeAssertionError{"", typ.string(), inter.typ.string(), name.name()})
    42  	}
    43  
    44  	h := itabhash(inter, typ)
    45  
    46  	// look twice - once without lock, once with.
    47  	// common case will be no lock contention.
    48  	var m *itab
    49  	var locked int
    50  	for locked = 0; locked < 2; locked++ {
    51  		if locked != 0 {
    52  			lock(&ifaceLock)
    53  		}
    54  		for m = (*itab)(atomic.Loadp(unsafe.Pointer(&hash[h]))); m != nil; m = m.link {
    55  			if m.inter == inter && m._type == typ {
    56  				if m.bad {
    57  					if !canfail {
    58  						// this can only happen if the conversion
    59  						// was already done once using the , ok form
    60  						// and we have a cached negative result.
    61  						// the cached result doesn't record which
    62  						// interface function was missing, so try
    63  						// adding the itab again, which will throw an error.
    64  						additab(m, locked != 0, false)
    65  					}
    66  					m = nil
    67  				}
    68  				if locked != 0 {
    69  					unlock(&ifaceLock)
    70  				}
    71  				return m
    72  			}
    73  		}
    74  	}
    75  
    76  	m = (*itab)(persistentalloc(unsafe.Sizeof(itab{})+uintptr(len(inter.mhdr)-1)*sys.PtrSize, 0, &memstats.other_sys))
    77  	m.inter = inter
    78  	m._type = typ
    79  	additab(m, true, canfail)
    80  	unlock(&ifaceLock)
    81  	if m.bad {
    82  		return nil
    83  	}
    84  	return m
    85  }
    86  
    87  func additab(m *itab, locked, canfail bool) {
    88  	inter := m.inter
    89  	typ := m._type
    90  	x := typ.uncommon()
    91  
    92  	// both inter and typ have method sorted by name,
    93  	// and interface names are unique,
    94  	// so can iterate over both in lock step;
    95  	// the loop is O(ni+nt) not O(ni*nt).
    96  	ni := len(inter.mhdr)
    97  	nt := int(x.mcount)
    98  	xmhdr := (*[1 << 16]method)(add(unsafe.Pointer(x), uintptr(x.moff)))[:nt:nt]
    99  	j := 0
   100  	for k := 0; k < ni; k++ {
   101  		i := &inter.mhdr[k]
   102  		itype := inter.typ.typeOff(i.ityp)
   103  		name := inter.typ.nameOff(i.name)
   104  		iname := name.name()
   105  		ipkg := name.pkgPath()
   106  		if ipkg == "" {
   107  			ipkg = inter.pkgpath.name()
   108  		}
   109  		for ; j < nt; j++ {
   110  			t := &xmhdr[j]
   111  			tname := typ.nameOff(t.name)
   112  			if typ.typeOff(t.mtyp) == itype && tname.name() == iname {
   113  				pkgPath := tname.pkgPath()
   114  				if pkgPath == "" {
   115  					pkgPath = typ.nameOff(x.pkgpath).name()
   116  				}
   117  				if tname.isExported() || pkgPath == ipkg {
   118  					if m != nil {
   119  						ifn := typ.textOff(t.ifn)
   120  						*(*unsafe.Pointer)(add(unsafe.Pointer(&m.fun[0]), uintptr(k)*sys.PtrSize)) = ifn
   121  					}
   122  					goto nextimethod
   123  				}
   124  			}
   125  		}
   126  		// didn't find method
   127  		if !canfail {
   128  			if locked {
   129  				unlock(&ifaceLock)
   130  			}
   131  			panic(&TypeAssertionError{"", typ.string(), inter.typ.string(), iname})
   132  		}
   133  		m.bad = true
   134  		break
   135  	nextimethod:
   136  	}
   137  	if !locked {
   138  		throw("invalid itab locking")
   139  	}
   140  	h := itabhash(inter, typ)
   141  	m.link = hash[h]
   142  	m.inhash = true
   143  	atomicstorep(unsafe.Pointer(&hash[h]), unsafe.Pointer(m))
   144  }
   145  
   146  func itabsinit() {
   147  	lock(&ifaceLock)
   148  	for _, md := range activeModules() {
   149  		for _, i := range md.itablinks {
   150  			// itablinks is a slice of pointers to the itabs used in this
   151  			// module. A given itab may be used in more than one module
   152  			// and thanks to the way global symbol resolution works, the
   153  			// pointed-to itab may already have been inserted into the
   154  			// global 'hash'.
   155  			if !i.inhash {
   156  				additab(i, true, false)
   157  			}
   158  		}
   159  	}
   160  	unlock(&ifaceLock)
   161  }
   162  
   163  // panicdottypeE is called when doing an e.(T) conversion and the conversion fails.
   164  // have = the dynamic type we have.
   165  // want = the static type we're trying to convert to.
   166  // iface = the static type we're converting from.
   167  func panicdottypeE(have, want, iface *_type) {
   168  	haveString := ""
   169  	if have != nil {
   170  		haveString = have.string()
   171  	}
   172  	panic(&TypeAssertionError{iface.string(), haveString, want.string(), ""})
   173  }
   174  
   175  // panicdottypeI is called when doing an i.(T) conversion and the conversion fails.
   176  // Same args as panicdottypeE, but "have" is the dynamic itab we have.
   177  func panicdottypeI(have *itab, want, iface *_type) {
   178  	var t *_type
   179  	if have != nil {
   180  		t = have._type
   181  	}
   182  	panicdottypeE(t, want, iface)
   183  }
   184  
   185  // panicnildottype is called when doing a i.(T) conversion and the interface i is nil.
   186  // want = the static type we're trying to convert to.
   187  func panicnildottype(want *_type) {
   188  	panic(&TypeAssertionError{"", "", want.string(), ""})
   189  	// TODO: Add the static type we're converting from as well.
   190  	// It might generate a better error message.
   191  	// Just to match other nil conversion errors, we don't for now.
   192  }
   193  
   194  // The conv and assert functions below do very similar things.
   195  // The convXXX functions are guaranteed by the compiler to succeed.
   196  // The assertXXX functions may fail (either panicking or returning false,
   197  // depending on whether they are 1-result or 2-result).
   198  // The convXXX functions succeed on a nil input, whereas the assertXXX
   199  // functions fail on a nil input.
   200  
   201  func convT2E(t *_type, elem unsafe.Pointer) (e eface) {
   202  	if raceenabled {
   203  		raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&t)), funcPC(convT2E))
   204  	}
   205  	if msanenabled {
   206  		msanread(elem, t.size)
   207  	}
   208  	x := mallocgc(t.size, t, true)
   209  	// TODO: We allocate a zeroed object only to overwrite it with actual data.
   210  	// Figure out how to avoid zeroing. Also below in convT2Eslice, convT2I, convT2Islice.
   211  	typedmemmove(t, x, elem)
   212  	e._type = t
   213  	e.data = x
   214  	return
   215  }
   216  
   217  func convT2E16(t *_type, elem unsafe.Pointer) (e eface) {
   218  	if raceenabled {
   219  		raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&t)), funcPC(convT2E16))
   220  	}
   221  	if msanenabled {
   222  		msanread(elem, t.size)
   223  	}
   224  	var x unsafe.Pointer
   225  	if *(*uint16)(elem) == 0 {
   226  		x = unsafe.Pointer(&zeroVal[0])
   227  	} else {
   228  		x = mallocgc(2, t, false)
   229  		*(*uint16)(x) = *(*uint16)(elem)
   230  	}
   231  	e._type = t
   232  	e.data = x
   233  	return
   234  }
   235  
   236  func convT2E32(t *_type, elem unsafe.Pointer) (e eface) {
   237  	if raceenabled {
   238  		raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&t)), funcPC(convT2E32))
   239  	}
   240  	if msanenabled {
   241  		msanread(elem, t.size)
   242  	}
   243  	var x unsafe.Pointer
   244  	if *(*uint32)(elem) == 0 {
   245  		x = unsafe.Pointer(&zeroVal[0])
   246  	} else {
   247  		x = mallocgc(4, t, false)
   248  		*(*uint32)(x) = *(*uint32)(elem)
   249  	}
   250  	e._type = t
   251  	e.data = x
   252  	return
   253  }
   254  
   255  func convT2E64(t *_type, elem unsafe.Pointer) (e eface) {
   256  	if raceenabled {
   257  		raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&t)), funcPC(convT2E64))
   258  	}
   259  	if msanenabled {
   260  		msanread(elem, t.size)
   261  	}
   262  	var x unsafe.Pointer
   263  	if *(*uint64)(elem) == 0 {
   264  		x = unsafe.Pointer(&zeroVal[0])
   265  	} else {
   266  		x = mallocgc(8, t, false)
   267  		*(*uint64)(x) = *(*uint64)(elem)
   268  	}
   269  	e._type = t
   270  	e.data = x
   271  	return
   272  }
   273  
   274  func convT2Estring(t *_type, elem unsafe.Pointer) (e eface) {
   275  	if raceenabled {
   276  		raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&t)), funcPC(convT2Estring))
   277  	}
   278  	if msanenabled {
   279  		msanread(elem, t.size)
   280  	}
   281  	var x unsafe.Pointer
   282  	if *(*string)(elem) == "" {
   283  		x = unsafe.Pointer(&zeroVal[0])
   284  	} else {
   285  		x = mallocgc(t.size, t, true)
   286  		*(*string)(x) = *(*string)(elem)
   287  	}
   288  	e._type = t
   289  	e.data = x
   290  	return
   291  }
   292  
   293  func convT2Eslice(t *_type, elem unsafe.Pointer) (e eface) {
   294  	if raceenabled {
   295  		raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&t)), funcPC(convT2Eslice))
   296  	}
   297  	if msanenabled {
   298  		msanread(elem, t.size)
   299  	}
   300  	var x unsafe.Pointer
   301  	if v := *(*slice)(elem); uintptr(v.array) == 0 {
   302  		x = unsafe.Pointer(&zeroVal[0])
   303  	} else {
   304  		x = mallocgc(t.size, t, true)
   305  		*(*slice)(x) = *(*slice)(elem)
   306  	}
   307  	e._type = t
   308  	e.data = x
   309  	return
   310  }
   311  
   312  func convT2Enoptr(t *_type, elem unsafe.Pointer) (e eface) {
   313  	if raceenabled {
   314  		raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&t)), funcPC(convT2Enoptr))
   315  	}
   316  	if msanenabled {
   317  		msanread(elem, t.size)
   318  	}
   319  	x := mallocgc(t.size, t, false)
   320  	memmove(x, elem, t.size)
   321  	e._type = t
   322  	e.data = x
   323  	return
   324  }
   325  
   326  func convT2I(tab *itab, elem unsafe.Pointer) (i iface) {
   327  	t := tab._type
   328  	if raceenabled {
   329  		raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&tab)), funcPC(convT2I))
   330  	}
   331  	if msanenabled {
   332  		msanread(elem, t.size)
   333  	}
   334  	x := mallocgc(t.size, t, true)
   335  	typedmemmove(t, x, elem)
   336  	i.tab = tab
   337  	i.data = x
   338  	return
   339  }
   340  
   341  func convT2I16(tab *itab, elem unsafe.Pointer) (i iface) {
   342  	t := tab._type
   343  	if raceenabled {
   344  		raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&tab)), funcPC(convT2I16))
   345  	}
   346  	if msanenabled {
   347  		msanread(elem, t.size)
   348  	}
   349  	var x unsafe.Pointer
   350  	if *(*uint16)(elem) == 0 {
   351  		x = unsafe.Pointer(&zeroVal[0])
   352  	} else {
   353  		x = mallocgc(2, t, false)
   354  		*(*uint16)(x) = *(*uint16)(elem)
   355  	}
   356  	i.tab = tab
   357  	i.data = x
   358  	return
   359  }
   360  
   361  func convT2I32(tab *itab, elem unsafe.Pointer) (i iface) {
   362  	t := tab._type
   363  	if raceenabled {
   364  		raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&tab)), funcPC(convT2I32))
   365  	}
   366  	if msanenabled {
   367  		msanread(elem, t.size)
   368  	}
   369  	var x unsafe.Pointer
   370  	if *(*uint32)(elem) == 0 {
   371  		x = unsafe.Pointer(&zeroVal[0])
   372  	} else {
   373  		x = mallocgc(4, t, false)
   374  		*(*uint32)(x) = *(*uint32)(elem)
   375  	}
   376  	i.tab = tab
   377  	i.data = x
   378  	return
   379  }
   380  
   381  func convT2I64(tab *itab, elem unsafe.Pointer) (i iface) {
   382  	t := tab._type
   383  	if raceenabled {
   384  		raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&tab)), funcPC(convT2I64))
   385  	}
   386  	if msanenabled {
   387  		msanread(elem, t.size)
   388  	}
   389  	var x unsafe.Pointer
   390  	if *(*uint64)(elem) == 0 {
   391  		x = unsafe.Pointer(&zeroVal[0])
   392  	} else {
   393  		x = mallocgc(8, t, false)
   394  		*(*uint64)(x) = *(*uint64)(elem)
   395  	}
   396  	i.tab = tab
   397  	i.data = x
   398  	return
   399  }
   400  
   401  func convT2Istring(tab *itab, elem unsafe.Pointer) (i iface) {
   402  	t := tab._type
   403  	if raceenabled {
   404  		raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&tab)), funcPC(convT2Istring))
   405  	}
   406  	if msanenabled {
   407  		msanread(elem, t.size)
   408  	}
   409  	var x unsafe.Pointer
   410  	if *(*string)(elem) == "" {
   411  		x = unsafe.Pointer(&zeroVal[0])
   412  	} else {
   413  		x = mallocgc(t.size, t, true)
   414  		*(*string)(x) = *(*string)(elem)
   415  	}
   416  	i.tab = tab
   417  	i.data = x
   418  	return
   419  }
   420  
   421  func convT2Islice(tab *itab, elem unsafe.Pointer) (i iface) {
   422  	t := tab._type
   423  	if raceenabled {
   424  		raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&tab)), funcPC(convT2Islice))
   425  	}
   426  	if msanenabled {
   427  		msanread(elem, t.size)
   428  	}
   429  	var x unsafe.Pointer
   430  	if v := *(*slice)(elem); uintptr(v.array) == 0 {
   431  		x = unsafe.Pointer(&zeroVal[0])
   432  	} else {
   433  		x = mallocgc(t.size, t, true)
   434  		*(*slice)(x) = *(*slice)(elem)
   435  	}
   436  	i.tab = tab
   437  	i.data = x
   438  	return
   439  }
   440  
   441  func convT2Inoptr(tab *itab, elem unsafe.Pointer) (i iface) {
   442  	t := tab._type
   443  	if raceenabled {
   444  		raceReadObjectPC(t, elem, getcallerpc(unsafe.Pointer(&tab)), funcPC(convT2Inoptr))
   445  	}
   446  	if msanenabled {
   447  		msanread(elem, t.size)
   448  	}
   449  	x := mallocgc(t.size, t, false)
   450  	memmove(x, elem, t.size)
   451  	i.tab = tab
   452  	i.data = x
   453  	return
   454  }
   455  
   456  func convI2I(inter *interfacetype, i iface) (r iface) {
   457  	tab := i.tab
   458  	if tab == nil {
   459  		return
   460  	}
   461  	if tab.inter == inter {
   462  		r.tab = tab
   463  		r.data = i.data
   464  		return
   465  	}
   466  	r.tab = getitab(inter, tab._type, false)
   467  	r.data = i.data
   468  	return
   469  }
   470  
   471  func assertI2I(inter *interfacetype, i iface) (r iface) {
   472  	tab := i.tab
   473  	if tab == nil {
   474  		// explicit conversions require non-nil interface value.
   475  		panic(&TypeAssertionError{"", "", inter.typ.string(), ""})
   476  	}
   477  	if tab.inter == inter {
   478  		r.tab = tab
   479  		r.data = i.data
   480  		return
   481  	}
   482  	r.tab = getitab(inter, tab._type, false)
   483  	r.data = i.data
   484  	return
   485  }
   486  
   487  func assertI2I2(inter *interfacetype, i iface) (r iface, b bool) {
   488  	tab := i.tab
   489  	if tab == nil {
   490  		return
   491  	}
   492  	if tab.inter != inter {
   493  		tab = getitab(inter, tab._type, true)
   494  		if tab == nil {
   495  			return
   496  		}
   497  	}
   498  	r.tab = tab
   499  	r.data = i.data
   500  	b = true
   501  	return
   502  }
   503  
   504  func assertE2I(inter *interfacetype, e eface) (r iface) {
   505  	t := e._type
   506  	if t == nil {
   507  		// explicit conversions require non-nil interface value.
   508  		panic(&TypeAssertionError{"", "", inter.typ.string(), ""})
   509  	}
   510  	r.tab = getitab(inter, t, false)
   511  	r.data = e.data
   512  	return
   513  }
   514  
   515  func assertE2I2(inter *interfacetype, e eface) (r iface, b bool) {
   516  	t := e._type
   517  	if t == nil {
   518  		return
   519  	}
   520  	tab := getitab(inter, t, true)
   521  	if tab == nil {
   522  		return
   523  	}
   524  	r.tab = tab
   525  	r.data = e.data
   526  	b = true
   527  	return
   528  }
   529  
   530  //go:linkname reflect_ifaceE2I reflect.ifaceE2I
   531  func reflect_ifaceE2I(inter *interfacetype, e eface, dst *iface) {
   532  	*dst = assertE2I(inter, e)
   533  }
   534  
   535  func iterate_itabs(fn func(*itab)) {
   536  	for _, h := range &hash {
   537  		for ; h != nil; h = h.link {
   538  			fn(h)
   539  		}
   540  	}
   541  }
   542  
   543  // staticbytes is used to avoid convT2E for byte-sized values.
   544  var staticbytes = [...]byte{
   545  	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
   546  	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
   547  	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
   548  	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
   549  	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
   550  	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
   551  	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
   552  	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
   553  	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
   554  	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
   555  	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
   556  	0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
   557  	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
   558  	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
   559  	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
   560  	0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
   561  	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
   562  	0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
   563  	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
   564  	0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
   565  	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
   566  	0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
   567  	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
   568  	0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
   569  	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
   570  	0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
   571  	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
   572  	0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
   573  	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
   574  	0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
   575  	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
   576  	0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
   577  }