github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/runtime/iface.c (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  #include "runtime.h"
     6  #include "arch_GOARCH.h"
     7  #include "type.h"
     8  #include "typekind.h"
     9  #include "malloc.h"
    10  
    11  void
    12  runtime·printiface(Iface i)
    13  {
    14  	runtime·printf("(%p,%p)", i.tab, i.data);
    15  }
    16  
    17  void
    18  runtime·printeface(Eface e)
    19  {
    20  	runtime·printf("(%p,%p)", e.type, e.data);
    21  }
    22  
    23  static	Itab*	hash[1009];
    24  static	Lock	ifacelock;
    25  
    26  static Itab*
    27  itab(InterfaceType *inter, Type *type, int32 canfail)
    28  {
    29  	int32 locked;
    30  	int32 ni;
    31  	Method *t, *et;
    32  	IMethod *i, *ei;
    33  	uint32 h;
    34  	String *iname, *ipkgPath;
    35  	Itab *m;
    36  	UncommonType *x;
    37  	Type *itype;
    38  	Eface err;
    39  
    40  	if(inter->mhdr.len == 0)
    41  		runtime·throw("internal error - misuse of itab");
    42  
    43  	locked = 0;
    44  
    45  	// easy case
    46  	x = type->x;
    47  	if(x == nil) {
    48  		if(canfail)
    49  			return nil;
    50  		iname = inter->m[0].name;
    51  		goto throw;
    52  	}
    53  
    54  	// compiler has provided some good hash codes for us.
    55  	h = inter->hash;
    56  	h += 17 * type->hash;
    57  	// TODO(rsc): h += 23 * x->mhash ?
    58  	h %= nelem(hash);
    59  
    60  	// look twice - once without lock, once with.
    61  	// common case will be no lock contention.
    62  	for(locked=0; locked<2; locked++) {
    63  		if(locked)
    64  			runtime·lock(&ifacelock);
    65  		for(m=runtime·atomicloadp(&hash[h]); m!=nil; m=m->link) {
    66  			if(m->inter == inter && m->type == type) {
    67  				if(m->bad) {
    68  					m = nil;
    69  					if(!canfail) {
    70  						// this can only happen if the conversion
    71  						// was already done once using the , ok form
    72  						// and we have a cached negative result.
    73  						// the cached result doesn't record which
    74  						// interface function was missing, so jump
    75  						// down to the interface check, which will
    76  						// do more work but give a better error.
    77  						goto search;
    78  					}
    79  				}
    80  				if(locked)
    81  					runtime·unlock(&ifacelock);
    82  				return m;
    83  			}
    84  		}
    85  	}
    86  
    87  	ni = inter->mhdr.len;
    88  	m = runtime·malloc(sizeof(*m) + ni*sizeof m->fun[0]);
    89  	m->inter = inter;
    90  	m->type = type;
    91  
    92  search:
    93  	// both inter and type have method sorted by name,
    94  	// and interface names are unique,
    95  	// so can iterate over both in lock step;
    96  	// the loop is O(ni+nt) not O(ni*nt).
    97  	i = inter->m;
    98  	ei = i + inter->mhdr.len;
    99  	t = x->m;
   100  	et = t + x->mhdr.len;
   101  	for(; i < ei; i++) {
   102  		itype = i->type;
   103  		iname = i->name;
   104  		ipkgPath = i->pkgPath;
   105  		for(;; t++) {
   106  			if(t >= et) {
   107  				if(!canfail) {
   108  				throw:
   109  					// didn't find method
   110  					runtime·newTypeAssertionError(
   111  						nil, type->string, inter->string,
   112  						iname, &err);
   113  					if(locked)
   114  						runtime·unlock(&ifacelock);
   115  					runtime·panic(err);
   116  					return nil;	// not reached
   117  				}
   118  				m->bad = 1;
   119  				goto out;
   120  			}
   121  			if(t->mtyp == itype && t->name == iname && t->pkgPath == ipkgPath)
   122  				break;
   123  		}
   124  		if(m)
   125  			m->fun[i - inter->m] = t->ifn;
   126  	}
   127  
   128  out:
   129  	if(!locked)
   130  		runtime·panicstring("invalid itab locking");
   131  	m->link = hash[h];
   132  	runtime·atomicstorep(&hash[h], m);
   133  	runtime·unlock(&ifacelock);
   134  	if(m->bad)
   135  		return nil;
   136  	return m;
   137  }
   138  
   139  static void
   140  copyin(Type *t, void *src, void **dst)
   141  {
   142  	uintptr size;
   143  	void *p;
   144  	Alg *alg;
   145  
   146  	size = t->size;
   147  	alg = t->alg;
   148  
   149  	if(size <= sizeof(*dst))
   150  		alg->copy(size, dst, src);
   151  	else {
   152  		p = runtime·mal(size);
   153  		alg->copy(size, p, src);
   154  		*dst = p;
   155  	}
   156  }
   157  
   158  static void
   159  copyout(Type *t, void **src, void *dst)
   160  {
   161  	uintptr size;
   162  	Alg *alg;
   163  
   164  	size = t->size;
   165  	alg = t->alg;
   166  
   167  	if(size <= sizeof(*src))
   168  		alg->copy(size, dst, src);
   169  	else
   170  		alg->copy(size, dst, *src);
   171  }
   172  
   173  #pragma textflag 7
   174  void
   175  runtime·typ2Itab(Type *t, InterfaceType *inter, Itab **cache, Itab *ret)
   176  {
   177  	Itab *tab;
   178  
   179  	tab = itab(inter, t, 0);
   180  	runtime·atomicstorep(cache, tab);
   181  	ret = tab;
   182  	FLUSH(&ret);
   183  }
   184  
   185  // func convT2I(typ *byte, typ2 *byte, cache **byte, elem any) (ret any)
   186  #pragma textflag 7
   187  void
   188  runtime·convT2I(Type *t, InterfaceType *inter, Itab **cache, ...)
   189  {
   190  	byte *elem;
   191  	Iface *ret;
   192  	Itab *tab;
   193  	int32 wid;
   194  
   195  	elem = (byte*)(&cache+1);
   196  	wid = t->size;
   197  	ret = (Iface*)(elem + ROUND(wid, Structrnd));
   198  	tab = runtime·atomicloadp(cache);
   199  	if(!tab) {
   200  		tab = itab(inter, t, 0);
   201  		runtime·atomicstorep(cache, tab);
   202  	}
   203  	ret->tab = tab;
   204  	copyin(t, elem, &ret->data);
   205  }
   206  
   207  // func convT2E(typ *byte, elem any) (ret any)
   208  #pragma textflag 7
   209  void
   210  runtime·convT2E(Type *t, ...)
   211  {
   212  	byte *elem;
   213  	Eface *ret;
   214  	int32 wid;
   215  
   216  	elem = (byte*)(&t+1);
   217  	wid = t->size;
   218  	ret = (Eface*)(elem + ROUND(wid, Structrnd));
   219  	ret->type = t;
   220  	copyin(t, elem, &ret->data);
   221  }
   222  
   223  static void assertI2Tret(Type *t, Iface i, byte *ret);
   224  
   225  // func ifaceI2T(typ *byte, iface any) (ret any)
   226  #pragma textflag 7
   227  void
   228  runtime·assertI2T(Type *t, Iface i, ...)
   229  {
   230  	byte *ret;
   231  
   232  	ret = (byte*)(&i+1);
   233  	assertI2Tret(t, i, ret);
   234  }
   235  
   236  static void
   237  assertI2Tret(Type *t, Iface i, byte *ret)
   238  {
   239  	Itab *tab;
   240  	Eface err;
   241  
   242  	tab = i.tab;
   243  	if(tab == nil) {
   244  		runtime·newTypeAssertionError(
   245  			nil, nil, t->string,
   246  			nil, &err);
   247  		runtime·panic(err);
   248  	}
   249  	if(tab->type != t) {
   250  		runtime·newTypeAssertionError(
   251  			tab->inter->string, tab->type->string, t->string,
   252  			nil, &err);
   253  		runtime·panic(err);
   254  	}
   255  	copyout(t, &i.data, ret);
   256  }
   257  
   258  // func ifaceI2T2(typ *byte, iface any) (ret any, ok bool)
   259  #pragma textflag 7
   260  void
   261  runtime·assertI2T2(Type *t, Iface i, ...)
   262  {
   263  	byte *ret;
   264  	bool *ok;
   265  	int32 wid;
   266  
   267  	ret = (byte*)(&i+1);
   268  	wid = t->size;
   269  	ok = (bool*)(ret + wid);
   270  
   271  	if(i.tab == nil || i.tab->type != t) {
   272  		*ok = false;
   273  		runtime·memclr(ret, wid);
   274  		return;
   275  	}
   276  
   277  	*ok = true;
   278  	copyout(t, &i.data, ret);
   279  }
   280  
   281  void
   282  runtime·assertI2TOK(Type *t, Iface i, bool ok)
   283  {
   284  	ok = i.tab!=nil && i.tab->type==t;
   285  	FLUSH(&ok);
   286  }
   287  
   288  static void assertE2Tret(Type *t, Eface e, byte *ret);
   289  
   290  // func ifaceE2T(typ *byte, iface any) (ret any)
   291  #pragma textflag 7
   292  void
   293  runtime·assertE2T(Type *t, Eface e, ...)
   294  {
   295  	byte *ret;
   296  
   297  	ret = (byte*)(&e+1);
   298  	assertE2Tret(t, e, ret);
   299  }
   300  
   301  static void
   302  assertE2Tret(Type *t, Eface e, byte *ret)
   303  {
   304  	Eface err;
   305  
   306  	if(e.type == nil) {
   307  		runtime·newTypeAssertionError(
   308  			nil, nil, t->string,
   309  			nil, &err);
   310  		runtime·panic(err);
   311  	}
   312  	if(e.type != t) {
   313  		runtime·newTypeAssertionError(
   314  			nil, e.type->string, t->string,
   315  			nil, &err);
   316  		runtime·panic(err);
   317  	}
   318  	copyout(t, &e.data, ret);
   319  }
   320  
   321  // func ifaceE2T2(sigt *byte, iface any) (ret any, ok bool);
   322  #pragma textflag 7
   323  void
   324  runtime·assertE2T2(Type *t, Eface e, ...)
   325  {
   326  	byte *ret;
   327  	bool *ok;
   328  	int32 wid;
   329  
   330  	ret = (byte*)(&e+1);
   331  	wid = t->size;
   332  	ok = (bool*)(ret + wid);
   333  
   334  	if(t != e.type) {
   335  		*ok = false;
   336  		runtime·memclr(ret, wid);
   337  		return;
   338  	}
   339  
   340  	*ok = true;
   341  	copyout(t, &e.data, ret);
   342  }
   343  
   344  void
   345  runtime·assertE2TOK(Type *t, Eface e, bool ok)
   346  {
   347  	ok = t==e.type;
   348  	FLUSH(&ok);
   349  }
   350  
   351  // func convI2E(elem any) (ret any)
   352  void
   353  runtime·convI2E(Iface i, Eface ret)
   354  {
   355  	Itab *tab;
   356  
   357  	ret.data = i.data;
   358  	if((tab = i.tab) == nil)
   359  		ret.type = nil;
   360  	else
   361  		ret.type = tab->type;
   362  	FLUSH(&ret);
   363  }
   364  
   365  // func ifaceI2E(typ *byte, iface any) (ret any)
   366  void
   367  runtime·assertI2E(InterfaceType* inter, Iface i, Eface ret)
   368  {
   369  	Itab *tab;
   370  	Eface err;
   371  
   372  	tab = i.tab;
   373  	if(tab == nil) {
   374  		// explicit conversions require non-nil interface value.
   375  		runtime·newTypeAssertionError(
   376  			nil, nil, inter->string,
   377  			nil, &err);
   378  		runtime·panic(err);
   379  	}
   380  	ret.data = i.data;
   381  	ret.type = tab->type;
   382  	FLUSH(&ret);
   383  }
   384  
   385  // func ifaceI2E2(typ *byte, iface any) (ret any, ok bool)
   386  void
   387  runtime·assertI2E2(InterfaceType* inter, Iface i, Eface ret, bool ok)
   388  {
   389  	Itab *tab;
   390  
   391  	USED(inter);
   392  	tab = i.tab;
   393  	if(tab == nil) {
   394  		ret.type = nil;
   395  		ok = 0;
   396  	} else {
   397  		ret.type = tab->type;
   398  		ok = 1;
   399  	}
   400  	ret.data = i.data;
   401  	FLUSH(&ret);
   402  	FLUSH(&ok);
   403  }
   404  
   405  // func convI2I(typ *byte, elem any) (ret any)
   406  void
   407  runtime·convI2I(InterfaceType* inter, Iface i, Iface ret)
   408  {
   409  	Itab *tab;
   410  
   411  	ret.data = i.data;
   412  	if((tab = i.tab) == nil)
   413  		ret.tab = nil;
   414  	else if(tab->inter == inter)
   415  		ret.tab = tab;
   416  	else
   417  		ret.tab = itab(inter, tab->type, 0);
   418  	FLUSH(&ret);
   419  }
   420  
   421  void
   422  runtime·ifaceI2I(InterfaceType *inter, Iface i, Iface *ret)
   423  {
   424  	Itab *tab;
   425  	Eface err;
   426  
   427  	tab = i.tab;
   428  	if(tab == nil) {
   429  		// explicit conversions require non-nil interface value.
   430  		runtime·newTypeAssertionError(
   431  			nil, nil, inter->string,
   432  			nil, &err);
   433  		runtime·panic(err);
   434  	}
   435  	ret->data = i.data;
   436  	ret->tab = itab(inter, tab->type, 0);
   437  }
   438  
   439  // func ifaceI2I(sigi *byte, iface any) (ret any)
   440  void
   441  runtime·assertI2I(InterfaceType* inter, Iface i, Iface ret)
   442  {
   443  	runtime·ifaceI2I(inter, i, &ret);
   444  }
   445  
   446  // func ifaceI2I2(sigi *byte, iface any) (ret any, ok bool)
   447  void
   448  runtime·assertI2I2(InterfaceType *inter, Iface i, Iface ret, bool ok)
   449  {
   450  	Itab *tab;
   451  
   452  	tab = i.tab;
   453  	if(tab != nil && (tab->inter == inter || (tab = itab(inter, tab->type, 1)) != nil)) {
   454  		ret.data = i.data;
   455  		ret.tab = tab;
   456  		ok = 1;
   457  	} else {
   458  		ret.data = 0;
   459  		ret.tab = 0;
   460  		ok = 0;
   461  	}
   462  	FLUSH(&ret);
   463  	FLUSH(&ok);
   464  }
   465  
   466  void
   467  runtime·ifaceE2I(InterfaceType *inter, Eface e, Iface *ret)
   468  {
   469  	Type *t;
   470  	Eface err;
   471  
   472  	t = e.type;
   473  	if(t == nil) {
   474  		// explicit conversions require non-nil interface value.
   475  		runtime·newTypeAssertionError(
   476  			nil, nil, inter->string,
   477  			nil, &err);
   478  		runtime·panic(err);
   479  	}
   480  	ret->data = e.data;
   481  	ret->tab = itab(inter, t, 0);
   482  }
   483  
   484  // For reflect
   485  //	func ifaceE2I(t *InterfaceType, e interface{}, dst *Iface)
   486  void
   487  reflect·ifaceE2I(InterfaceType *inter, Eface e, Iface *dst)
   488  {
   489  	runtime·ifaceE2I(inter, e, dst);
   490  }
   491  
   492  // func ifaceE2I(sigi *byte, iface any) (ret any)
   493  void
   494  runtime·assertE2I(InterfaceType* inter, Eface e, Iface ret)
   495  {
   496  	runtime·ifaceE2I(inter, e, &ret);
   497  }
   498  
   499  // ifaceE2I2(sigi *byte, iface any) (ret any, ok bool)
   500  void
   501  runtime·assertE2I2(InterfaceType *inter, Eface e, Iface ret, bool ok)
   502  {
   503  	if(e.type == nil) {
   504  		ok = 0;
   505  		ret.data = nil;
   506  		ret.tab = nil;
   507  	} else if((ret.tab = itab(inter, e.type, 1)) == nil) {
   508  		ok = 0;
   509  		ret.data = nil;
   510  	} else {
   511  		ok = 1;
   512  		ret.data = e.data;
   513  	}
   514  	FLUSH(&ret);
   515  	FLUSH(&ok);
   516  }
   517  
   518  // func ifaceE2E(typ *byte, iface any) (ret any)
   519  void
   520  runtime·assertE2E(InterfaceType* inter, Eface e, Eface ret)
   521  {
   522  	Type *t;
   523  	Eface err;
   524  
   525  	t = e.type;
   526  	if(t == nil) {
   527  		// explicit conversions require non-nil interface value.
   528  		runtime·newTypeAssertionError(
   529  			nil, nil, inter->string,
   530  			nil, &err);
   531  		runtime·panic(err);
   532  	}
   533  	ret = e;
   534  	FLUSH(&ret);
   535  }
   536  
   537  // func ifaceE2E2(iface any) (ret any, ok bool)
   538  void
   539  runtime·assertE2E2(InterfaceType* inter, Eface e, Eface ret, bool ok)
   540  {
   541  	USED(inter);
   542  	ret = e;
   543  	ok = e.type != nil;
   544  	FLUSH(&ret);
   545  	FLUSH(&ok);
   546  }
   547  
   548  static uintptr
   549  ifacehash1(void *data, Type *t, uintptr h)
   550  {
   551  	Alg *alg;
   552  	uintptr size;
   553  	Eface err;
   554  
   555  	if(t == nil)
   556  		return 0;
   557  
   558  	alg = t->alg;
   559  	size = t->size;
   560  	if(alg->hash == runtime·nohash) {
   561  		// calling nohash will panic too,
   562  		// but we can print a better error.
   563  		runtime·newErrorString(runtime·catstring(runtime·gostringnocopy((byte*)"hash of unhashable type "), *t->string), &err);
   564  		runtime·panic(err);
   565  	}
   566  	if(size <= sizeof(data))
   567  		alg->hash(&h, size, &data);
   568  	else
   569  		alg->hash(&h, size, data);
   570  	return h;
   571  }
   572  
   573  uintptr
   574  runtime·ifacehash(Iface a, uintptr h)
   575  {
   576  	if(a.tab == nil)
   577  		return h;
   578  	return ifacehash1(a.data, a.tab->type, h);
   579  }
   580  
   581  uintptr
   582  runtime·efacehash(Eface a, uintptr h)
   583  {
   584  	return ifacehash1(a.data, a.type, h);
   585  }
   586  
   587  static bool
   588  ifaceeq1(void *data1, void *data2, Type *t)
   589  {
   590  	uintptr size;
   591  	Alg *alg;
   592  	Eface err;
   593  	bool eq;
   594  
   595  	alg = t->alg;
   596  	size = t->size;
   597  
   598  	if(alg->equal == runtime·noequal) {
   599  		// calling noequal will panic too,
   600  		// but we can print a better error.
   601  		runtime·newErrorString(runtime·catstring(runtime·gostringnocopy((byte*)"comparing uncomparable type "), *t->string), &err);
   602  		runtime·panic(err);
   603  	}
   604  
   605  	eq = 0;
   606  	if(size <= sizeof(data1))
   607  		alg->equal(&eq, size, &data1, &data2);
   608  	else
   609  		alg->equal(&eq, size, data1, data2);
   610  	return eq;
   611  }
   612  
   613  bool
   614  runtime·ifaceeq_c(Iface i1, Iface i2)
   615  {
   616  	if(i1.tab != i2.tab)
   617  		return false;
   618  	if(i1.tab == nil)
   619  		return true;
   620  	return ifaceeq1(i1.data, i2.data, i1.tab->type);
   621  }
   622  
   623  bool
   624  runtime·efaceeq_c(Eface e1, Eface e2)
   625  {
   626  	if(e1.type != e2.type)
   627  		return false;
   628  	if(e1.type == nil)
   629  		return true;
   630  	return ifaceeq1(e1.data, e2.data, e1.type);
   631  }
   632  
   633  // ifaceeq(i1 any, i2 any) (ret bool);
   634  void
   635  runtime·ifaceeq(Iface i1, Iface i2, bool ret)
   636  {
   637  	ret = runtime·ifaceeq_c(i1, i2);
   638  	FLUSH(&ret);
   639  }
   640  
   641  // efaceeq(i1 any, i2 any) (ret bool)
   642  void
   643  runtime·efaceeq(Eface e1, Eface e2, bool ret)
   644  {
   645  	ret = runtime·efaceeq_c(e1, e2);
   646  	FLUSH(&ret);
   647  }
   648  
   649  // ifacethash(i1 any) (ret uint32);
   650  void
   651  runtime·ifacethash(Iface i1, uint32 ret)
   652  {
   653  	Itab *tab;
   654  
   655  	ret = 0;
   656  	tab = i1.tab;
   657  	if(tab != nil)
   658  		ret = tab->type->hash;
   659  	FLUSH(&ret);
   660  }
   661  
   662  // efacethash(e1 any) (ret uint32)
   663  void
   664  runtime·efacethash(Eface e1, uint32 ret)
   665  {
   666  	Type *t;
   667  
   668  	ret = 0;
   669  	t = e1.type;
   670  	if(t != nil)
   671  		ret = t->hash;
   672  	FLUSH(&ret);
   673  }
   674  
   675  void
   676  reflect·unsafe_Typeof(Eface e, Eface ret)
   677  {
   678  	if(e.type == nil) {
   679  		ret.type = nil;
   680  		ret.data = nil;
   681  	} else {
   682  		ret = *(Eface*)(e.type);
   683  	}
   684  	FLUSH(&ret);
   685  }
   686  
   687  void
   688  reflect·unsafe_New(Type *t, void *ret)
   689  {
   690  	uint32 flag;
   691  
   692  	flag = t->kind&KindNoPointers ? FlagNoPointers : 0;
   693  	ret = runtime·mallocgc(t->size, flag, 1, 1);
   694  
   695  	if(UseSpanType && !flag) {
   696  		if(false) {
   697  			runtime·printf("unsafe_New %S: %p\n", *t->string, ret);
   698  		}
   699  		runtime·settype(ret, (uintptr)t | TypeInfo_SingleObject);
   700  	}
   701  
   702  	FLUSH(&ret);
   703  }
   704  
   705  void
   706  reflect·unsafe_NewArray(Type *t, intgo n, void *ret)
   707  {
   708  	uint64 size;
   709  
   710  	size = n*t->size;
   711  	if(size == 0)
   712  		ret = (byte*)&runtime·zerobase;
   713  	else if(t->kind&KindNoPointers)
   714  		ret = runtime·mallocgc(size, FlagNoPointers, 1, 1);
   715  	else {
   716  		ret = runtime·mallocgc(size, 0, 1, 1);
   717  
   718  		if(UseSpanType) {
   719  			if(false) {
   720  				runtime·printf("unsafe_NewArray [%D]%S: %p\n", (int64)n, *t->string, ret);
   721  			}
   722  			runtime·settype(ret, (uintptr)t | TypeInfo_Array);
   723  		}
   724  	}
   725  
   726  	FLUSH(&ret);
   727  }
   728  
   729  void
   730  reflect·typelinks(Slice ret)
   731  {
   732  	extern Type *typelink[], *etypelink[];
   733  	static int32 first = 1;
   734  	ret.array = (byte*)typelink;
   735  	ret.len = etypelink - typelink;
   736  	ret.cap = ret.len;
   737  	FLUSH(&ret);
   738  }