Commit b9ccd077 authored by Russ Cox's avatar Russ Cox

runtime: prep for type-specific algorithms

Equality on structs will require arbitrary code for type equality,
so change algorithm in type data from uint8 to table pointer.
In the process, trim top-level map structure from
104/80 bytes (64-bit/32-bit) to 24/12.

Equality on structs will require being able to call code generated
by the Go compiler, and C code has no way to access Go return
values, so change the hash and equal algorithm functions to take
a pointer to a result instead of returning the result.

R=ken
CC=golang-dev
https://golang.org/cl/5453043
parent 263c955f
This diff is collapsed.
...@@ -72,35 +72,6 @@ struct Strlit ...@@ -72,35 +72,6 @@ struct Strlit
char s[3]; // variable char s[3]; // variable
}; };
/*
* note this is the runtime representation
* of hashmap iterator. it is probably
* insafe to use it this way, but it puts
* all the changes in one place.
* only flag is referenced from go.
* actual placement does not matter as long
* as the size is >= actual size.
*/
typedef struct Hiter Hiter;
struct Hiter
{
uchar data[8]; // return val from next
int32 elemsize; // size of elements in table
int32 changes; // number of changes observed last time
int32 i; // stack pointer in subtable_state
int32 cycled; // actually a bool but pad for next field, a pointer
uchar last[8]; // last hash value returned
uchar cycle[8]; // the value where we started and will stop
uchar h[8]; // the hash table
struct
{
uchar sub[8]; // pointer into subtable
uchar start[8]; // pointer into start of subtable
uchar end[8]; // pointer into end of subtable
uchar pad[8];
} sub[4];
};
enum enum
{ {
Mpscale = 29, // safely smaller than bits in a long Mpscale = 29, // safely smaller than bits in a long
......
...@@ -167,7 +167,9 @@ walkrange(Node *n) ...@@ -167,7 +167,9 @@ walkrange(Node *n)
case TMAP: case TMAP:
th = typ(TARRAY); th = typ(TARRAY);
th->type = ptrto(types[TUINT8]); th->type = ptrto(types[TUINT8]);
th->bound = (sizeof(struct Hiter) + widthptr - 1) / widthptr; // see ../../pkg/runtime/hashmap.h:/hash_iter
// Size in words.
th->bound = 5 + 4*3 + 4*4/widthptr;
hit = temp(th); hit = temp(th);
fn = syslook("mapiterinit", 1); fn = syslook("mapiterinit", 1);
......
...@@ -553,10 +553,15 @@ haspointers(Type *t) ...@@ -553,10 +553,15 @@ haspointers(Type *t)
static int static int
dcommontype(Sym *s, int ot, Type *t) dcommontype(Sym *s, int ot, Type *t)
{ {
int i; int i, sizeofAlg;
Sym *sptr; Sym *sptr;
static Sym *algarray;
char *p; char *p;
sizeofAlg = 4*widthptr;
if(algarray == nil)
algarray = pkglookup("algarray", runtimepkg);
dowidth(t); dowidth(t);
if(t->sym != nil && !isptr[t->etype]) if(t->sym != nil && !isptr[t->etype])
...@@ -586,7 +591,7 @@ dcommontype(Sym *s, int ot, Type *t) ...@@ -586,7 +591,7 @@ dcommontype(Sym *s, int ot, Type *t)
// } // }
ot = duintptr(s, ot, t->width); ot = duintptr(s, ot, t->width);
ot = duint32(s, ot, typehash(t)); ot = duint32(s, ot, typehash(t));
ot = duint8(s, ot, algtype(t)); ot = duint8(s, ot, 0); // unused
ot = duint8(s, ot, t->align); // align ot = duint8(s, ot, t->align); // align
ot = duint8(s, ot, t->align); // fieldAlign ot = duint8(s, ot, t->align); // fieldAlign
i = kinds[t->etype]; i = kinds[t->etype];
...@@ -595,6 +600,7 @@ dcommontype(Sym *s, int ot, Type *t) ...@@ -595,6 +600,7 @@ dcommontype(Sym *s, int ot, Type *t)
if(!haspointers(t)) if(!haspointers(t))
i |= KindNoPointers; i |= KindNoPointers;
ot = duint8(s, ot, i); // kind ot = duint8(s, ot, i); // kind
ot = dsymptr(s, ot, algarray, algtype(t)*sizeofAlg);
p = smprint("%-uT", t); p = smprint("%-uT", t);
//print("dcommontype: %s\n", p); //print("dcommontype: %s\n", p);
ot = dgostringptr(s, ot, p); // string ot = dgostringptr(s, ot, p); // string
......
...@@ -52,7 +52,7 @@ func stringtoslicebyte(string) []byte ...@@ -52,7 +52,7 @@ func stringtoslicebyte(string) []byte
func stringtoslicerune(string) []rune func stringtoslicerune(string) []rune
func stringiter(string, int) int func stringiter(string, int) int
func stringiter2(string, int) (retk int, retv rune) func stringiter2(string, int) (retk int, retv rune)
func slicecopy(to any, fr any, wid uint32) int func copy(to any, fr any, wid uint32) int
func slicestringcopy(to any, fr any) int func slicestringcopy(to any, fr any) int
// interface conversions // interface conversions
......
...@@ -1078,7 +1078,7 @@ walkexpr(Node **np, NodeList **init) ...@@ -1078,7 +1078,7 @@ walkexpr(Node **np, NodeList **init)
if(n->right->type->etype == TSTRING) if(n->right->type->etype == TSTRING)
fn = syslook("slicestringcopy", 1); fn = syslook("slicestringcopy", 1);
else else
fn = syslook("slicecopy", 1); fn = syslook("copy", 1);
argtype(fn, n->left->type); argtype(fn, n->left->type);
argtype(fn, n->right->type); argtype(fn, n->right->type);
n = mkcall1(fn, n->type, init, n = mkcall1(fn, n->type, init,
......
...@@ -775,7 +775,7 @@ enum { ...@@ -775,7 +775,7 @@ enum {
KindNoPointers = 1<<7, KindNoPointers = 1<<7,
// size of Type interface header + CommonType structure. // size of Type interface header + CommonType structure.
CommonSize = 2*PtrSize+ 4*PtrSize + 8, CommonSize = 2*PtrSize+ 5*PtrSize + 8,
}; };
static Reloc* static Reloc*
......
...@@ -241,10 +241,11 @@ const ( ...@@ -241,10 +241,11 @@ const (
type commonType struct { type commonType struct {
size uintptr size uintptr
hash uint32 hash uint32
alg uint8 _ uint8
align uint8 align uint8
fieldAlign uint8 fieldAlign uint8
kind uint8 kind uint8
alg *uintptr
string *string string *string
*uncommonType *uncommonType
ptrToThis *runtime.Type ptrToThis *runtime.Type
......
...@@ -63,6 +63,7 @@ OFILES_arm=\ ...@@ -63,6 +63,7 @@ OFILES_arm=\
vlrt.$O\ vlrt.$O\
OFILES=\ OFILES=\
alg.$O\
asm.$O\ asm.$O\
atomic.$O\ atomic.$O\
cgocall.$O\ cgocall.$O\
......
// 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"
/*
* map and chan helpers for
* dealing with unknown types
*/
void
runtime·memhash(uintptr *h, uintptr s, void *a)
{
byte *b;
uintptr hash;
b = a;
if(sizeof(hash) == 4)
hash = 2860486313U;
else
hash = 33054211828000289ULL;
while(s > 0) {
if(sizeof(hash) == 4)
hash = (hash ^ *b) * 3267000013UL;
else
hash = (hash ^ *b) * 23344194077549503ULL;
b++;
s--;
}
*h ^= hash;
}
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:
v = *(uintptr*)a;
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);
}
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];
}
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)
{
int32 alen;
USED(s);
alen = ((String*)a)->len;
if(alen != ((String*)b)->len) {
*eq = false;
return;
}
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);
*h ^= runtime·ifacehash(*(Iface*)a);
}
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);
*h ^= runtime·efacehash(*(Eface*)a);
}
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 },
[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 },
[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 },
};
...@@ -92,11 +92,6 @@ runtime·makechan_c(ChanType *t, int64 hint) ...@@ -92,11 +92,6 @@ runtime·makechan_c(ChanType *t, int64 hint)
if(hint < 0 || (int32)hint != hint || (elem->size > 0 && hint > ((uintptr)-1) / elem->size)) if(hint < 0 || (int32)hint != hint || (elem->size > 0 && hint > ((uintptr)-1) / elem->size))
runtime·panicstring("makechan: size out of range"); runtime·panicstring("makechan: size out of range");
if(elem->alg >= nelem(runtime·algarray)) {
runtime·printf("chan(alg=%d)\n", elem->alg);
runtime·throw("runtime.makechan: unsupported elem type");
}
// calculate rounded size of Hchan // calculate rounded size of Hchan
n = sizeof(*c); n = sizeof(*c);
while(n & MAXALIGN) while(n & MAXALIGN)
...@@ -105,12 +100,12 @@ runtime·makechan_c(ChanType *t, int64 hint) ...@@ -105,12 +100,12 @@ runtime·makechan_c(ChanType *t, int64 hint)
// allocate memory in one call // allocate memory in one call
c = (Hchan*)runtime·mal(n + hint*elem->size); c = (Hchan*)runtime·mal(n + hint*elem->size);
c->elemsize = elem->size; c->elemsize = elem->size;
c->elemalg = &runtime·algarray[elem->alg]; c->elemalg = elem->alg;
c->elemalign = elem->align; c->elemalign = elem->align;
c->dataqsiz = hint; c->dataqsiz = hint;
if(debug) if(debug)
runtime·printf("makechan: chan=%p; elemsize=%D; elemalg=%d; elemalign=%d; dataqsiz=%d\n", runtime·printf("makechan: chan=%p; elemsize=%D; elemalg=%p; elemalign=%d; dataqsiz=%d\n",
c, (int64)elem->size, elem->alg, elem->align, c->dataqsiz); c, (int64)elem->size, elem->alg, elem->align, c->dataqsiz);
return c; return c;
......
This diff is collapsed.
...@@ -86,6 +86,7 @@ struct hash_iter { ...@@ -86,6 +86,7 @@ struct hash_iter {
hash_hash_t last_hash; /* last hash value returned */ hash_hash_t last_hash; /* last hash value returned */
hash_hash_t cycle; /* hash value where we started */ hash_hash_t cycle; /* hash value where we started */
struct Hmap *h; /* the hash table */ struct Hmap *h; /* the hash table */
MapType *t; /* the map type */
struct hash_iter_sub { struct hash_iter_sub {
struct hash_entry *e; /* pointer into subtable */ struct hash_entry *e; /* pointer into subtable */
struct hash_entry *start; /* start of subtable */ struct hash_entry *start; /* start of subtable */
......
...@@ -159,17 +159,18 @@ out: ...@@ -159,17 +159,18 @@ out:
static void static void
copyin(Type *t, void *src, void **dst) copyin(Type *t, void *src, void **dst)
{ {
int32 wid, alg; uintptr size;
void *p; void *p;
Alg *alg;
wid = t->size; size = t->size;
alg = t->alg; alg = t->alg;
if(wid <= sizeof(*dst)) if(size <= sizeof(*dst))
runtime·algarray[alg].copy(wid, dst, src); alg->copy(size, dst, src);
else { else {
p = runtime·mal(wid); p = runtime·mal(size);
runtime·algarray[alg].copy(wid, p, src); alg->copy(size, p, src);
*dst = p; *dst = p;
} }
} }
...@@ -177,15 +178,16 @@ copyin(Type *t, void *src, void **dst) ...@@ -177,15 +178,16 @@ copyin(Type *t, void *src, void **dst)
static void static void
copyout(Type *t, void **src, void *dst) copyout(Type *t, void **src, void *dst)
{ {
int32 wid, alg; uintptr size;
Alg *alg;
wid = t->size; size = t->size;
alg = t->alg; alg = t->alg;
if(wid <= sizeof(*src)) if(size <= sizeof(*src))
runtime·algarray[alg].copy(wid, dst, src); alg->copy(size, dst, src);
else else
runtime·algarray[alg].copy(wid, dst, *src); alg->copy(size, dst, *src);
} }
// func convT2I(typ *byte, typ2 *byte, elem any) (ret any) // func convT2I(typ *byte, typ2 *byte, elem any) (ret any)
...@@ -548,23 +550,27 @@ runtime·assertE2E2(InterfaceType* inter, Eface e, Eface ret, bool ok) ...@@ -548,23 +550,27 @@ runtime·assertE2E2(InterfaceType* inter, Eface e, Eface ret, bool ok)
static uintptr static uintptr
ifacehash1(void *data, Type *t) ifacehash1(void *data, Type *t)
{ {
int32 alg, wid; Alg *alg;
uintptr size, h;
Eface err; Eface err;
if(t == nil) if(t == nil)
return 0; return 0;
alg = t->alg; alg = t->alg;
wid = t->size; size = t->size;
if(runtime·algarray[alg].hash == runtime·nohash) { if(alg->hash == runtime·nohash) {
// calling nohash will panic too, // calling nohash will panic too,
// but we can print a better error. // but we can print a better error.
runtime·newErrorString(runtime·catstring(runtime·gostringnocopy((byte*)"hash of unhashable type "), *t->string), &err); runtime·newErrorString(runtime·catstring(runtime·gostringnocopy((byte*)"hash of unhashable type "), *t->string), &err);
runtime·panic(err); runtime·panic(err);
} }
if(wid <= sizeof(data)) h = 0;
return runtime·algarray[alg].hash(wid, &data); if(size <= sizeof(data))
return runtime·algarray[alg].hash(wid, data); alg->hash(&h, size, &data);
else
alg->hash(&h, size, data);
return h;
} }
uintptr uintptr
...@@ -584,22 +590,27 @@ runtime·efacehash(Eface a) ...@@ -584,22 +590,27 @@ runtime·efacehash(Eface a)
static bool static bool
ifaceeq1(void *data1, void *data2, Type *t) ifaceeq1(void *data1, void *data2, Type *t)
{ {
int32 alg, wid; uintptr size;
Alg *alg;
Eface err; Eface err;
bool eq;
alg = t->alg; alg = t->alg;
wid = t->size; size = t->size;
if(runtime·algarray[alg].equal == runtime·noequal) { if(alg->equal == runtime·noequal) {
// calling noequal will panic too, // calling noequal will panic too,
// but we can print a better error. // but we can print a better error.
runtime·newErrorString(runtime·catstring(runtime·gostringnocopy((byte*)"comparing uncomparable type "), *t->string), &err); runtime·newErrorString(runtime·catstring(runtime·gostringnocopy((byte*)"comparing uncomparable type "), *t->string), &err);
runtime·panic(err); runtime·panic(err);
} }
if(wid <= sizeof(data1)) eq = 0;
return runtime·algarray[alg].equal(wid, &data1, &data2); if(size <= sizeof(data1))
return runtime·algarray[alg].equal(wid, data1, data2); alg->equal(&eq, size, &data1, &data2);
else
alg->equal(&eq, size, data1, data2);
return eq;
} }
bool bool
...@@ -701,7 +712,7 @@ unsafe·Reflect(Eface e, Eface rettype, void *retaddr) ...@@ -701,7 +712,7 @@ unsafe·Reflect(Eface e, Eface rettype, void *retaddr)
if(e.type->size <= sizeof(uintptr)) { if(e.type->size <= sizeof(uintptr)) {
// Copy data into x ... // Copy data into x ...
x = 0; x = 0;
runtime·algarray[e.type->alg].copy(e.type->size, &x, &e.data); e.type->alg->copy(e.type->size, &x, &e.data);
// but then build pointer to x so that Reflect // but then build pointer to x so that Reflect
// always returns pointer to data. // always returns pointer to data.
...@@ -711,7 +722,7 @@ unsafe·Reflect(Eface e, Eface rettype, void *retaddr) ...@@ -711,7 +722,7 @@ unsafe·Reflect(Eface e, Eface rettype, void *retaddr)
// Already a pointer, but still make a copy, // Already a pointer, but still make a copy,
// to preserve value semantics for interface data. // to preserve value semantics for interface data.
p = runtime·mal(e.type->size); p = runtime·mal(e.type->size);
runtime·algarray[e.type->alg].copy(e.type->size, p, e.data); e.type->alg->copy(e.type->size, p, e.data);
} }
retaddr = p; retaddr = p;
} }
...@@ -734,7 +745,7 @@ unsafe·Unreflect(Eface typ, void *addr, Eface e) ...@@ -734,7 +745,7 @@ unsafe·Unreflect(Eface typ, void *addr, Eface e)
// Interface holds either pointer to data // Interface holds either pointer to data
// or copy of original data. // or copy of original data.
if(e.type->size <= sizeof(uintptr)) if(e.type->size <= sizeof(uintptr))
runtime·algarray[e.type->alg].copy(e.type->size, &e.data, addr); e.type->alg->copy(e.type->size, &e.data, addr);
else { else {
// Easier: already a pointer to data. // Easier: already a pointer to data.
// TODO(rsc): Should this make a copy? // TODO(rsc): Should this make a copy?
......
...@@ -322,338 +322,6 @@ runtime·check(void) ...@@ -322,338 +322,6 @@ runtime·check(void)
runtime·initsig(0); runtime·initsig(0);
} }
/*
* map and chan helpers for
* dealing with unknown types
*/
static uintptr
memhash(uint32 s, void *a)
{
byte *b;
uintptr hash;
b = a;
if(sizeof(hash) == 4)
hash = 2860486313U;
else
hash = 33054211828000289ULL;
while(s > 0) {
if(sizeof(hash) == 4)
hash = (hash ^ *b) * 3267000013UL;
else
hash = (hash ^ *b) * 23344194077549503ULL;
b++;
s--;
}
return hash;
}
static uint32
memequal(uint32 s, void *a, void *b)
{
byte *ba, *bb, *aend;
if(a == b)
return 1;
ba = a;
bb = b;
aend = ba+s;
while(ba != aend) {
if(*ba != *bb)
return 0;
ba++;
bb++;
}
return 1;
}
static void
memprint(uint32 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(v);
}
static void
memcopy(uint32 s, void *a, void *b)
{
if(b == nil) {
runtime·memclr(a,s);
return;
}
runtime·memmove(a,b,s);
}
static uint32
memequal8(uint32 s, uint8 *a, uint8 *b)
{
USED(s);
return *a == *b;
}
static void
memcopy8(uint32 s, uint8 *a, uint8 *b)
{
USED(s);
if(b == nil) {
*a = 0;
return;
}
*a = *b;
}
static uint32
memequal16(uint32 s, uint16 *a, uint16 *b)
{
USED(s);
return *a == *b;
}
static void
memcopy16(uint32 s, uint16 *a, uint16 *b)
{
USED(s);
if(b == nil) {
*a = 0;
return;
}
*a = *b;
}
static uint32
memequal32(uint32 s, uint32 *a, uint32 *b)
{
USED(s);
return *a == *b;
}
static void
memcopy32(uint32 s, uint32 *a, uint32 *b)
{
USED(s);
if(b == nil) {
*a = 0;
return;
}
*a = *b;
}
static uint32
memequal64(uint32 s, uint64 *a, uint64 *b)
{
USED(s);
return *a == *b;
}
static void
memcopy64(uint32 s, uint64 *a, uint64 *b)
{
USED(s);
if(b == nil) {
*a = 0;
return;
}
*a = *b;
}
static uint32
memequal128(uint32 s, uint64 *a, uint64 *b)
{
USED(s);
return a[0] == b[0] && a[1] == b[1];
}
static void
memcopy128(uint32 s, uint64 *a, uint64 *b)
{
USED(s);
if(b == nil) {
a[0] = 0;
a[1] = 0;
return;
}
a[0] = b[0];
a[1] = b[1];
}
static void
slicecopy(uint32 s, Slice *a, Slice *b)
{
USED(s);
if(b == nil) {
a->array = 0;
a->len = 0;
a->cap = 0;
return;
}
a->array = b->array;
a->len = b->len;
a->cap = b->cap;
}
static uintptr
strhash(uint32 s, String *a)
{
USED(s);
return memhash((*a).len, (*a).str);
}
static uint32
strequal(uint32 s, String *a, String *b)
{
int32 alen;
USED(s);
alen = a->len;
if(alen != b->len)
return false;
return memequal(alen, a->str, b->str);
}
static void
strprint(uint32 s, String *a)
{
USED(s);
runtime·printstring(*a);
}
static void
strcopy(uint32 s, String *a, String *b)
{
USED(s);
if(b == nil) {
a->str = 0;
a->len = 0;
return;
}
a->str = b->str;
a->len = b->len;
}
static uintptr
interhash(uint32 s, Iface *a)
{
USED(s);
return runtime·ifacehash(*a);
}
static void
interprint(uint32 s, Iface *a)
{
USED(s);
runtime·printiface(*a);
}
static uint32
interequal(uint32 s, Iface *a, Iface *b)
{
USED(s);
return runtime·ifaceeq_c(*a, *b);
}
static void
intercopy(uint32 s, Iface *a, Iface *b)
{
USED(s);
if(b == nil) {
a->tab = 0;
a->data = 0;
return;
}
a->tab = b->tab;
a->data = b->data;
}
static uintptr
nilinterhash(uint32 s, Eface *a)
{
USED(s);
return runtime·efacehash(*a);
}
static void
nilinterprint(uint32 s, Eface *a)
{
USED(s);
runtime·printeface(*a);
}
static uint32
nilinterequal(uint32 s, Eface *a, Eface *b)
{
USED(s);
return runtime·efaceeq_c(*a, *b);
}
static void
nilintercopy(uint32 s, Eface *a, Eface *b)
{
USED(s);
if(b == nil) {
a->type = 0;
a->data = 0;
return;
}
a->type = b->type;
a->data = b->data;
}
uintptr
runtime·nohash(uint32 s, void *a)
{
USED(s);
USED(a);
runtime·panicstring("hash of unhashable type");
return 0;
}
uint32
runtime·noequal(uint32 s, void *a, void *b)
{
USED(s);
USED(a);
USED(b);
runtime·panicstring("comparing uncomparable types");
return 0;
}
Alg
runtime·algarray[] =
{
[AMEM] { memhash, memequal, memprint, memcopy },
[ANOEQ] { runtime·nohash, runtime·noequal, memprint, memcopy },
[ASTRING] { (void*)strhash, (void*)strequal, (void*)strprint, (void*)strcopy },
[AINTER] { (void*)interhash, (void*)interequal, (void*)interprint, (void*)intercopy },
[ANILINTER] { (void*)nilinterhash, (void*)nilinterequal, (void*)nilinterprint, (void*)nilintercopy },
[ASLICE] { (void*)runtime·nohash, (void*)runtime·noequal, (void*)memprint, (void*)slicecopy },
[AMEM8] { memhash, (void*)memequal8, memprint, (void*)memcopy8 },
[AMEM16] { memhash, (void*)memequal16, memprint, (void*)memcopy16 },
[AMEM32] { memhash, (void*)memequal32, memprint, (void*)memcopy32 },
[AMEM64] { memhash, (void*)memequal64, memprint, (void*)memcopy64 },
[AMEM128] { memhash, (void*)memequal128, memprint, (void*)memcopy128 },
[ANOEQ8] { runtime·nohash, runtime·noequal, memprint, (void*)memcopy8 },
[ANOEQ16] { runtime·nohash, runtime·noequal, memprint, (void*)memcopy16 },
[ANOEQ32] { runtime·nohash, runtime·noequal, memprint, (void*)memcopy32 },
[ANOEQ64] { runtime·nohash, runtime·noequal, memprint, (void*)memcopy64 },
[ANOEQ128] { runtime·nohash, runtime·noequal, memprint, (void*)memcopy128 },
};
void void
runtime·Caller(int32 skip, uintptr retpc, String retfile, int32 retline, bool retbool) runtime·Caller(int32 skip, uintptr retpc, String retfile, int32 retline, bool retbool)
{ {
......
...@@ -43,7 +43,6 @@ typedef int32 intptr; ...@@ -43,7 +43,6 @@ typedef int32 intptr;
*/ */
typedef uint8 bool; typedef uint8 bool;
typedef uint8 byte; typedef uint8 byte;
typedef struct Alg Alg;
typedef struct Func Func; typedef struct Func Func;
typedef struct G G; typedef struct G G;
typedef struct Gobuf Gobuf; typedef struct Gobuf Gobuf;
...@@ -260,13 +259,6 @@ struct Stktop ...@@ -260,13 +259,6 @@ struct Stktop
uintptr free; // if free>0, call stackfree using free as size uintptr free; // if free>0, call stackfree using free as size
bool panic; // is this frame the top of a panic? bool panic; // is this frame the top of a panic?
}; };
struct Alg
{
uintptr (*hash)(uint32, void*);
uint32 (*equal)(uint32, void*, void*);
void (*print)(uint32, void*);
void (*copy)(uint32, void*, void*);
};
struct SigTab struct SigTab
{ {
int32 flags; int32 flags;
...@@ -356,6 +348,13 @@ struct Timer ...@@ -356,6 +348,13 @@ struct Timer
/* /*
* known to compiler * known to compiler
*/ */
enum {
Structrnd = sizeof(uintptr)
};
/*
* type algorithms - known to compiler
*/
enum enum
{ {
AMEM, AMEM,
...@@ -376,11 +375,45 @@ enum ...@@ -376,11 +375,45 @@ enum
ANOEQ128, ANOEQ128,
Amax Amax
}; };
typedef struct Alg Alg;
struct Alg
{
void (*hash)(uintptr*, uintptr, void*);
void (*equal)(bool*, uintptr, void*, void*);
void (*print)(uintptr, void*);
void (*copy)(uintptr, void*, void*);
};
extern Alg runtime·algarray[Amax];
enum { void runtime·memhash(uintptr*, uintptr, void*);
Structrnd = sizeof(uintptr) void runtime·nohash(uintptr*, uintptr, void*);
}; void runtime·strhash(uintptr*, uintptr, void*);
void runtime·interhash(uintptr*, uintptr, void*);
void runtime·nilinterhash(uintptr*, uintptr, void*);
void runtime·memequal(bool*, uintptr, void*, void*);
void runtime·noequal(bool*, uintptr, void*, void*);
void runtime·strequal(bool*, uintptr, void*, void*);
void runtime·interequal(bool*, uintptr, void*, void*);
void runtime·nilinterequal(bool*, uintptr, void*, void*);
void runtime·memprint(uintptr, void*);
void runtime·strprint(uintptr, void*);
void runtime·interprint(uintptr, void*);
void runtime·nilinterprint(uintptr, void*);
void runtime·memcopy(uintptr, void*, void*);
void runtime·memcopy8(uintptr, void*, void*);
void runtime·memcopy16(uintptr, void*, void*);
void runtime·memcopy32(uintptr, void*, void*);
void runtime·memcopy64(uintptr, void*, void*);
void runtime·memcopy128(uintptr, void*, void*);
void runtime·memcopy(uintptr, void*, void*);
void runtime·strcopy(uintptr, void*, void*);
void runtime·algslicecopy(uintptr, void*, void*);
void runtime·intercopy(uintptr, void*, void*);
void runtime·nilintercopy(uintptr, void*, void*);
/* /*
* deferred subroutine calls * deferred subroutine calls
...@@ -410,7 +443,6 @@ struct Panic ...@@ -410,7 +443,6 @@ struct Panic
/* /*
* external data * external data
*/ */
extern Alg runtime·algarray[Amax];
extern String runtime·emptystring; extern String runtime·emptystring;
G* runtime·allg; G* runtime·allg;
G* runtime·lastg; G* runtime·lastg;
...@@ -498,8 +530,6 @@ bool runtime·ifaceeq_c(Iface, Iface); ...@@ -498,8 +530,6 @@ bool runtime·ifaceeq_c(Iface, Iface);
bool runtime·efaceeq_c(Eface, Eface); bool runtime·efaceeq_c(Eface, Eface);
uintptr runtime·ifacehash(Iface); uintptr runtime·ifacehash(Iface);
uintptr runtime·efacehash(Eface); uintptr runtime·efacehash(Eface);
uintptr runtime·nohash(uint32, void*);
uint32 runtime·noequal(uint32, void*, void*);
void* runtime·malloc(uintptr size); void* runtime·malloc(uintptr size);
void runtime·free(void *v); void runtime·free(void *v);
bool runtime·addfinalizer(void*, void(*fn)(void*), int32); bool runtime·addfinalizer(void*, void(*fn)(void*), int32);
......
...@@ -11,7 +11,7 @@ static int32 debug = 0; ...@@ -11,7 +11,7 @@ static int32 debug = 0;
static void makeslice1(SliceType*, int32, int32, Slice*); static void makeslice1(SliceType*, int32, int32, Slice*);
static void growslice1(SliceType*, Slice, int32, Slice *); static void growslice1(SliceType*, Slice, int32, Slice *);
void runtime·slicecopy(Slice to, Slice fm, uintptr width, int32 ret); void runtime·copy(Slice to, Slice fm, uintptr width, int32 ret);
// see also unsafe·NewArray // see also unsafe·NewArray
// makeslice(typ *Type, len, cap int64) (ary []any); // makeslice(typ *Type, len, cap int64) (ary []any);
...@@ -290,9 +290,9 @@ runtime·slicearray(byte* old, uint64 nel, uint64 lb, uint64 hb, uint64 width, S ...@@ -290,9 +290,9 @@ runtime·slicearray(byte* old, uint64 nel, uint64 lb, uint64 hb, uint64 width, S
} }
} }
// slicecopy(to any, fr any, wid uint32) int // copy(to any, fr any, wid uint32) int
void void
runtime·slicecopy(Slice to, Slice fm, uintptr width, int32 ret) runtime·copy(Slice to, Slice fm, uintptr width, int32 ret)
{ {
if(fm.len == 0 || to.len == 0 || width == 0) { if(fm.len == 0 || to.len == 0 || width == 0) {
ret = 0; ret = 0;
......
...@@ -27,15 +27,16 @@ type Type interface{} ...@@ -27,15 +27,16 @@ type Type interface{}
// All types begin with a few common fields needed for // All types begin with a few common fields needed for
// the interface runtime. // the interface runtime.
type commonType struct { type commonType struct {
size uintptr // size in bytes size uintptr // size in bytes
hash uint32 // hash of type; avoids computation in hash tables hash uint32 // hash of type; avoids computation in hash tables
alg uint8 // algorithm for copy+hash+cmp (../runtime/runtime.h:/AMEM) _ uint8 // unused
align uint8 // alignment of variable with this type align uint8 // alignment of variable with this type
fieldAlign uint8 // alignment of struct field with this type fieldAlign uint8 // alignment of struct field with this type
kind uint8 // enumeration for C kind uint8 // enumeration for C
string *string // string form; unnecessary but undeniably useful alg *uintptr // algorithm table (../runtime/runtime.h:/Alg)
*uncommonType // (relatively) uncommon fields string *string // string form; unnecessary but undeniably useful
ptrToThis *Type // pointer to this type, if used in binary or has methods *uncommonType // (relatively) uncommon fields
ptrToThis *Type // pointer to this type, if used in binary or has methods
} }
// Values for commonType.kind. // Values for commonType.kind.
......
...@@ -23,10 +23,11 @@ struct CommonType ...@@ -23,10 +23,11 @@ struct CommonType
{ {
uintptr size; uintptr size;
uint32 hash; uint32 hash;
uint8 alg; uint8 _unused;
uint8 align; uint8 align;
uint8 fieldAlign; uint8 fieldAlign;
uint8 kind; uint8 kind;
Alg *alg;
String *string; String *string;
UncommonType *x; UncommonType *x;
Type *ptrto; Type *ptrto;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment