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 }