2011-12-05 07:40:22 -07:00
|
|
|
// 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.
|
|
|
|
|
|
|
|
#include "runtime.h"
|
2011-12-12 20:22:09 -07:00
|
|
|
#include "type.h"
|
2011-12-05 07:40:22 -07:00
|
|
|
|
2012-06-13 13:52:32 -06:00
|
|
|
#define M0 (sizeof(uintptr)==4 ? 2860486313UL : 33054211828000289ULL)
|
|
|
|
#define M1 (sizeof(uintptr)==4 ? 3267000013UL : 23344194077549503ULL)
|
|
|
|
|
2011-12-05 07:40:22 -07:00
|
|
|
/*
|
|
|
|
* map and chan helpers for
|
|
|
|
* dealing with unknown types
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
runtime·memhash(uintptr *h, uintptr s, void *a)
|
|
|
|
{
|
|
|
|
byte *b;
|
|
|
|
uintptr hash;
|
|
|
|
|
|
|
|
b = a;
|
2013-01-04 08:53:42 -07:00
|
|
|
hash = M0 ^ *h;
|
2011-12-05 07:40:22 -07:00
|
|
|
while(s > 0) {
|
2012-06-13 13:52:32 -06:00
|
|
|
hash = (hash ^ *b) * M1;
|
2011-12-05 07:40:22 -07:00
|
|
|
b++;
|
|
|
|
s--;
|
|
|
|
}
|
2013-01-04 08:53:42 -07:00
|
|
|
*h = hash;
|
2011-12-05 07:40:22 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
runtime·memequal(bool *eq, uintptr s, void *a, void *b)
|
|
|
|
{
|
|
|
|
byte *ba, *bb, *aend;
|
|
|
|
|
|
|
|
if(a == b) {
|
|
|
|
*eq = 1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ba = a;
|
|
|
|
bb = b;
|
|
|
|
aend = ba+s;
|
|
|
|
while(ba != aend) {
|
|
|
|
if(*ba != *bb) {
|
|
|
|
*eq = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ba++;
|
|
|
|
bb++;
|
|
|
|
}
|
|
|
|
*eq = 1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
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:
|
2011-12-12 20:22:09 -07:00
|
|
|
v = *(uint32*)a;
|
2011-12-05 07:40:22 -07:00
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
v = *(uint64*)a;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
runtime·printint(v);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
runtime·memcopy(uintptr s, void *a, void *b)
|
|
|
|
{
|
|
|
|
if(b == nil) {
|
|
|
|
runtime·memclr(a, s);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
runtime·memmove(a, b, s);
|
|
|
|
}
|
|
|
|
|
2012-01-19 23:32:55 -07:00
|
|
|
void
|
|
|
|
runtime·memequal0(bool *eq, uintptr s, void *a, void *b)
|
|
|
|
{
|
|
|
|
USED(s);
|
|
|
|
USED(a);
|
|
|
|
USED(b);
|
|
|
|
*eq = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
runtime·memcopy0(uintptr s, void *a, void *b)
|
|
|
|
{
|
|
|
|
USED(s);
|
|
|
|
USED(a);
|
|
|
|
USED(b);
|
|
|
|
}
|
|
|
|
|
2011-12-05 07:40:22 -07:00
|
|
|
void
|
|
|
|
runtime·memequal8(bool *eq, uintptr s, void *a, void *b)
|
|
|
|
{
|
|
|
|
USED(s);
|
|
|
|
*eq = *(uint8*)a == *(uint8*)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·memequal16(bool *eq, uintptr s, void *a, void *b)
|
|
|
|
{
|
|
|
|
USED(s);
|
|
|
|
*eq = *(uint16*)a == *(uint16*)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·memequal32(bool *eq, uintptr s, void *a, void *b)
|
|
|
|
{
|
|
|
|
USED(s);
|
|
|
|
*eq = *(uint32*)a == *(uint32*)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·memequal64(bool *eq, uintptr s, void *a, void *b)
|
|
|
|
{
|
|
|
|
USED(s);
|
|
|
|
*eq = *(uint64*)a == *(uint64*)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·memequal128(bool *eq, uintptr s, void *a, void *b)
|
|
|
|
{
|
|
|
|
USED(s);
|
|
|
|
*eq = ((uint64*)a)[0] == ((uint64*)b)[0] && ((uint64*)a)[1] == ((uint64*)b)[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
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];
|
|
|
|
}
|
|
|
|
|
2012-01-26 14:25:07 -07:00
|
|
|
void
|
|
|
|
runtime·f32equal(bool *eq, uintptr s, void *a, void *b)
|
|
|
|
{
|
|
|
|
USED(s);
|
|
|
|
*eq = *(float32*)a == *(float32*)b;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
runtime·f64equal(bool *eq, uintptr s, void *a, void *b)
|
|
|
|
{
|
|
|
|
USED(s);
|
|
|
|
*eq = *(float64*)a == *(float64*)b;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
runtime·c64equal(bool *eq, uintptr s, void *a, void *b)
|
|
|
|
{
|
|
|
|
Complex64 *ca, *cb;
|
|
|
|
|
|
|
|
USED(s);
|
|
|
|
ca = a;
|
|
|
|
cb = b;
|
|
|
|
*eq = ca->real == cb->real && ca->imag == cb->imag;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
runtime·c128equal(bool *eq, uintptr s, void *a, void *b)
|
|
|
|
{
|
|
|
|
Complex128 *ca, *cb;
|
|
|
|
|
|
|
|
USED(s);
|
|
|
|
ca = a;
|
|
|
|
cb = b;
|
|
|
|
*eq = ca->real == cb->real && ca->imag == cb->imag;
|
|
|
|
}
|
|
|
|
|
|
|
|
// NOTE: Because NaN != NaN, a map can contain any
|
|
|
|
// number of (mostly useless) entries keyed with NaNs.
|
|
|
|
// To avoid long hash chains, we assign a random number
|
|
|
|
// as the hash value for a NaN.
|
|
|
|
|
|
|
|
void
|
|
|
|
runtime·f32hash(uintptr *h, uintptr s, void *a)
|
|
|
|
{
|
|
|
|
uintptr hash;
|
|
|
|
float32 f;
|
|
|
|
|
|
|
|
USED(s);
|
|
|
|
f = *(float32*)a;
|
|
|
|
if(f == 0)
|
|
|
|
hash = 0; // +0, -0
|
|
|
|
else if(f != f)
|
|
|
|
hash = runtime·fastrand1(); // any kind of NaN
|
|
|
|
else
|
|
|
|
hash = *(uint32*)a;
|
2012-06-13 13:52:32 -06:00
|
|
|
*h = (*h ^ hash ^ M0) * M1;
|
2012-01-26 14:25:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
runtime·f64hash(uintptr *h, uintptr s, void *a)
|
|
|
|
{
|
|
|
|
uintptr hash;
|
|
|
|
float64 f;
|
|
|
|
uint64 u;
|
|
|
|
|
|
|
|
USED(s);
|
2012-01-30 09:10:59 -07:00
|
|
|
f = *(float64*)a;
|
2012-01-26 14:25:07 -07:00
|
|
|
if(f == 0)
|
|
|
|
hash = 0; // +0, -0
|
|
|
|
else if(f != f)
|
|
|
|
hash = runtime·fastrand1(); // any kind of NaN
|
|
|
|
else {
|
|
|
|
u = *(uint64*)a;
|
|
|
|
if(sizeof(uintptr) == 4)
|
2012-06-13 13:52:32 -06:00
|
|
|
hash = ((uint32)(u>>32) * M1) ^ (uint32)u;
|
2012-01-26 14:25:07 -07:00
|
|
|
else
|
|
|
|
hash = u;
|
|
|
|
}
|
2012-06-13 13:52:32 -06:00
|
|
|
*h = (*h ^ hash ^ M0) * M1;
|
2012-01-26 14:25:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
runtime·c64hash(uintptr *h, uintptr s, void *a)
|
|
|
|
{
|
|
|
|
USED(s);
|
|
|
|
runtime·f32hash(h, 0, a);
|
|
|
|
runtime·f32hash(h, 0, (float32*)a+1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
runtime·c128hash(uintptr *h, uintptr s, void *a)
|
|
|
|
{
|
|
|
|
USED(s);
|
|
|
|
runtime·f64hash(h, 0, a);
|
|
|
|
runtime·f64hash(h, 0, (float64*)a+1);
|
|
|
|
}
|
|
|
|
|
2011-12-05 07:40:22 -07:00
|
|
|
void
|
|
|
|
runtime·slicecopy(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·strhash(uintptr *h, uintptr s, void *a)
|
|
|
|
{
|
|
|
|
USED(s);
|
|
|
|
runtime·memhash(h, ((String*)a)->len, ((String*)a)->str);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
runtime·strequal(bool *eq, uintptr s, void *a, void *b)
|
|
|
|
{
|
2012-09-24 12:58:34 -06:00
|
|
|
intgo alen;
|
2011-12-05 07:40:22 -07:00
|
|
|
|
|
|
|
USED(s);
|
|
|
|
alen = ((String*)a)->len;
|
|
|
|
if(alen != ((String*)b)->len) {
|
|
|
|
*eq = false;
|
|
|
|
return;
|
|
|
|
}
|
2012-08-05 13:35:41 -06:00
|
|
|
if(((String*)a)->str == ((String*)b)->str) {
|
|
|
|
*eq = true;
|
|
|
|
return;
|
|
|
|
}
|
2011-12-05 07:40:22 -07:00
|
|
|
runtime·memequal(eq, alen, ((String*)a)->str, ((String*)b)->str);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
runtime·strprint(uintptr s, void *a)
|
|
|
|
{
|
|
|
|
USED(s);
|
|
|
|
runtime·printstring(*(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·interhash(uintptr *h, uintptr s, void *a)
|
|
|
|
{
|
|
|
|
USED(s);
|
2013-01-04 08:53:42 -07:00
|
|
|
*h = runtime·ifacehash(*(Iface*)a, *h ^ M0) * M1;
|
2011-12-05 07:40:22 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
runtime·interprint(uintptr s, void *a)
|
|
|
|
{
|
|
|
|
USED(s);
|
|
|
|
runtime·printiface(*(Iface*)a);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
runtime·interequal(bool *eq, uintptr s, void *a, void *b)
|
|
|
|
{
|
|
|
|
USED(s);
|
|
|
|
*eq = runtime·ifaceeq_c(*(Iface*)a, *(Iface*)b);
|
|
|
|
}
|
|
|
|
|
|
|
|
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·nilinterhash(uintptr *h, uintptr s, void *a)
|
|
|
|
{
|
|
|
|
USED(s);
|
2013-01-04 08:53:42 -07:00
|
|
|
*h = runtime·efacehash(*(Eface*)a, *h ^ M0) * M1;
|
2011-12-05 07:40:22 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
runtime·nilinterprint(uintptr s, void *a)
|
|
|
|
{
|
|
|
|
USED(s);
|
|
|
|
runtime·printeface(*(Eface*)a);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
runtime·nilinterequal(bool *eq, uintptr s, void *a, void *b)
|
|
|
|
{
|
|
|
|
USED(s);
|
|
|
|
*eq = runtime·efaceeq_c(*(Eface*)a, *(Eface*)b);
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
runtime·nohash(uintptr *h, uintptr s, void *a)
|
|
|
|
{
|
|
|
|
USED(s);
|
|
|
|
USED(a);
|
|
|
|
USED(h);
|
|
|
|
runtime·panicstring("hash of unhashable type");
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
runtime·noequal(bool *eq, uintptr s, void *a, void *b)
|
|
|
|
{
|
|
|
|
USED(s);
|
|
|
|
USED(a);
|
|
|
|
USED(b);
|
|
|
|
USED(eq);
|
|
|
|
runtime·panicstring("comparing uncomparable types");
|
|
|
|
}
|
|
|
|
|
|
|
|
Alg
|
|
|
|
runtime·algarray[] =
|
|
|
|
{
|
|
|
|
[AMEM] { runtime·memhash, runtime·memequal, runtime·memprint, runtime·memcopy },
|
|
|
|
[ANOEQ] { runtime·nohash, runtime·noequal, runtime·memprint, runtime·memcopy },
|
|
|
|
[ASTRING] { runtime·strhash, runtime·strequal, runtime·strprint, runtime·strcopy },
|
|
|
|
[AINTER] { runtime·interhash, runtime·interequal, runtime·interprint, runtime·intercopy },
|
|
|
|
[ANILINTER] { runtime·nilinterhash, runtime·nilinterequal, runtime·nilinterprint, runtime·nilintercopy },
|
|
|
|
[ASLICE] { runtime·nohash, runtime·noequal, runtime·memprint, runtime·slicecopy },
|
2012-01-26 14:25:07 -07:00
|
|
|
[AFLOAT32] { runtime·f32hash, runtime·f32equal, runtime·memprint, runtime·memcopy },
|
|
|
|
[AFLOAT64] { runtime·f64hash, runtime·f64equal, runtime·memprint, runtime·memcopy },
|
|
|
|
[ACPLX64] { runtime·c64hash, runtime·c64equal, runtime·memprint, runtime·memcopy },
|
|
|
|
[ACPLX128] { runtime·c128hash, runtime·c128equal, runtime·memprint, runtime·memcopy },
|
2012-01-19 23:32:55 -07:00
|
|
|
[AMEM0] { runtime·memhash, runtime·memequal0, runtime·memprint, runtime·memcopy0 },
|
2011-12-05 07:40:22 -07:00
|
|
|
[AMEM8] { runtime·memhash, runtime·memequal8, runtime·memprint, runtime·memcopy8 },
|
|
|
|
[AMEM16] { runtime·memhash, runtime·memequal16, runtime·memprint, runtime·memcopy16 },
|
|
|
|
[AMEM32] { runtime·memhash, runtime·memequal32, runtime·memprint, runtime·memcopy32 },
|
|
|
|
[AMEM64] { runtime·memhash, runtime·memequal64, runtime·memprint, runtime·memcopy64 },
|
|
|
|
[AMEM128] { runtime·memhash, runtime·memequal128, runtime·memprint, runtime·memcopy128 },
|
2012-01-19 23:32:55 -07:00
|
|
|
[ANOEQ0] { runtime·nohash, runtime·noequal, runtime·memprint, runtime·memcopy0 },
|
2011-12-05 07:40:22 -07:00
|
|
|
[ANOEQ8] { runtime·nohash, runtime·noequal, runtime·memprint, runtime·memcopy8 },
|
|
|
|
[ANOEQ16] { runtime·nohash, runtime·noequal, runtime·memprint, runtime·memcopy16 },
|
|
|
|
[ANOEQ32] { runtime·nohash, runtime·noequal, runtime·memprint, runtime·memcopy32 },
|
|
|
|
[ANOEQ64] { runtime·nohash, runtime·noequal, runtime·memprint, runtime·memcopy64 },
|
|
|
|
[ANOEQ128] { runtime·nohash, runtime·noequal, runtime·memprint, runtime·memcopy128 },
|
|
|
|
};
|
|
|
|
|
2011-12-12 20:22:09 -07:00
|
|
|
// Runtime helpers.
|
|
|
|
|
|
|
|
// func equal(t *Type, x T, y T) (ret bool)
|
|
|
|
#pragma textflag 7
|
|
|
|
void
|
|
|
|
runtime·equal(Type *t, ...)
|
|
|
|
{
|
|
|
|
byte *x, *y;
|
2012-07-31 21:02:46 -06:00
|
|
|
uintptr ret;
|
2011-12-12 20:22:09 -07:00
|
|
|
|
|
|
|
x = (byte*)(&t+1);
|
2012-08-06 19:49:56 -06:00
|
|
|
y = x + t->size;
|
2012-07-31 21:02:46 -06:00
|
|
|
ret = (uintptr)(y + t->size);
|
|
|
|
ret = ROUND(ret, Structrnd);
|
|
|
|
t->alg->equal((bool*)ret, t->size, x, y);
|
2011-12-12 20:22:09 -07:00
|
|
|
}
|