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