github.com/spotify/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/runtime/alg.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 "type.h"
     7  #include "../../cmd/ld/textflag.h"
     8  
     9  #define M0 (sizeof(uintptr)==4 ? 2860486313UL : 33054211828000289ULL)
    10  #define M1 (sizeof(uintptr)==4 ? 3267000013UL : 23344194077549503ULL)
    11  
    12  static bool use_aeshash;
    13  
    14  /*
    15   * map and chan helpers for
    16   * dealing with unknown types
    17   */
    18  void
    19  runtime·memhash(uintptr *h, uintptr s, void *a)
    20  {
    21  	byte *b;
    22  	uintptr hash;
    23  	if(use_aeshash) {
    24  		runtime·aeshash(h, s, a);
    25  		return;
    26  	}
    27  
    28  	b = a;
    29  	hash = M0 ^ *h;
    30  	while(s > 0) {
    31  		hash = (hash ^ *b) * M1;
    32  		b++;
    33  		s--;
    34  	}
    35  	*h = hash;
    36  }
    37  
    38  void
    39  runtime·memequal(bool *eq, uintptr s, void *a, void *b)
    40  {
    41  	if(a == b) {
    42  		*eq = 1;
    43  		return;
    44  	}
    45  	*eq = runtime·memeq(a, b, s);
    46  }
    47  
    48  void
    49  runtime·memprint(uintptr s, void *a)
    50  {
    51  	uint64 v;
    52  
    53  	v = 0xbadb00b;
    54  	switch(s) {
    55  	case 1:
    56  		v = *(uint8*)a;
    57  		break;
    58  	case 2:
    59  		v = *(uint16*)a;
    60  		break;
    61  	case 4:
    62  		v = *(uint32*)a;
    63  		break;
    64  	case 8:
    65  		v = *(uint64*)a;
    66  		break;
    67  	}
    68  	runtime·printint(v);
    69  }
    70  
    71  void
    72  runtime·memcopy(uintptr s, void *a, void *b)
    73  {
    74  	if(b == nil) {
    75  		runtime·memclr(a, s);
    76  		return;
    77  	}
    78  	runtime·memmove(a, b, s);
    79  }
    80  
    81  void
    82  runtime·memequal0(bool *eq, uintptr s, void *a, void *b)
    83  {
    84  	USED(s);
    85  	USED(a);
    86  	USED(b);
    87  	*eq = true;
    88  }
    89  
    90  void
    91  runtime·memcopy0(uintptr s, void *a, void *b)
    92  {
    93  	USED(s);
    94  	USED(a);
    95  	USED(b);
    96  }
    97  
    98  void
    99  runtime·memequal8(bool *eq, uintptr s, void *a, void *b)
   100  {
   101  	USED(s);
   102  	*eq = *(uint8*)a == *(uint8*)b;
   103  }
   104  
   105  void
   106  runtime·memcopy8(uintptr s, void *a, void *b)
   107  {
   108  	USED(s);
   109  	if(b == nil) {
   110  		*(uint8*)a = 0;
   111  		return;
   112  	}
   113  	*(uint8*)a = *(uint8*)b;
   114  }
   115  
   116  void
   117  runtime·memequal16(bool *eq, uintptr s, void *a, void *b)
   118  {
   119  	USED(s);
   120  	*eq = *(uint16*)a == *(uint16*)b;
   121  }
   122  
   123  void
   124  runtime·memcopy16(uintptr s, void *a, void *b)
   125  {
   126  	USED(s);
   127  	if(b == nil) {
   128  		*(uint16*)a = 0;
   129  		return;
   130  	}
   131  	*(uint16*)a = *(uint16*)b;
   132  }
   133  
   134  void
   135  runtime·memequal32(bool *eq, uintptr s, void *a, void *b)
   136  {
   137  	USED(s);
   138  	*eq = *(uint32*)a == *(uint32*)b;
   139  }
   140  
   141  void
   142  runtime·memcopy32(uintptr s, void *a, void *b)
   143  {
   144  	USED(s);
   145  	if(b == nil) {
   146  		*(uint32*)a = 0;
   147  		return;
   148  	}
   149  	*(uint32*)a = *(uint32*)b;
   150  }
   151  
   152  void
   153  runtime·memequal64(bool *eq, uintptr s, void *a, void *b)
   154  {
   155  	USED(s);
   156  	*eq = *(uint64*)a == *(uint64*)b;
   157  }
   158  
   159  void
   160  runtime·memcopy64(uintptr s, void *a, void *b)
   161  {
   162  	USED(s);
   163  	if(b == nil) {
   164  		*(uint64*)a = 0;
   165  		return;
   166  	}
   167  	*(uint64*)a = *(uint64*)b;
   168  }
   169  
   170  void
   171  runtime·memequal128(bool *eq, uintptr s, void *a, void *b)
   172  {
   173  	USED(s);
   174  	*eq = ((uint64*)a)[0] == ((uint64*)b)[0] && ((uint64*)a)[1] == ((uint64*)b)[1];
   175  }
   176  
   177  void
   178  runtime·memcopy128(uintptr s, void *a, void *b)
   179  {
   180  	USED(s);
   181  	if(b == nil) {
   182  		((uint64*)a)[0] = 0;
   183  		((uint64*)a)[1] = 0;
   184  		return;
   185  	}
   186  	((uint64*)a)[0] = ((uint64*)b)[0];
   187  	((uint64*)a)[1] = ((uint64*)b)[1];
   188  }
   189  
   190  void
   191  runtime·f32equal(bool *eq, uintptr s, void *a, void *b)
   192  {
   193  	USED(s);
   194  	*eq = *(float32*)a == *(float32*)b;
   195  }
   196  
   197  void
   198  runtime·f64equal(bool *eq, uintptr s, void *a, void *b)
   199  {
   200  	USED(s);
   201  	*eq = *(float64*)a == *(float64*)b;
   202  }
   203  
   204  void
   205  runtime·c64equal(bool *eq, uintptr s, void *a, void *b)
   206  {	
   207  	Complex64 *ca, *cb;
   208  	
   209  	USED(s);
   210  	ca = a;
   211  	cb = b;
   212  	*eq = ca->real == cb->real && ca->imag == cb->imag;
   213  }
   214  
   215  void
   216  runtime·c128equal(bool *eq, uintptr s, void *a, void *b)
   217  {	
   218  	Complex128 *ca, *cb;
   219  	
   220  	USED(s);
   221  	ca = a;
   222  	cb = b;
   223  	*eq = ca->real == cb->real && ca->imag == cb->imag;
   224  }
   225  
   226  // NOTE: Because NaN != NaN, a map can contain any
   227  // number of (mostly useless) entries keyed with NaNs.
   228  // To avoid long hash chains, we assign a random number
   229  // as the hash value for a NaN.
   230  
   231  void
   232  runtime·f32hash(uintptr *h, uintptr s, void *a)
   233  {
   234  	uintptr hash;
   235  	float32 f;
   236  
   237  	USED(s);
   238  	f = *(float32*)a;
   239  	if(f == 0)
   240  		hash = 0;  // +0, -0
   241  	else if(f != f)
   242  		hash = runtime·fastrand1();  // any kind of NaN
   243  	else
   244  		hash = *(uint32*)a;
   245  	*h = (*h ^ hash ^ M0) * M1;
   246  }
   247  
   248  void
   249  runtime·f64hash(uintptr *h, uintptr s, void *a)
   250  {
   251  	uintptr hash;
   252  	float64 f;
   253  	uint64 u;
   254  
   255  	USED(s);
   256  	f = *(float64*)a;
   257  	if(f == 0)
   258  		hash = 0;	// +0, -0
   259  	else if(f != f)
   260  		hash = runtime·fastrand1();  // any kind of NaN
   261  	else {
   262  		u = *(uint64*)a;
   263  		if(sizeof(uintptr) == 4)
   264  			hash = ((uint32)(u>>32) * M1) ^ (uint32)u;
   265  		else
   266  			hash = u;
   267  	}
   268  	*h = (*h ^ hash ^ M0) * M1;
   269  }
   270  
   271  void
   272  runtime·c64hash(uintptr *h, uintptr s, void *a)
   273  {
   274  	USED(s);
   275  	runtime·f32hash(h, 0, a);
   276  	runtime·f32hash(h, 0, (float32*)a+1);
   277  }
   278  
   279  void
   280  runtime·c128hash(uintptr *h, uintptr s, void *a)
   281  {
   282  	USED(s);
   283  	runtime·f64hash(h, 0, a);
   284  	runtime·f64hash(h, 0, (float64*)a+1);
   285  }
   286  
   287  void
   288  runtime·slicecopy(uintptr s, void *a, void *b)
   289  {
   290  	USED(s);
   291  	if(b == nil) {
   292  		((Slice*)a)->array = 0;
   293  		((Slice*)a)->len = 0;
   294  		((Slice*)a)->cap = 0;
   295  		return;
   296  	}
   297  	((Slice*)a)->array = ((Slice*)b)->array;
   298  	((Slice*)a)->len = ((Slice*)b)->len;
   299  	((Slice*)a)->cap = ((Slice*)b)->cap;
   300  }
   301  
   302  void
   303  runtime·strhash(uintptr *h, uintptr s, void *a)
   304  {
   305  	USED(s);
   306  	runtime·memhash(h, ((String*)a)->len, ((String*)a)->str);
   307  }
   308  
   309  void
   310  runtime·strequal(bool *eq, uintptr s, void *a, void *b)
   311  {
   312  	intgo alen;
   313  	byte *s1, *s2;
   314  
   315  	USED(s);
   316  	alen = ((String*)a)->len;
   317  	if(alen != ((String*)b)->len) {
   318  		*eq = false;
   319  		return;
   320  	}
   321  	s1 = ((String*)a)->str;
   322  	s2 = ((String*)b)->str;
   323  	if(s1 == s2) {
   324  		*eq = true;
   325  		return;
   326  	}
   327  	*eq = runtime·memeq(s1, s2, alen);
   328  }
   329  
   330  void
   331  runtime·strprint(uintptr s, void *a)
   332  {
   333  	USED(s);
   334  	runtime·printstring(*(String*)a);
   335  }
   336  
   337  void
   338  runtime·strcopy(uintptr s, void *a, void *b)
   339  {
   340  	USED(s);
   341  	if(b == nil) {
   342  		((String*)a)->str = 0;
   343  		((String*)a)->len = 0;
   344  		return;
   345  	}
   346  	((String*)a)->str = ((String*)b)->str;
   347  	((String*)a)->len = ((String*)b)->len;
   348  }
   349  
   350  void
   351  runtime·interhash(uintptr *h, uintptr s, void *a)
   352  {
   353  	USED(s);
   354  	*h = runtime·ifacehash(*(Iface*)a, *h ^ M0) * M1;
   355  }
   356  
   357  void
   358  runtime·interprint(uintptr s, void *a)
   359  {
   360  	USED(s);
   361  	runtime·printiface(*(Iface*)a);
   362  }
   363  
   364  void
   365  runtime·interequal(bool *eq, uintptr s, void *a, void *b)
   366  {
   367  	USED(s);
   368  	*eq = runtime·ifaceeq_c(*(Iface*)a, *(Iface*)b);
   369  }
   370  
   371  void
   372  runtime·intercopy(uintptr s, void *a, void *b)
   373  {
   374  	USED(s);
   375  	if(b == nil) {
   376  		((Iface*)a)->tab = 0;
   377  		((Iface*)a)->data = 0;
   378  		return;
   379  	}
   380  	((Iface*)a)->tab = ((Iface*)b)->tab;
   381  	((Iface*)a)->data = ((Iface*)b)->data;
   382  }
   383  
   384  void
   385  runtime·nilinterhash(uintptr *h, uintptr s, void *a)
   386  {
   387  	USED(s);
   388  	*h = runtime·efacehash(*(Eface*)a, *h ^ M0) * M1;
   389  }
   390  
   391  void
   392  runtime·nilinterprint(uintptr s, void *a)
   393  {
   394  	USED(s);
   395  	runtime·printeface(*(Eface*)a);
   396  }
   397  
   398  void
   399  runtime·nilinterequal(bool *eq, uintptr s, void *a, void *b)
   400  {
   401  	USED(s);
   402  	*eq = runtime·efaceeq_c(*(Eface*)a, *(Eface*)b);
   403  }
   404  
   405  void
   406  runtime·nilintercopy(uintptr s, void *a, void *b)
   407  {
   408  	USED(s);
   409  	if(b == nil) {
   410  		((Eface*)a)->type = 0;
   411  		((Eface*)a)->data = 0;
   412  		return;
   413  	}
   414  	((Eface*)a)->type = ((Eface*)b)->type;
   415  	((Eface*)a)->data = ((Eface*)b)->data;
   416  }
   417  
   418  void
   419  runtime·nohash(uintptr *h, uintptr s, void *a)
   420  {
   421  	USED(s);
   422  	USED(a);
   423  	USED(h);
   424  	runtime·panicstring("hash of unhashable type");
   425  }
   426  
   427  void
   428  runtime·noequal(bool *eq, uintptr s, void *a, void *b)
   429  {
   430  	USED(s);
   431  	USED(a);
   432  	USED(b);
   433  	USED(eq);
   434  	runtime·panicstring("comparing uncomparable types");
   435  }
   436  
   437  Alg
   438  runtime·algarray[] =
   439  {
   440  [AMEM]		{ runtime·memhash, runtime·memequal, runtime·memprint, runtime·memcopy },
   441  [ANOEQ]		{ runtime·nohash, runtime·noequal, runtime·memprint, runtime·memcopy },
   442  [ASTRING]	{ runtime·strhash, runtime·strequal, runtime·strprint, runtime·strcopy },
   443  [AINTER]	{ runtime·interhash, runtime·interequal, runtime·interprint, runtime·intercopy },
   444  [ANILINTER]	{ runtime·nilinterhash, runtime·nilinterequal, runtime·nilinterprint, runtime·nilintercopy },
   445  [ASLICE]	{ runtime·nohash, runtime·noequal, runtime·memprint, runtime·slicecopy },
   446  [AFLOAT32]	{ runtime·f32hash, runtime·f32equal, runtime·memprint, runtime·memcopy },
   447  [AFLOAT64]	{ runtime·f64hash, runtime·f64equal, runtime·memprint, runtime·memcopy },
   448  [ACPLX64]	{ runtime·c64hash, runtime·c64equal, runtime·memprint, runtime·memcopy },
   449  [ACPLX128]	{ runtime·c128hash, runtime·c128equal, runtime·memprint, runtime·memcopy },
   450  [AMEM0]		{ runtime·memhash, runtime·memequal0, runtime·memprint, runtime·memcopy0 },
   451  [AMEM8]		{ runtime·memhash, runtime·memequal8, runtime·memprint, runtime·memcopy8 },
   452  [AMEM16]	{ runtime·memhash, runtime·memequal16, runtime·memprint, runtime·memcopy16 },
   453  [AMEM32]	{ runtime·memhash, runtime·memequal32, runtime·memprint, runtime·memcopy32 },
   454  [AMEM64]	{ runtime·memhash, runtime·memequal64, runtime·memprint, runtime·memcopy64 },
   455  [AMEM128]	{ runtime·memhash, runtime·memequal128, runtime·memprint, runtime·memcopy128 },
   456  [ANOEQ0]	{ runtime·nohash, runtime·noequal, runtime·memprint, runtime·memcopy0 },
   457  [ANOEQ8]	{ runtime·nohash, runtime·noequal, runtime·memprint, runtime·memcopy8 },
   458  [ANOEQ16]	{ runtime·nohash, runtime·noequal, runtime·memprint, runtime·memcopy16 },
   459  [ANOEQ32]	{ runtime·nohash, runtime·noequal, runtime·memprint, runtime·memcopy32 },
   460  [ANOEQ64]	{ runtime·nohash, runtime·noequal, runtime·memprint, runtime·memcopy64 },
   461  [ANOEQ128]	{ runtime·nohash, runtime·noequal, runtime·memprint, runtime·memcopy128 },
   462  };
   463  
   464  // Runtime helpers.
   465  
   466  // used in asm_{386,amd64}.s
   467  byte runtime·aeskeysched[HashRandomBytes];
   468  
   469  void
   470  runtime·hashinit(void)
   471  {
   472  	// Install aes hash algorithm if we have the instructions we need
   473  	if((runtime·cpuid_ecx & (1 << 25)) != 0 &&  // aes (aesenc)
   474  	   (runtime·cpuid_ecx & (1 << 9)) != 0 &&   // sse3 (pshufb)
   475  	   (runtime·cpuid_ecx & (1 << 19)) != 0) {  // sse4.1 (pinsr{d,q})
   476  		byte *rnd;
   477  		int32 n;
   478  		use_aeshash = true;
   479  		runtime·algarray[AMEM].hash = runtime·aeshash;
   480  		runtime·algarray[AMEM8].hash = runtime·aeshash;
   481  		runtime·algarray[AMEM16].hash = runtime·aeshash;
   482  		runtime·algarray[AMEM32].hash = runtime·aeshash32;
   483  		runtime·algarray[AMEM64].hash = runtime·aeshash64;
   484  		runtime·algarray[AMEM128].hash = runtime·aeshash;
   485  		runtime·algarray[ASTRING].hash = runtime·aeshashstr;
   486  
   487  		// Initialize with random data so hash collisions will be hard to engineer.
   488  		runtime·get_random_data(&rnd, &n);
   489  		if(n > HashRandomBytes)
   490  			n = HashRandomBytes;
   491  		runtime·memmove(runtime·aeskeysched, rnd, n);
   492  		if(n < HashRandomBytes) {
   493  			// Not very random, but better than nothing.
   494  			int64 t = runtime·nanotime();
   495  			while (n < HashRandomBytes) {
   496  				runtime·aeskeysched[n++] = (int8)(t >> (8 * (n % 8)));
   497  			}
   498  		}
   499  	}
   500  }
   501  
   502  // func equal(t *Type, x T, y T) (ret bool)
   503  #pragma textflag NOSPLIT
   504  void
   505  runtime·equal(Type *t, ...)
   506  {
   507  	byte *x, *y;
   508  	uintptr ret;
   509  	
   510  	x = (byte*)(&t+1);
   511  	y = x + t->size;
   512  	ret = (uintptr)(y + t->size);
   513  	ret = ROUND(ret, Structrnd);
   514  	t->alg->equal((bool*)ret, t->size, x, y);
   515  }
   516  
   517  // Testing adapters for hash quality tests (see hash_test.go)
   518  void runtime·haveGoodHash(bool res) {
   519  	res = use_aeshash;
   520  	FLUSH(&res);
   521  }
   522  void runtime·stringHash(String s, uintptr seed, uintptr res) {
   523  	runtime·algarray[ASTRING].hash(&seed, sizeof(String), &s);
   524  	res = seed;
   525  	FLUSH(&res);
   526  }
   527  void runtime·bytesHash(Slice s, uintptr seed, uintptr res) {
   528  	runtime·algarray[AMEM].hash(&seed, s.len, s.array);
   529  	res = seed;
   530  	FLUSH(&res);
   531  }
   532  void runtime·int32Hash(uint32 i, uintptr seed, uintptr res) {
   533  	runtime·algarray[AMEM32].hash(&seed, sizeof(uint32), &i);
   534  	res = seed;
   535  	FLUSH(&res);
   536  }
   537  void runtime·int64Hash(uint64 i, uintptr seed, uintptr res) {
   538  	runtime·algarray[AMEM64].hash(&seed, sizeof(uint64), &i);
   539  	res = seed;
   540  	FLUSH(&res);
   541  }