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