github.com/c0deoo1/golang1.5@v0.0.0-20220525150107-c87c805d4593/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 "unsafe"
     8  
     9  const (
    10  	hashSize = 1009
    11  )
    12  
    13  var (
    14  	ifaceLock mutex // lock for accessing hash
    15  	hash      [hashSize]*itab
    16  )
    17  
    18  // fInterface is our standard non-empty interface.  We use it instead
    19  // of interface{f()} in function prototypes because gofmt insists on
    20  // putting lots of newlines in the otherwise concise interface{f()}.
    21  type fInterface interface {
    22  	f()
    23  }
    24  
    25  func getitab(inter *interfacetype, typ *_type, canfail bool) *itab {
    26  	if len(inter.mhdr) == 0 {
    27  		throw("internal error - misuse of itab")
    28  	}
    29  
    30  	// easy case
    31  	x := typ.x
    32  	if x == nil {
    33  		if canfail {
    34  			return nil
    35  		}
    36  		panic(&TypeAssertionError{"", *typ._string, *inter.typ._string, *inter.mhdr[0].name})
    37  	}
    38  
    39  	// compiler has provided some good hash codes for us.
    40  	h := inter.typ.hash
    41  	h += 17 * typ.hash
    42  	// TODO(rsc): h += 23 * x.mhash ?
    43  	h %= hashSize
    44  
    45  	// look twice - once without lock, once with.
    46  	// common case will be no lock contention.
    47  	var m *itab
    48  	var locked int
    49  	for locked = 0; locked < 2; locked++ {
    50  		if locked != 0 {
    51  			lock(&ifaceLock)
    52  		}
    53  		for m = (*itab)(atomicloadp(unsafe.Pointer(&hash[h]))); m != nil; m = m.link {
    54  			if m.inter == inter && m._type == typ {
    55  				if m.bad != 0 {
    56  					m = nil
    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 jump
    63  						// down to the interface check, which will
    64  						// do more work but give a better error.
    65  						goto search
    66  					}
    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)*ptrSize, 0, &memstats.other_sys))
    77  	m.inter = inter
    78  	m._type = typ
    79  
    80  search:
    81  	// both inter and typ have method sorted by name,
    82  	// and interface names are unique,
    83  	// so can iterate over both in lock step;
    84  	// the loop is O(ni+nt) not O(ni*nt).
    85  	ni := len(inter.mhdr)
    86  	nt := len(x.mhdr)
    87  	j := 0
    88  	for k := 0; k < ni; k++ {
    89  		i := &inter.mhdr[k]
    90  		iname := i.name
    91  		ipkgpath := i.pkgpath
    92  		itype := i._type
    93  		for ; j < nt; j++ {
    94  			t := &x.mhdr[j]
    95  			if t.mtyp == itype && (t.name == iname || *t.name == *iname) && t.pkgpath == ipkgpath {
    96  				if m != nil {
    97  					*(*unsafe.Pointer)(add(unsafe.Pointer(&m.fun[0]), uintptr(k)*ptrSize)) = t.ifn
    98  				}
    99  				goto nextimethod
   100  			}
   101  		}
   102  		// didn't find method
   103  		if !canfail {
   104  			if locked != 0 {
   105  				unlock(&ifaceLock)
   106  			}
   107  			panic(&TypeAssertionError{"", *typ._string, *inter.typ._string, *iname})
   108  		}
   109  		m.bad = 1
   110  		break
   111  	nextimethod:
   112  	}
   113  	if locked == 0 {
   114  		throw("invalid itab locking")
   115  	}
   116  	m.link = hash[h]
   117  	atomicstorep(unsafe.Pointer(&hash[h]), unsafe.Pointer(m))
   118  	unlock(&ifaceLock)
   119  	if m.bad != 0 {
   120  		return nil
   121  	}
   122  	return m
   123  }
   124  
   125  func typ2Itab(t *_type, inter *interfacetype, cache **itab) *itab {
   126  	tab := getitab(inter, t, false)
   127  	atomicstorep(unsafe.Pointer(cache), unsafe.Pointer(tab))
   128  	return tab
   129  }
   130  
   131  func convT2E(t *_type, elem unsafe.Pointer, x unsafe.Pointer) (e interface{}) {
   132  	ep := (*eface)(unsafe.Pointer(&e))
   133  	if isDirectIface(t) {
   134  		ep._type = t
   135  		typedmemmove(t, unsafe.Pointer(&ep.data), elem)
   136  	} else {
   137  		if x == nil {
   138  			x = newobject(t)
   139  		}
   140  		// TODO: We allocate a zeroed object only to overwrite it with
   141  		// actual data.  Figure out how to avoid zeroing.  Also below in convT2I.
   142  		typedmemmove(t, x, elem)
   143  		ep._type = t
   144  		ep.data = x
   145  	}
   146  	return
   147  }
   148  
   149  func convT2I(t *_type, inter *interfacetype, cache **itab, elem unsafe.Pointer, x unsafe.Pointer) (i fInterface) {
   150  	tab := (*itab)(atomicloadp(unsafe.Pointer(cache)))
   151  	if tab == nil {
   152  		tab = getitab(inter, t, false)
   153  		atomicstorep(unsafe.Pointer(cache), unsafe.Pointer(tab))
   154  	}
   155  	pi := (*iface)(unsafe.Pointer(&i))
   156  	if isDirectIface(t) {
   157  		pi.tab = tab
   158  		typedmemmove(t, unsafe.Pointer(&pi.data), elem)
   159  	} else {
   160  		if x == nil {
   161  			x = newobject(t)
   162  		}
   163  		typedmemmove(t, x, elem)
   164  		pi.tab = tab
   165  		pi.data = x
   166  	}
   167  	return
   168  }
   169  
   170  func panicdottype(have, want, iface *_type) {
   171  	haveString := ""
   172  	if have != nil {
   173  		haveString = *have._string
   174  	}
   175  	panic(&TypeAssertionError{*iface._string, haveString, *want._string, ""})
   176  }
   177  
   178  func assertI2T(t *_type, i fInterface, r unsafe.Pointer) {
   179  	ip := (*iface)(unsafe.Pointer(&i))
   180  	tab := ip.tab
   181  	if tab == nil {
   182  		panic(&TypeAssertionError{"", "", *t._string, ""})
   183  	}
   184  	if tab._type != t {
   185  		panic(&TypeAssertionError{*tab.inter.typ._string, *tab._type._string, *t._string, ""})
   186  	}
   187  	if r != nil {
   188  		if isDirectIface(t) {
   189  			writebarrierptr((*uintptr)(r), uintptr(ip.data))
   190  		} else {
   191  			typedmemmove(t, r, ip.data)
   192  		}
   193  	}
   194  }
   195  
   196  func assertI2T2(t *_type, i fInterface, r unsafe.Pointer) bool {
   197  	ip := (*iface)(unsafe.Pointer(&i))
   198  	tab := ip.tab
   199  	if tab == nil || tab._type != t {
   200  		if r != nil {
   201  			memclr(r, uintptr(t.size))
   202  		}
   203  		return false
   204  	}
   205  	if r != nil {
   206  		if isDirectIface(t) {
   207  			writebarrierptr((*uintptr)(r), uintptr(ip.data))
   208  		} else {
   209  			typedmemmove(t, r, ip.data)
   210  		}
   211  	}
   212  	return true
   213  }
   214  
   215  func assertE2T(t *_type, e interface{}, r unsafe.Pointer) {
   216  	ep := (*eface)(unsafe.Pointer(&e))
   217  	if ep._type == nil {
   218  		panic(&TypeAssertionError{"", "", *t._string, ""})
   219  	}
   220  	if ep._type != t {
   221  		panic(&TypeAssertionError{"", *ep._type._string, *t._string, ""})
   222  	}
   223  	if r != nil {
   224  		if isDirectIface(t) {
   225  			writebarrierptr((*uintptr)(r), uintptr(ep.data))
   226  		} else {
   227  			typedmemmove(t, r, ep.data)
   228  		}
   229  	}
   230  }
   231  
   232  // The compiler ensures that r is non-nil.
   233  func assertE2T2(t *_type, e interface{}, r unsafe.Pointer) bool {
   234  	ep := (*eface)(unsafe.Pointer(&e))
   235  	if ep._type != t {
   236  		memclr(r, uintptr(t.size))
   237  		return false
   238  	}
   239  	if isDirectIface(t) {
   240  		writebarrierptr((*uintptr)(r), uintptr(ep.data))
   241  	} else {
   242  		typedmemmove(t, r, ep.data)
   243  	}
   244  	return true
   245  }
   246  
   247  func convI2E(i fInterface) (r interface{}) {
   248  	ip := (*iface)(unsafe.Pointer(&i))
   249  	tab := ip.tab
   250  	if tab == nil {
   251  		return
   252  	}
   253  	rp := (*eface)(unsafe.Pointer(&r))
   254  	rp._type = tab._type
   255  	rp.data = ip.data
   256  	return
   257  }
   258  
   259  func assertI2E(inter *interfacetype, i fInterface, r *interface{}) {
   260  	ip := (*iface)(unsafe.Pointer(&i))
   261  	tab := ip.tab
   262  	if tab == nil {
   263  		// explicit conversions require non-nil interface value.
   264  		panic(&TypeAssertionError{"", "", *inter.typ._string, ""})
   265  	}
   266  	rp := (*eface)(unsafe.Pointer(r))
   267  	rp._type = tab._type
   268  	rp.data = ip.data
   269  	return
   270  }
   271  
   272  // The compiler ensures that r is non-nil.
   273  func assertI2E2(inter *interfacetype, i fInterface, r *interface{}) bool {
   274  	ip := (*iface)(unsafe.Pointer(&i))
   275  	tab := ip.tab
   276  	if tab == nil {
   277  		return false
   278  	}
   279  	rp := (*eface)(unsafe.Pointer(r))
   280  	rp._type = tab._type
   281  	rp.data = ip.data
   282  	return true
   283  }
   284  
   285  func convI2I(inter *interfacetype, i fInterface) (r fInterface) {
   286  	ip := (*iface)(unsafe.Pointer(&i))
   287  	tab := ip.tab
   288  	if tab == nil {
   289  		return
   290  	}
   291  	rp := (*iface)(unsafe.Pointer(&r))
   292  	if tab.inter == inter {
   293  		rp.tab = tab
   294  		rp.data = ip.data
   295  		return
   296  	}
   297  	rp.tab = getitab(inter, tab._type, false)
   298  	rp.data = ip.data
   299  	return
   300  }
   301  
   302  func assertI2I(inter *interfacetype, i fInterface, r *fInterface) {
   303  	ip := (*iface)(unsafe.Pointer(&i))
   304  	tab := ip.tab
   305  	if tab == nil {
   306  		// explicit conversions require non-nil interface value.
   307  		panic(&TypeAssertionError{"", "", *inter.typ._string, ""})
   308  	}
   309  	rp := (*iface)(unsafe.Pointer(r))
   310  	if tab.inter == inter {
   311  		rp.tab = tab
   312  		rp.data = ip.data
   313  		return
   314  	}
   315  	rp.tab = getitab(inter, tab._type, false)
   316  	rp.data = ip.data
   317  }
   318  
   319  func assertI2I2(inter *interfacetype, i fInterface, r *fInterface) bool {
   320  	ip := (*iface)(unsafe.Pointer(&i))
   321  	tab := ip.tab
   322  	if tab == nil {
   323  		if r != nil {
   324  			*r = nil
   325  		}
   326  		return false
   327  	}
   328  	if tab.inter != inter {
   329  		tab = getitab(inter, tab._type, true)
   330  		if tab == nil {
   331  			if r != nil {
   332  				*r = nil
   333  			}
   334  			return false
   335  		}
   336  	}
   337  	if r != nil {
   338  		rp := (*iface)(unsafe.Pointer(r))
   339  		rp.tab = tab
   340  		rp.data = ip.data
   341  	}
   342  	return true
   343  }
   344  
   345  func assertE2I(inter *interfacetype, e interface{}, r *fInterface) {
   346  	ep := (*eface)(unsafe.Pointer(&e))
   347  	t := ep._type
   348  	if t == nil {
   349  		// explicit conversions require non-nil interface value.
   350  		panic(&TypeAssertionError{"", "", *inter.typ._string, ""})
   351  	}
   352  	rp := (*iface)(unsafe.Pointer(r))
   353  	rp.tab = getitab(inter, t, false)
   354  	rp.data = ep.data
   355  }
   356  
   357  var testingAssertE2I2GC bool
   358  
   359  func assertE2I2(inter *interfacetype, e interface{}, r *fInterface) bool {
   360  	if testingAssertE2I2GC {
   361  		GC()
   362  	}
   363  	ep := (*eface)(unsafe.Pointer(&e))
   364  	t := ep._type
   365  	if t == nil {
   366  		if r != nil {
   367  			*r = nil
   368  		}
   369  		return false
   370  	}
   371  	tab := getitab(inter, t, true)
   372  	if tab == nil {
   373  		if r != nil {
   374  			*r = nil
   375  		}
   376  		return false
   377  	}
   378  	if r != nil {
   379  		rp := (*iface)(unsafe.Pointer(r))
   380  		rp.tab = tab
   381  		rp.data = ep.data
   382  	}
   383  	return true
   384  }
   385  
   386  //go:linkname reflect_ifaceE2I reflect.ifaceE2I
   387  func reflect_ifaceE2I(inter *interfacetype, e interface{}, dst *fInterface) {
   388  	assertE2I(inter, e, dst)
   389  }
   390  
   391  func assertE2E(inter *interfacetype, e interface{}, r *interface{}) {
   392  	ep := (*eface)(unsafe.Pointer(&e))
   393  	if ep._type == nil {
   394  		// explicit conversions require non-nil interface value.
   395  		panic(&TypeAssertionError{"", "", *inter.typ._string, ""})
   396  	}
   397  	*r = e
   398  }
   399  
   400  // The compiler ensures that r is non-nil.
   401  func assertE2E2(inter *interfacetype, e interface{}, r *interface{}) bool {
   402  	ep := (*eface)(unsafe.Pointer(&e))
   403  	if ep._type == nil {
   404  		*r = nil
   405  		return false
   406  	}
   407  	*r = e
   408  	return true
   409  }
   410  
   411  func ifacethash(i fInterface) uint32 {
   412  	ip := (*iface)(unsafe.Pointer(&i))
   413  	tab := ip.tab
   414  	if tab == nil {
   415  		return 0
   416  	}
   417  	return tab._type.hash
   418  }
   419  
   420  func efacethash(e interface{}) uint32 {
   421  	ep := (*eface)(unsafe.Pointer(&e))
   422  	t := ep._type
   423  	if t == nil {
   424  		return 0
   425  	}
   426  	return t.hash
   427  }
   428  
   429  func iterate_itabs(fn func(*itab)) {
   430  	for _, h := range &hash {
   431  		for ; h != nil; h = h.link {
   432  			fn(h)
   433  		}
   434  	}
   435  }