| // Copyright 2009 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package runtime |
| #include "runtime.h" |
| #include "type.h" |
| #include "../../cmd/ld/textflag.h" |
| |
| bool runtime·use_aeshash; |
| |
| void |
| runtime·memprint(uintptr s, void *a) |
| { |
| uint64 v; |
| |
| v = 0xbadb00b; |
| switch(s) { |
| case 1: |
| v = *(uint8*)a; |
| break; |
| case 2: |
| v = *(uint16*)a; |
| break; |
| case 4: |
| v = *(uint32*)a; |
| break; |
| case 8: |
| v = *(uint64*)a; |
| break; |
| } |
| runtime·printint_c(v); |
| } |
| |
| void |
| runtime·memcopy(uintptr s, void *a, void *b) |
| { |
| if(b == nil) { |
| runtime·memclr(a, s); |
| return; |
| } |
| runtime·memmove(a, b, s); |
| } |
| |
| void |
| runtime·memcopy0(uintptr s, void *a, void *b) |
| { |
| USED(s); |
| USED(a); |
| USED(b); |
| } |
| |
| void |
| runtime·memcopy8(uintptr s, void *a, void *b) |
| { |
| USED(s); |
| if(b == nil) { |
| *(uint8*)a = 0; |
| return; |
| } |
| *(uint8*)a = *(uint8*)b; |
| } |
| |
| void |
| runtime·memcopy16(uintptr s, void *a, void *b) |
| { |
| USED(s); |
| if(b == nil) { |
| *(uint16*)a = 0; |
| return; |
| } |
| *(uint16*)a = *(uint16*)b; |
| } |
| |
| void |
| runtime·memcopy32(uintptr s, void *a, void *b) |
| { |
| USED(s); |
| if(b == nil) { |
| *(uint32*)a = 0; |
| return; |
| } |
| *(uint32*)a = *(uint32*)b; |
| } |
| |
| void |
| runtime·memcopy64(uintptr s, void *a, void *b) |
| { |
| USED(s); |
| if(b == nil) { |
| *(uint64*)a = 0; |
| return; |
| } |
| *(uint64*)a = *(uint64*)b; |
| } |
| |
| void |
| runtime·memcopy128(uintptr s, void *a, void *b) |
| { |
| USED(s); |
| if(b == nil) { |
| ((uint64*)a)[0] = 0; |
| ((uint64*)a)[1] = 0; |
| return; |
| } |
| ((uint64*)a)[0] = ((uint64*)b)[0]; |
| ((uint64*)a)[1] = ((uint64*)b)[1]; |
| } |
| |
| void |
| runtime·algslicecopy(uintptr s, void *a, void *b) |
| { |
| USED(s); |
| if(b == nil) { |
| ((Slice*)a)->array = 0; |
| ((Slice*)a)->len = 0; |
| ((Slice*)a)->cap = 0; |
| return; |
| } |
| ((Slice*)a)->array = ((Slice*)b)->array; |
| ((Slice*)a)->len = ((Slice*)b)->len; |
| ((Slice*)a)->cap = ((Slice*)b)->cap; |
| } |
| |
| void |
| runtime·strprint(uintptr s, void *a) |
| { |
| USED(s); |
| runtime·printstring_c(*(String*)a); |
| } |
| |
| void |
| runtime·strcopy(uintptr s, void *a, void *b) |
| { |
| USED(s); |
| if(b == nil) { |
| ((String*)a)->str = 0; |
| ((String*)a)->len = 0; |
| return; |
| } |
| ((String*)a)->str = ((String*)b)->str; |
| ((String*)a)->len = ((String*)b)->len; |
| } |
| |
| void |
| runtime·interprint(uintptr s, void *a) |
| { |
| USED(s); |
| runtime·printiface_c(*(Iface*)a); |
| } |
| |
| void |
| runtime·intercopy(uintptr s, void *a, void *b) |
| { |
| USED(s); |
| if(b == nil) { |
| ((Iface*)a)->tab = 0; |
| ((Iface*)a)->data = 0; |
| return; |
| } |
| ((Iface*)a)->tab = ((Iface*)b)->tab; |
| ((Iface*)a)->data = ((Iface*)b)->data; |
| } |
| |
| void |
| runtime·nilinterprint(uintptr s, void *a) |
| { |
| USED(s); |
| runtime·printeface_c(*(Eface*)a); |
| } |
| |
| void |
| runtime·nilintercopy(uintptr s, void *a, void *b) |
| { |
| USED(s); |
| if(b == nil) { |
| ((Eface*)a)->type = 0; |
| ((Eface*)a)->data = 0; |
| return; |
| } |
| ((Eface*)a)->type = ((Eface*)b)->type; |
| ((Eface*)a)->data = ((Eface*)b)->data; |
| } |
| |
| extern uintptr runtime·nohashcode; |
| extern uintptr runtime·noequalcode; |
| |
| static FuncVal memhashfunc = {(void*)runtime·memhash}; |
| static FuncVal nohashfunc = {(void*)runtime·nohash}; |
| static FuncVal strhashfunc = {(void*)runtime·strhash}; |
| static FuncVal interhashfunc = {(void*)runtime·interhash}; |
| static FuncVal nilinterhashfunc = {(void*)runtime·nilinterhash}; |
| static FuncVal f32hashfunc = {(void*)runtime·f32hash}; |
| static FuncVal f64hashfunc = {(void*)runtime·f64hash}; |
| static FuncVal c64hashfunc = {(void*)runtime·c64hash}; |
| static FuncVal c128hashfunc = {(void*)runtime·c128hash}; |
| |
| static FuncVal aeshashfunc = {(void*)runtime·aeshash}; |
| static FuncVal aeshash32func = {(void*)runtime·aeshash32}; |
| static FuncVal aeshash64func = {(void*)runtime·aeshash64}; |
| static FuncVal aeshashstrfunc = {(void*)runtime·aeshashstr}; |
| |
| static FuncVal memequalfunc = {(void*)runtime·memequal}; |
| static FuncVal noequalfunc = {(void*)runtime·noequal}; |
| static FuncVal strequalfunc = {(void*)runtime·strequal}; |
| static FuncVal interequalfunc = {(void*)runtime·interequal}; |
| static FuncVal nilinterequalfunc = {(void*)runtime·nilinterequal}; |
| static FuncVal f32equalfunc = {(void*)runtime·f32equal}; |
| static FuncVal f64equalfunc = {(void*)runtime·f64equal}; |
| static FuncVal c64equalfunc = {(void*)runtime·c64equal}; |
| static FuncVal c128equalfunc = {(void*)runtime·c128equal}; |
| static FuncVal memequal0func = {(void*)runtime·memequal0}; |
| static FuncVal memequal8func = {(void*)runtime·memequal8}; |
| static FuncVal memequal16func = {(void*)runtime·memequal16}; |
| static FuncVal memequal32func = {(void*)runtime·memequal32}; |
| static FuncVal memequal64func = {(void*)runtime·memequal64}; |
| static FuncVal memequal128func = {(void*)runtime·memequal128}; |
| |
| |
| Alg |
| runtime·algarray[] = |
| { |
| [AMEM] { &memhashfunc, &memequalfunc, runtime·memprint, runtime·memcopy }, |
| [ANOEQ] { &nohashfunc, &noequalfunc, runtime·memprint, runtime·memcopy }, |
| [ASTRING] { &strhashfunc, &strequalfunc, runtime·strprint, runtime·strcopy }, |
| [AINTER] { &interhashfunc, &interequalfunc, runtime·interprint, runtime·intercopy }, |
| [ANILINTER] { &nilinterhashfunc, &nilinterequalfunc, runtime·nilinterprint, runtime·nilintercopy }, |
| [ASLICE] { &nohashfunc, &noequalfunc, runtime·memprint, runtime·algslicecopy }, |
| [AFLOAT32] { &f32hashfunc, &f32equalfunc, runtime·memprint, runtime·memcopy }, |
| [AFLOAT64] { &f64hashfunc, &f64equalfunc, runtime·memprint, runtime·memcopy }, |
| [ACPLX64] { &c64hashfunc, &c64equalfunc, runtime·memprint, runtime·memcopy }, |
| [ACPLX128] { &c128hashfunc, &c128equalfunc, runtime·memprint, runtime·memcopy }, |
| [AMEM0] { &memhashfunc, &memequal0func, runtime·memprint, runtime·memcopy0 }, |
| [AMEM8] { &memhashfunc, &memequal8func, runtime·memprint, runtime·memcopy8 }, |
| [AMEM16] { &memhashfunc, &memequal16func, runtime·memprint, runtime·memcopy16 }, |
| [AMEM32] { &memhashfunc, &memequal32func, runtime·memprint, runtime·memcopy32 }, |
| [AMEM64] { &memhashfunc, &memequal64func, runtime·memprint, runtime·memcopy64 }, |
| [AMEM128] { &memhashfunc, &memequal128func, runtime·memprint, runtime·memcopy128 }, |
| [ANOEQ0] { &nohashfunc, &noequalfunc, runtime·memprint, runtime·memcopy0 }, |
| [ANOEQ8] { &nohashfunc, &noequalfunc, runtime·memprint, runtime·memcopy8 }, |
| [ANOEQ16] { &nohashfunc, &noequalfunc, runtime·memprint, runtime·memcopy16 }, |
| [ANOEQ32] { &nohashfunc, &noequalfunc, runtime·memprint, runtime·memcopy32 }, |
| [ANOEQ64] { &nohashfunc, &noequalfunc, runtime·memprint, runtime·memcopy64 }, |
| [ANOEQ128] { &nohashfunc, &noequalfunc, runtime·memprint, runtime·memcopy128 }, |
| }; |
| |
| // Runtime helpers. |
| |
| // used in asm_{386,amd64}.s |
| #pragma dataflag NOPTR |
| byte runtime·aeskeysched[HashRandomBytes]; |
| |
| void |
| runtime·hashinit(void) |
| { |
| runtime·nohashcode = (uintptr)runtime·nohash; |
| runtime·noequalcode = (uintptr)runtime·noequal; |
| |
| if(NaCl) |
| return; |
| |
| // Install aes hash algorithm if we have the instructions we need |
| if((runtime·cpuid_ecx & (1 << 25)) != 0 && // aes (aesenc) |
| (runtime·cpuid_ecx & (1 << 9)) != 0 && // sse3 (pshufb) |
| (runtime·cpuid_ecx & (1 << 19)) != 0) { // sse4.1 (pinsr{d,q}) |
| byte *rnd; |
| int32 n; |
| runtime·use_aeshash = true; |
| runtime·algarray[AMEM].hash = &aeshashfunc; |
| runtime·algarray[AMEM8].hash = &aeshashfunc; |
| runtime·algarray[AMEM16].hash = &aeshashfunc; |
| runtime·algarray[AMEM32].hash = &aeshash32func; |
| runtime·algarray[AMEM64].hash = &aeshash64func; |
| runtime·algarray[AMEM128].hash = &aeshashfunc; |
| runtime·algarray[ASTRING].hash = &aeshashstrfunc; |
| // Initialize with random data so hash collisions will be hard to engineer. |
| runtime·get_random_data(&rnd, &n); |
| if(n > HashRandomBytes) |
| n = HashRandomBytes; |
| runtime·memmove(runtime·aeskeysched, rnd, n); |
| if(n < HashRandomBytes) { |
| // Not very random, but better than nothing. |
| int64 t = runtime·nanotime(); |
| while (n < HashRandomBytes) { |
| runtime·aeskeysched[n++] = (int8)(t >> (8 * (n % 8))); |
| } |
| } |
| } |
| } |