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 }