1
0
mirror of https://github.com/golang/go synced 2024-11-25 08:57:58 -07:00

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
This commit is contained in:
Russ Cox 2011-12-05 09:40:22 -05:00
parent 263c955f2f
commit b9ccd077dc
19 changed files with 670 additions and 722 deletions

View File

@ -1,116 +1,116 @@
char *runtimeimport = char *runtimeimport =
"package runtime\n" "package runtime\n"
"import runtime \"runtime\"\n" "import runtime \"runtime\"\n"
"func @\"\".new (typ *byte) *any\n" "func @\"\".new(typ *byte) *any\n"
"func @\"\".panicindex ()\n" "func @\"\".panicindex()\n"
"func @\"\".panicslice ()\n" "func @\"\".panicslice()\n"
"func @\"\".throwreturn ()\n" "func @\"\".throwreturn()\n"
"func @\"\".throwinit ()\n" "func @\"\".throwinit()\n"
"func @\"\".panicwrap (? string, ? string, ? string)\n" "func @\"\".panicwrap(? string, ? string, ? string)\n"
"func @\"\".panic (? interface { })\n" "func @\"\".panic(? interface {})\n"
"func @\"\".recover (? *int32) interface { }\n" "func @\"\".recover(? *int32) interface {}\n"
"func @\"\".printbool (? bool)\n" "func @\"\".printbool(? bool)\n"
"func @\"\".printfloat (? float64)\n" "func @\"\".printfloat(? float64)\n"
"func @\"\".printint (? int64)\n" "func @\"\".printint(? int64)\n"
"func @\"\".printuint (? uint64)\n" "func @\"\".printuint(? uint64)\n"
"func @\"\".printcomplex (? complex128)\n" "func @\"\".printcomplex(? complex128)\n"
"func @\"\".printstring (? string)\n" "func @\"\".printstring(? string)\n"
"func @\"\".printpointer (? any)\n" "func @\"\".printpointer(? any)\n"
"func @\"\".printiface (? any)\n" "func @\"\".printiface(? any)\n"
"func @\"\".printeface (? any)\n" "func @\"\".printeface(? any)\n"
"func @\"\".printslice (? any)\n" "func @\"\".printslice(? any)\n"
"func @\"\".printnl ()\n" "func @\"\".printnl()\n"
"func @\"\".printsp ()\n" "func @\"\".printsp()\n"
"func @\"\".goprintf ()\n" "func @\"\".goprintf()\n"
"func @\"\".concatstring ()\n" "func @\"\".concatstring()\n"
"func @\"\".append ()\n" "func @\"\".append()\n"
"func @\"\".appendslice (typ *byte, x any, y []any) any\n" "func @\"\".appendslice(typ *byte, x any, y []any) any\n"
"func @\"\".appendstr (typ *byte, x []byte, y string) []byte\n" "func @\"\".appendstr(typ *byte, x []byte, y string) []byte\n"
"func @\"\".cmpstring (? string, ? string) int\n" "func @\"\".cmpstring(? string, ? string) int\n"
"func @\"\".slicestring (? string, ? int, ? int) string\n" "func @\"\".slicestring(? string, ? int, ? int) string\n"
"func @\"\".slicestring1 (? string, ? int) string\n" "func @\"\".slicestring1(? string, ? int) string\n"
"func @\"\".intstring (? int64) string\n" "func @\"\".intstring(? int64) string\n"
"func @\"\".slicebytetostring (? []byte) string\n" "func @\"\".slicebytetostring(? []byte) string\n"
"func @\"\".slicerunetostring (? []rune) string\n" "func @\"\".slicerunetostring(? []rune) string\n"
"func @\"\".stringtoslicebyte (? string) []byte\n" "func @\"\".stringtoslicebyte(? string) []byte\n"
"func @\"\".stringtoslicerune (? string) []rune\n" "func @\"\".stringtoslicerune(? string) []rune\n"
"func @\"\".stringiter (? string, ? int) int\n" "func @\"\".stringiter(? string, ? int) int\n"
"func @\"\".stringiter2 (? string, ? int) (retk int, retv rune)\n" "func @\"\".stringiter2(? string, ? int) (retk int, retv rune)\n"
"func @\"\".slicecopy (to any, fr any, wid uint32) int\n" "func @\"\".copy(to any, fr any, wid uint32) int\n"
"func @\"\".slicestringcopy (to any, fr any) int\n" "func @\"\".slicestringcopy(to any, fr any) int\n"
"func @\"\".convI2E (elem any) any\n" "func @\"\".convI2E(elem any) any\n"
"func @\"\".convI2I (typ *byte, elem any) any\n" "func @\"\".convI2I(typ *byte, elem any) any\n"
"func @\"\".convT2E (typ *byte, elem any) any\n" "func @\"\".convT2E(typ *byte, elem any) any\n"
"func @\"\".convT2I (typ *byte, typ2 *byte, elem any) any\n" "func @\"\".convT2I(typ *byte, typ2 *byte, elem any) any\n"
"func @\"\".assertE2E (typ *byte, iface any) any\n" "func @\"\".assertE2E(typ *byte, iface any) any\n"
"func @\"\".assertE2E2 (typ *byte, iface any) (ret any, ok bool)\n" "func @\"\".assertE2E2(typ *byte, iface any) (ret any, ok bool)\n"
"func @\"\".assertE2I (typ *byte, iface any) any\n" "func @\"\".assertE2I(typ *byte, iface any) any\n"
"func @\"\".assertE2I2 (typ *byte, iface any) (ret any, ok bool)\n" "func @\"\".assertE2I2(typ *byte, iface any) (ret any, ok bool)\n"
"func @\"\".assertE2T (typ *byte, iface any) any\n" "func @\"\".assertE2T(typ *byte, iface any) any\n"
"func @\"\".assertE2T2 (typ *byte, iface any) (ret any, ok bool)\n" "func @\"\".assertE2T2(typ *byte, iface any) (ret any, ok bool)\n"
"func @\"\".assertI2E (typ *byte, iface any) any\n" "func @\"\".assertI2E(typ *byte, iface any) any\n"
"func @\"\".assertI2E2 (typ *byte, iface any) (ret any, ok bool)\n" "func @\"\".assertI2E2(typ *byte, iface any) (ret any, ok bool)\n"
"func @\"\".assertI2I (typ *byte, iface any) any\n" "func @\"\".assertI2I(typ *byte, iface any) any\n"
"func @\"\".assertI2I2 (typ *byte, iface any) (ret any, ok bool)\n" "func @\"\".assertI2I2(typ *byte, iface any) (ret any, ok bool)\n"
"func @\"\".assertI2T (typ *byte, iface any) any\n" "func @\"\".assertI2T(typ *byte, iface any) any\n"
"func @\"\".assertI2T2 (typ *byte, iface any) (ret any, ok bool)\n" "func @\"\".assertI2T2(typ *byte, iface any) (ret any, ok bool)\n"
"func @\"\".ifaceeq (i1 any, i2 any) bool\n" "func @\"\".ifaceeq(i1 any, i2 any) bool\n"
"func @\"\".efaceeq (i1 any, i2 any) bool\n" "func @\"\".efaceeq(i1 any, i2 any) bool\n"
"func @\"\".ifacethash (i1 any) uint32\n" "func @\"\".ifacethash(i1 any) uint32\n"
"func @\"\".efacethash (i1 any) uint32\n" "func @\"\".efacethash(i1 any) uint32\n"
"func @\"\".makemap (mapType *byte, hint int64) map[any] any\n" "func @\"\".makemap(mapType *byte, hint int64) map[any]any\n"
"func @\"\".mapaccess1 (mapType *byte, hmap map[any] any, key any) any\n" "func @\"\".mapaccess1(mapType *byte, hmap map[any]any, key any) any\n"
"func @\"\".mapaccess2 (mapType *byte, hmap map[any] any, key any) (val any, pres bool)\n" "func @\"\".mapaccess2(mapType *byte, hmap map[any]any, key any) (val any, pres bool)\n"
"func @\"\".mapassign1 (mapType *byte, hmap map[any] any, key any, val any)\n" "func @\"\".mapassign1(mapType *byte, hmap map[any]any, key any, val any)\n"
"func @\"\".mapassign2 (mapType *byte, hmap map[any] any, key any, val any, pres bool)\n" "func @\"\".mapassign2(mapType *byte, hmap map[any]any, key any, val any, pres bool)\n"
"func @\"\".mapiterinit (mapType *byte, hmap map[any] any, hiter *any)\n" "func @\"\".mapiterinit(mapType *byte, hmap map[any]any, hiter *any)\n"
"func @\"\".mapdelete (mapType *byte, hmap map[any] any, key any)\n" "func @\"\".mapdelete(mapType *byte, hmap map[any]any, key any)\n"
"func @\"\".mapiternext (hiter *any)\n" "func @\"\".mapiternext(hiter *any)\n"
"func @\"\".mapiter1 (hiter *any) any\n" "func @\"\".mapiter1(hiter *any) any\n"
"func @\"\".mapiter2 (hiter *any) (key any, val any)\n" "func @\"\".mapiter2(hiter *any) (key any, val any)\n"
"func @\"\".makechan (chanType *byte, hint int64) chan any\n" "func @\"\".makechan(chanType *byte, hint int64) chan any\n"
"func @\"\".chanrecv1 (chanType *byte, hchan <-chan any) any\n" "func @\"\".chanrecv1(chanType *byte, hchan <-chan any) any\n"
"func @\"\".chanrecv2 (chanType *byte, hchan <-chan any) (elem any, received bool)\n" "func @\"\".chanrecv2(chanType *byte, hchan <-chan any) (elem any, received bool)\n"
"func @\"\".chansend1 (chanType *byte, hchan chan<- any, elem any)\n" "func @\"\".chansend1(chanType *byte, hchan chan<- any, elem any)\n"
"func @\"\".closechan (hchan any)\n" "func @\"\".closechan(hchan any)\n"
"func @\"\".selectnbsend (chanType *byte, hchan chan<- any, elem any) bool\n" "func @\"\".selectnbsend(chanType *byte, hchan chan<- any, elem any) bool\n"
"func @\"\".selectnbrecv (chanType *byte, elem *any, hchan <-chan any) bool\n" "func @\"\".selectnbrecv(chanType *byte, elem *any, hchan <-chan any) bool\n"
"func @\"\".selectnbrecv2 (chanType *byte, elem *any, received *bool, hchan <-chan any) bool\n" "func @\"\".selectnbrecv2(chanType *byte, elem *any, received *bool, hchan <-chan any) bool\n"
"func @\"\".newselect (size int) *byte\n" "func @\"\".newselect(size int) *byte\n"
"func @\"\".selectsend (sel *byte, hchan chan<- any, elem *any) bool\n" "func @\"\".selectsend(sel *byte, hchan chan<- any, elem *any) bool\n"
"func @\"\".selectrecv (sel *byte, hchan <-chan any, elem *any) bool\n" "func @\"\".selectrecv(sel *byte, hchan <-chan any, elem *any) bool\n"
"func @\"\".selectrecv2 (sel *byte, hchan <-chan any, elem *any, received *bool) bool\n" "func @\"\".selectrecv2(sel *byte, hchan <-chan any, elem *any, received *bool) bool\n"
"func @\"\".selectdefault (sel *byte) bool\n" "func @\"\".selectdefault(sel *byte) bool\n"
"func @\"\".selectgo (sel *byte)\n" "func @\"\".selectgo(sel *byte)\n"
"func @\"\".block ()\n" "func @\"\".block()\n"
"func @\"\".makeslice (typ *byte, nel int64, cap int64) []any\n" "func @\"\".makeslice(typ *byte, nel int64, cap int64) []any\n"
"func @\"\".growslice (typ *byte, old []any, n int64) []any\n" "func @\"\".growslice(typ *byte, old []any, n int64) []any\n"
"func @\"\".sliceslice1 (old []any, lb uint64, width uint64) []any\n" "func @\"\".sliceslice1(old []any, lb uint64, width uint64) []any\n"
"func @\"\".sliceslice (old []any, lb uint64, hb uint64, width uint64) []any\n" "func @\"\".sliceslice(old []any, lb uint64, hb uint64, width uint64) []any\n"
"func @\"\".slicearray (old *any, nel uint64, lb uint64, hb uint64, width uint64) []any\n" "func @\"\".slicearray(old *any, nel uint64, lb uint64, hb uint64, width uint64) []any\n"
"func @\"\".closure ()\n" "func @\"\".closure()\n"
"func @\"\".int64div (? int64, ? int64) int64\n" "func @\"\".int64div(? int64, ? int64) int64\n"
"func @\"\".uint64div (? uint64, ? uint64) uint64\n" "func @\"\".uint64div(? uint64, ? uint64) uint64\n"
"func @\"\".int64mod (? int64, ? int64) int64\n" "func @\"\".int64mod(? int64, ? int64) int64\n"
"func @\"\".uint64mod (? uint64, ? uint64) uint64\n" "func @\"\".uint64mod(? uint64, ? uint64) uint64\n"
"func @\"\".float64toint64 (? float64) int64\n" "func @\"\".float64toint64(? float64) int64\n"
"func @\"\".float64touint64 (? float64) uint64\n" "func @\"\".float64touint64(? float64) uint64\n"
"func @\"\".int64tofloat64 (? int64) float64\n" "func @\"\".int64tofloat64(? int64) float64\n"
"func @\"\".uint64tofloat64 (? uint64) float64\n" "func @\"\".uint64tofloat64(? uint64) float64\n"
"func @\"\".complex128div (num complex128, den complex128) complex128\n" "func @\"\".complex128div(num complex128, den complex128) complex128\n"
"\n" "\n"
"$$\n"; "$$\n";
char *unsafeimport = char *unsafeimport =
"package unsafe\n" "package unsafe\n"
"import runtime \"runtime\"\n" "import runtime \"runtime\"\n"
"type @\"\".Pointer uintptr\n" "type @\"\".Pointer uintptr\n"
"func @\"\".Offsetof (? any) uintptr\n" "func @\"\".Offsetof(? any) uintptr\n"
"func @\"\".Sizeof (? any) uintptr\n" "func @\"\".Sizeof(? any) uintptr\n"
"func @\"\".Alignof (? any) uintptr\n" "func @\"\".Alignof(? any) uintptr\n"
"func @\"\".Typeof (i interface { }) interface { }\n" "func @\"\".Typeof(i interface {}) interface {}\n"
"func @\"\".Reflect (i interface { }) (typ interface { }, addr @\"\".Pointer)\n" "func @\"\".Reflect(i interface {}) (typ interface {}, addr @\"\".Pointer)\n"
"func @\"\".Unreflect (typ interface { }, addr @\"\".Pointer) interface { }\n" "func @\"\".Unreflect(typ interface {}, addr @\"\".Pointer) interface {}\n"
"func @\"\".New (typ interface { }) @\"\".Pointer\n" "func @\"\".New(typ interface {}) @\"\".Pointer\n"
"func @\"\".NewArray (typ interface { }, n int) @\"\".Pointer\n" "func @\"\".NewArray(typ interface {}, n int) @\"\".Pointer\n"
"\n" "\n"
"$$\n"; "$$\n";

View File

@ -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

View File

@ -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);

View File

@ -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)
// } // }
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)
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

View File

@ -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

View File

@ -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,

View File

@ -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*

View File

@ -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

View File

@ -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\

345
src/pkg/runtime/alg.c Normal file
View File

@ -0,0 +1,345 @@
// 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 },
};

View File

@ -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)
// 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;

View File

@ -6,41 +6,14 @@
#include "hashmap.h" #include "hashmap.h"
#include "type.h" #include "type.h"
/* Return a pointer to the struct/union of type "type"
whose "field" field is addressed by pointer "p". */
struct Hmap { /* a hash table; initialize with hash_init() */ struct Hmap { /* a hash table; initialize with hash_init() */
uint32 count; /* elements in table - must be first */ uint32 count; /* elements in table - must be first */
uint8 datasize; /* amount of data to store in entry */ uint8 datasize; /* amount of data to store in entry */
uint8 max_power; /* max power of 2 to create sub-tables */ uint8 max_power; /* max power of 2 to create sub-tables */
uint8 max_probes; /* max entries to probe before rehashing */
uint8 indirectval; /* storing pointers to values */ uint8 indirectval; /* storing pointers to values */
uint8 valoff; /* offset of value in key+value data block */
int32 changes; /* inc'ed whenever a subtable is created/grown */ int32 changes; /* inc'ed whenever a subtable is created/grown */
hash_hash_t (*data_hash) (uint32, void *a); /* return hash of *a */
uint32 (*data_eq) (uint32, void *a, void *b); /* return whether *a == *b */
void (*data_del) (uint32, void *arg, void *data); /* invoked on deletion */
struct hash_subtable *st; /* first-level table */ struct hash_subtable *st; /* first-level table */
uint32 keysize;
uint32 valsize;
uint32 datavo;
// three sets of offsets: the digit counts how many
// of key, value are passed as inputs:
// 0 = func() (key, value)
// 1 = func(key) (value)
// 2 = func(key, value)
uint32 ko0;
uint32 vo0;
uint32 ko1;
uint32 vo1;
uint32 po1;
uint32 ko2;
uint32 vo2;
uint32 po2;
Alg* keyalg;
Alg* valalg;
}; };
struct hash_entry { struct hash_entry {
@ -58,7 +31,7 @@ struct hash_subtable {
struct hash_entry entry[1]; /* 2**power+max_probes-1 elements of elemsize bytes */ struct hash_entry entry[1]; /* 2**power+max_probes-1 elements of elemsize bytes */
}; };
#define HASH_DATA_EQ(h,x,y) ((*h->data_eq) (h->keysize, (x), (y))) #define HASH_DATA_EQ(eq, t, h,x,y) ((eq)=0, (*t->key->alg->equal) (&(eq), t->key->size, (x), (y)), (eq))
#define HASH_REHASH 0x2 /* an internal flag */ #define HASH_REHASH 0x2 /* an internal flag */
/* the number of bits used is stored in the flags word too */ /* the number of bits used is stored in the flags word too */
@ -79,6 +52,7 @@ struct hash_subtable {
#define HASH_OFFSET(base, byte_offset) \ #define HASH_OFFSET(base, byte_offset) \
((struct hash_entry *) (((byte *) (base)) + (byte_offset))) ((struct hash_entry *) (((byte *) (base)) + (byte_offset)))
#define HASH_MAX_PROBES 15 /* max entries to probe before rehashing */
/* return a hash layer with 2**power empty entries */ /* return a hash layer with 2**power empty entries */
static struct hash_subtable * static struct hash_subtable *
@ -87,8 +61,8 @@ hash_subtable_new (Hmap *h, int32 power, int32 used)
int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]); int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
int32 bytes = elemsize << power; int32 bytes = elemsize << power;
struct hash_subtable *st; struct hash_subtable *st;
int32 limit_bytes = h->max_probes * elemsize; int32 limit_bytes = HASH_MAX_PROBES * elemsize;
int32 max_probes = h->max_probes; int32 max_probes = HASH_MAX_PROBES;
if (bytes < limit_bytes) { if (bytes < limit_bytes) {
limit_bytes = bytes; limit_bytes = bytes;
@ -127,12 +101,7 @@ init_sizes (int64 hint, int32 *init_power, int32 *max_power)
} }
static void static void
hash_init (Hmap *h, hash_init (Hmap *h, int32 datasize, int64 hint)
int32 datasize,
hash_hash_t (*data_hash) (uint32, void *),
uint32 (*data_eq) (uint32, void *, void *),
void (*data_del) (uint32, void *, void *),
int64 hint)
{ {
int32 init_power; int32 init_power;
int32 max_power; int32 max_power;
@ -143,15 +112,11 @@ hash_init (Hmap *h,
init_sizes (hint, &init_power, &max_power); init_sizes (hint, &init_power, &max_power);
h->datasize = datasize; h->datasize = datasize;
h->max_power = max_power; h->max_power = max_power;
h->max_probes = 15;
assert (h->datasize == datasize); assert (h->datasize == datasize);
assert (h->max_power == max_power); assert (h->max_power == max_power);
assert (sizeof (void *) <= h->datasize || h->max_power == 255); assert (sizeof (void *) <= h->datasize || h->max_power == 255);
h->count = 0; h->count = 0;
h->changes = 0; h->changes = 0;
h->data_hash = data_hash;
h->data_eq = data_eq;
h->data_del = data_del;
h->st = hash_subtable_new (h, init_power, 0); h->st = hash_subtable_new (h, init_power, 0);
} }
@ -199,11 +164,11 @@ hash_remove_n (struct hash_subtable *st, struct hash_entry *dst_e, int32 n)
} }
static int32 static int32
hash_insert_internal (struct hash_subtable **pst, int32 flags, hash_hash_t hash, hash_insert_internal (MapType*, struct hash_subtable **pst, int32 flags, hash_hash_t hash,
Hmap *h, void *data, void **pres); Hmap *h, void *data, void **pres);
static void static void
hash_conv (Hmap *h, hash_conv (MapType *t, Hmap *h,
struct hash_subtable *st, int32 flags, struct hash_subtable *st, int32 flags,
hash_hash_t hash, hash_hash_t hash,
struct hash_entry *e) struct hash_entry *e)
@ -238,13 +203,13 @@ hash_conv (Hmap *h,
(ne <= st->last && (e_hash = ne->hash) != HASH_NIL && (ne <= st->last && (e_hash = ne->hash) != HASH_NIL &&
(e_hash & prefix_mask) == current)) { (e_hash & prefix_mask) == current)) {
struct hash_subtable *new_st = hash_subtable_new (h, 1, HASH_USED (new_flags)); struct hash_subtable *new_st = hash_subtable_new (h, 1, HASH_USED (new_flags));
int32 rc = hash_insert_internal (&new_st, new_flags, e->hash, h, e->data, &dummy_result); int32 rc = hash_insert_internal (t, &new_st, new_flags, e->hash, h, e->data, &dummy_result);
assert (rc == 0); assert (rc == 0);
memcpy(dummy_result, e->data, h->datasize); memcpy(dummy_result, e->data, h->datasize);
e = ne; e = ne;
while (e <= st->last && (e_hash = e->hash) != HASH_NIL && (e_hash & prefix_mask) == current) { while (e <= st->last && (e_hash = e->hash) != HASH_NIL && (e_hash & prefix_mask) == current) {
assert ((e_hash & HASH_MASK) != HASH_SUBHASH); assert ((e_hash & HASH_MASK) != HASH_SUBHASH);
rc = hash_insert_internal (&new_st, new_flags, e_hash, h, e->data, &dummy_result); rc = hash_insert_internal (t, &new_st, new_flags, e_hash, h, e->data, &dummy_result);
assert (rc == 0); assert (rc == 0);
memcpy(dummy_result, e->data, h->datasize); memcpy(dummy_result, e->data, h->datasize);
e = HASH_OFFSET (e, elemsize); e = HASH_OFFSET (e, elemsize);
@ -266,7 +231,7 @@ hash_conv (Hmap *h,
} }
static void static void
hash_grow (Hmap *h, struct hash_subtable **pst, int32 flags) hash_grow (MapType *t, Hmap *h, struct hash_subtable **pst, int32 flags)
{ {
struct hash_subtable *old_st = *pst; struct hash_subtable *old_st = *pst;
int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]); int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
@ -280,7 +245,7 @@ hash_grow (Hmap *h, struct hash_subtable **pst, int32 flags)
for (e = old_st->entry; e <= last_e; e = HASH_OFFSET (e, elemsize)) { for (e = old_st->entry; e <= last_e; e = HASH_OFFSET (e, elemsize)) {
hash_hash_t hash = e->hash; hash_hash_t hash = e->hash;
if (hash != HASH_NIL) { if (hash != HASH_NIL) {
int32 rc = hash_insert_internal (pst, flags, e->hash, h, e->data, &dummy_result); int32 rc = hash_insert_internal (t, pst, flags, e->hash, h, e->data, &dummy_result);
assert (rc == 0); assert (rc == 0);
memcpy(dummy_result, e->data, h->datasize); memcpy(dummy_result, e->data, h->datasize);
used++; used++;
@ -290,16 +255,20 @@ hash_grow (Hmap *h, struct hash_subtable **pst, int32 flags)
} }
static int32 static int32
hash_lookup (Hmap *h, void *data, void **pres) hash_lookup (MapType *t, Hmap *h, void *data, void **pres)
{ {
int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]); int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
hash_hash_t hash = (*h->data_hash) (h->keysize, data) & ~HASH_MASK; hash_hash_t hash;
struct hash_subtable *st = h->st; struct hash_subtable *st = h->st;
int32 used = 0; int32 used = 0;
hash_hash_t e_hash; hash_hash_t e_hash;
struct hash_entry *e; struct hash_entry *e;
struct hash_entry *end_e; struct hash_entry *end_e;
bool eq;
hash = 0;
(*t->key->alg->hash) (&hash, t->key->size, data);
hash &= ~HASH_MASK;
hash += HASH_ADJUST (hash); hash += HASH_ADJUST (hash);
for (;;) { for (;;) {
int32 shift = HASH_BITS - (st->power + used); int32 shift = HASH_BITS - (st->power + used);
@ -319,7 +288,7 @@ hash_lookup (Hmap *h, void *data, void **pres)
e = HASH_OFFSET (e, elemsize); e = HASH_OFFSET (e, elemsize);
} }
while (e != end_e && ((e_hash = e->hash) ^ hash) < HASH_SUBHASH) { while (e != end_e && ((e_hash = e->hash) ^ hash) < HASH_SUBHASH) {
if (HASH_DATA_EQ (h, data, e->data)) { /* a match */ if (HASH_DATA_EQ (eq, t, h, data, e->data)) { /* a match */
*pres = e->data; *pres = e->data;
return (1); return (1);
} }
@ -331,16 +300,20 @@ hash_lookup (Hmap *h, void *data, void **pres)
} }
static int32 static int32
hash_remove (Hmap *h, void *data, void *arg) hash_remove (MapType *t, Hmap *h, void *data)
{ {
int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]); int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
hash_hash_t hash = (*h->data_hash) (h->keysize, data) & ~HASH_MASK; hash_hash_t hash;
struct hash_subtable *st = h->st; struct hash_subtable *st = h->st;
int32 used = 0; int32 used = 0;
hash_hash_t e_hash; hash_hash_t e_hash;
struct hash_entry *e; struct hash_entry *e;
struct hash_entry *end_e; struct hash_entry *end_e;
bool eq;
hash = 0;
(*t->key->alg->hash) (&hash, t->key->size, data);
hash &= ~HASH_MASK;
hash += HASH_ADJUST (hash); hash += HASH_ADJUST (hash);
for (;;) { for (;;) {
int32 shift = HASH_BITS - (st->power + used); int32 shift = HASH_BITS - (st->power + used);
@ -360,8 +333,9 @@ hash_remove (Hmap *h, void *data, void *arg)
e = HASH_OFFSET (e, elemsize); e = HASH_OFFSET (e, elemsize);
} }
while (e != end_e && ((e_hash = e->hash) ^ hash) < HASH_SUBHASH) { while (e != end_e && ((e_hash = e->hash) ^ hash) < HASH_SUBHASH) {
if (HASH_DATA_EQ (h, data, e->data)) { /* a match */ if (HASH_DATA_EQ (eq, t, h, data, e->data)) { /* a match */
(*h->data_del) (h->datavo, arg, e->data); if (h->indirectval)
free (*(void**)((byte*)e->data + h->valoff));
hash_remove_n (st, e, 1); hash_remove_n (st, e, 1);
h->count--; h->count--;
return (1); return (1);
@ -373,10 +347,11 @@ hash_remove (Hmap *h, void *data, void *arg)
} }
static int32 static int32
hash_insert_internal (struct hash_subtable **pst, int32 flags, hash_hash_t hash, hash_insert_internal (MapType *t, struct hash_subtable **pst, int32 flags, hash_hash_t hash,
Hmap *h, void *data, void **pres) Hmap *h, void *data, void **pres)
{ {
int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]); int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
bool eq;
if ((flags & HASH_REHASH) == 0) { if ((flags & HASH_REHASH) == 0) {
hash += HASH_ADJUST (hash); hash += HASH_ADJUST (hash);
@ -409,7 +384,7 @@ hash_insert_internal (struct hash_subtable **pst, int32 flags, hash_hash_t hash,
int32 ins_i = i; int32 ins_i = i;
hash_hash_t ins_e_hash; hash_hash_t ins_e_hash;
while (ins_e != end_e && ((e_hash = ins_e->hash) ^ hash) < HASH_SUBHASH) { while (ins_e != end_e && ((e_hash = ins_e->hash) ^ hash) < HASH_SUBHASH) {
if (HASH_DATA_EQ (h, data, ins_e->data)) { /* a match */ if (HASH_DATA_EQ (eq, t, h, data, ins_e->data)) { /* a match */
*pres = ins_e->data; *pres = ins_e->data;
return (1); return (1);
} }
@ -447,17 +422,22 @@ hash_insert_internal (struct hash_subtable **pst, int32 flags, hash_hash_t hash,
} }
h->changes++; h->changes++;
if (st->power < h->max_power) { if (st->power < h->max_power) {
hash_grow (h, pst, flags); hash_grow (t, h, pst, flags);
} else { } else {
hash_conv (h, st, flags, hash, start_e); hash_conv (t, h, st, flags, hash, start_e);
} }
} }
} }
static int32 static int32
hash_insert (Hmap *h, void *data, void **pres) hash_insert (MapType *t, Hmap *h, void *data, void **pres)
{ {
int32 rc = hash_insert_internal (&h->st, 0, (*h->data_hash) (h->keysize, data), h, data, pres); uintptr hash;
int32 rc;
hash = 0;
(*t->key->alg->hash) (&hash, t->key->size, data);
rc = hash_insert_internal (t, &h->st, 0, hash, h, data, pres);
h->count += (rc == 0); /* increment count if element didn't previously exist */ h->count += (rc == 0); /* increment count if element didn't previously exist */
return (rc); return (rc);
@ -528,7 +508,7 @@ Again:
last = sub->last; last = sub->last;
if (e != sub->start && it->last_hash != HASH_OFFSET (e, -elemsize)->hash) { if (e != sub->start && it->last_hash != HASH_OFFSET (e, -elemsize)->hash) {
struct hash_entry *start = HASH_OFFSET (e, -(elemsize * it->h->max_probes)); struct hash_entry *start = HASH_OFFSET (e, -(elemsize * HASH_MAX_PROBES));
struct hash_entry *pe = HASH_OFFSET (e, -elemsize); struct hash_entry *pe = HASH_OFFSET (e, -elemsize);
hash_hash_t last_hash = it->last_hash; hash_hash_t last_hash = it->last_hash;
if (start < sub->start) { if (start < sub->start) {
@ -599,12 +579,13 @@ Again:
} }
static void static void
hash_iter_init (Hmap *h, struct hash_iter *it) hash_iter_init (MapType *t, Hmap *h, struct hash_iter *it)
{ {
it->elemsize = h->datasize + offsetof (struct hash_entry, data[0]); it->elemsize = h->datasize + offsetof (struct hash_entry, data[0]);
it->changes = h->changes; it->changes = h->changes;
it->i = 0; it->i = 0;
it->h = h; it->h = h;
it->t = t;
it->last_hash = 0; it->last_hash = 0;
it->subtable_state[0].e = h->st->entry; it->subtable_state[0].e = h->st->entry;
it->subtable_state[0].start = h->st->entry; it->subtable_state[0].start = h->st->entry;
@ -701,24 +682,6 @@ enum {
MaxValsize = 256 - 64 MaxValsize = 256 - 64
}; };
static void
donothing(uint32 s, void *a, void *b)
{
USED(s);
USED(a);
USED(b);
}
static void
freedata(uint32 datavo, void *a, void *b)
{
void *p;
USED(a);
p = *(void**)((byte*)b + datavo);
free(p);
}
static void** static void**
hash_indirect(Hmap *h, void *p) hash_indirect(Hmap *h, void *p)
{ {
@ -734,8 +697,7 @@ Hmap*
runtime·makemap_c(MapType *typ, int64 hint) runtime·makemap_c(MapType *typ, int64 hint)
{ {
Hmap *h; Hmap *h;
int32 keyalg, valalg, keysize, valsize, valsize_in_hash; int32 valsize_in_hash;
void (*data_del)(uint32, void*, void*);
Type *key, *val; Type *key, *val;
key = typ->key; key = typ->key;
@ -744,68 +706,30 @@ runtime·makemap_c(MapType *typ, int64 hint)
if(hint < 0 || (int32)hint != hint) if(hint < 0 || (int32)hint != hint)
runtime·panicstring("makemap: size out of range"); runtime·panicstring("makemap: size out of range");
keyalg = key->alg; if(key->alg->hash == runtime·nohash)
valalg = val->alg;
keysize = key->size;
valsize = val->size;
if(keyalg >= nelem(runtime·algarray) || runtime·algarray[keyalg].hash == runtime·nohash) {
runtime·printf("map(keyalg=%d)\n", keyalg);
runtime·throw("runtime.makemap: unsupported map key type"); runtime·throw("runtime.makemap: unsupported map key type");
}
if(valalg >= nelem(runtime·algarray)) {
runtime·printf("map(valalg=%d)\n", valalg);
runtime·throw("runtime.makemap: unsupported map value type");
}
h = runtime·mal(sizeof(*h)); h = runtime·mal(sizeof(*h));
valsize_in_hash = valsize; valsize_in_hash = val->size;
data_del = donothing; if (val->size > MaxValsize) {
if (valsize > MaxValsize) {
h->indirectval = 1; h->indirectval = 1;
data_del = freedata;
valsize_in_hash = sizeof(void*); valsize_in_hash = sizeof(void*);
} }
// align value inside data so that mark-sweep gc can find it. // Align value inside data so that mark-sweep gc can find it.
// might remove in the future and just assume datavo == keysize. h->valoff = key->size;
h->datavo = keysize;
if(valsize_in_hash >= sizeof(void*)) if(valsize_in_hash >= sizeof(void*))
h->datavo = runtime·rnd(keysize, sizeof(void*)); h->valoff = runtime·rnd(key->size, sizeof(void*));
hash_init(h, h->datavo+valsize_in_hash, hash_init(h, h->valoff+valsize_in_hash, hint);
runtime·algarray[keyalg].hash,
runtime·algarray[keyalg].equal,
data_del,
hint);
h->keysize = keysize;
h->valsize = valsize;
h->keyalg = &runtime·algarray[keyalg];
h->valalg = &runtime·algarray[valalg];
// these calculations are compiler dependent. // these calculations are compiler dependent.
// figure out offsets of map call arguments. // figure out offsets of map call arguments.
// func() (key, val)
h->ko0 = runtime·rnd(sizeof(h), Structrnd);
h->vo0 = runtime·rnd(h->ko0+keysize, val->align);
// func(key) (val[, pres])
h->ko1 = runtime·rnd(sizeof(h), key->align);
h->vo1 = runtime·rnd(h->ko1+keysize, Structrnd);
h->po1 = h->vo1 + valsize;
// func(key, val[, pres])
h->ko2 = runtime·rnd(sizeof(h), key->align);
h->vo2 = runtime·rnd(h->ko2+keysize, val->align);
h->po2 = h->vo2 + valsize;
if(debug) { if(debug) {
runtime·printf("makemap: map=%p; keysize=%d; valsize=%d; keyalg=%d; valalg=%d; offsets=%d,%d; %d,%d,%d; %d,%d,%d\n", runtime·printf("makemap: map=%p; keysize=%p; valsize=%p; keyalg=%p; valalg=%p\n",
h, keysize, valsize, keyalg, valalg, h->ko0, h->vo0, h->ko1, h->vo1, h->po1, h->ko2, h->vo2, h->po2); h, key->size, val->size, key->alg, val->alg);
} }
return h; return h;
@ -834,9 +758,9 @@ runtime·mapaccess(MapType *t, Hmap *h, byte *ak, byte *av, bool *pres)
byte *res; byte *res;
Type *elem; Type *elem;
if(h == nil) {
elem = t->elem; elem = t->elem;
runtime·algarray[elem->alg].copy(elem->size, av, nil); if(h == nil) {
elem->alg->copy(elem->size, av, nil);
*pres = false; *pres = false;
return; return;
} }
@ -845,12 +769,12 @@ runtime·mapaccess(MapType *t, Hmap *h, byte *ak, byte *av, bool *pres)
runtime·gosched(); runtime·gosched();
res = nil; res = nil;
if(hash_lookup(h, ak, (void**)&res)) { if(hash_lookup(t, h, ak, (void**)&res)) {
*pres = true; *pres = true;
h->valalg->copy(h->valsize, av, hash_indirect(h, res+h->datavo)); elem->alg->copy(elem->size, av, hash_indirect(h, res+h->valoff));
} else { } else {
*pres = false; *pres = false;
h->valalg->copy(h->valsize, av, nil); elem->alg->copy(elem->size, av, nil);
} }
} }
@ -862,13 +786,8 @@ runtime·mapaccess1(MapType *t, Hmap *h, ...)
byte *ak, *av; byte *ak, *av;
bool pres; bool pres;
if(h == nil) {
ak = (byte*)(&h + 1); ak = (byte*)(&h + 1);
av = ak + runtime·rnd(t->key->size, Structrnd); av = ak + runtime·rnd(t->key->size, Structrnd);
} else {
ak = (byte*)&h + h->ko1;
av = (byte*)&h + h->vo1;
}
runtime·mapaccess(t, h, ak, av, &pres); runtime·mapaccess(t, h, ak, av, &pres);
@ -876,9 +795,9 @@ runtime·mapaccess1(MapType *t, Hmap *h, ...)
runtime·prints("runtime.mapaccess1: map="); runtime·prints("runtime.mapaccess1: map=");
runtime·printpointer(h); runtime·printpointer(h);
runtime·prints("; key="); runtime·prints("; key=");
h->keyalg->print(h->keysize, ak); t->key->alg->print(t->key->size, ak);
runtime·prints("; val="); runtime·prints("; val=");
h->valalg->print(h->valsize, av); t->elem->alg->print(t->elem->size, av);
runtime·prints("; pres="); runtime·prints("; pres=");
runtime·printbool(pres); runtime·printbool(pres);
runtime·prints("\n"); runtime·prints("\n");
@ -892,15 +811,9 @@ runtime·mapaccess2(MapType *t, Hmap *h, ...)
{ {
byte *ak, *av, *ap; byte *ak, *av, *ap;
if(h == nil) {
ak = (byte*)(&h + 1); ak = (byte*)(&h + 1);
av = ak + runtime·rnd(t->key->size, Structrnd); av = ak + runtime·rnd(t->key->size, Structrnd);
ap = av + t->elem->size; ap = av + t->elem->size;
} else {
ak = (byte*)&h + h->ko1;
av = (byte*)&h + h->vo1;
ap = (byte*)&h + h->po1;
}
runtime·mapaccess(t, h, ak, av, ap); runtime·mapaccess(t, h, ak, av, ap);
@ -908,9 +821,9 @@ runtime·mapaccess2(MapType *t, Hmap *h, ...)
runtime·prints("runtime.mapaccess2: map="); runtime·prints("runtime.mapaccess2: map=");
runtime·printpointer(h); runtime·printpointer(h);
runtime·prints("; key="); runtime·prints("; key=");
h->keyalg->print(h->keysize, ak); t->key->alg->print(t->key->size, ak);
runtime·prints("; val="); runtime·prints("; val=");
h->valalg->print(h->valsize, av); t->elem->alg->print(t->key->size, av);
runtime·prints("; pres="); runtime·prints("; pres=");
runtime·printbool(*ap); runtime·printbool(*ap);
runtime·prints("\n"); runtime·prints("\n");
@ -949,33 +862,31 @@ runtime·mapassign(MapType *t, Hmap *h, byte *ak, byte *av)
byte *res; byte *res;
int32 hit; int32 hit;
USED(t);
if(h == nil) if(h == nil)
runtime·panicstring("assignment to entry in nil map"); runtime·panicstring("assignment to entry in nil map");
if(runtime·gcwaiting) if(runtime·gcwaiting)
runtime·gosched(); runtime·gosched();
res = nil;
if(av == nil) { if(av == nil) {
hash_remove(h, ak, (void**)&res); hash_remove(t, h, ak);
return; return;
} }
hit = hash_insert(h, ak, (void**)&res); res = nil;
hit = hash_insert(t, h, ak, (void**)&res);
if(!hit && h->indirectval) if(!hit && h->indirectval)
*(void**)(res+h->datavo) = runtime·mal(h->valsize); *(void**)(res+h->valoff) = runtime·mal(t->elem->size);
h->keyalg->copy(h->keysize, res, ak); t->key->alg->copy(t->key->size, res, ak);
h->valalg->copy(h->valsize, hash_indirect(h, res+h->datavo), av); t->elem->alg->copy(t->elem->size, hash_indirect(h, res+h->valoff), av);
if(debug) { if(debug) {
runtime·prints("mapassign: map="); runtime·prints("mapassign: map=");
runtime·printpointer(h); runtime·printpointer(h);
runtime·prints("; key="); runtime·prints("; key=");
h->keyalg->print(h->keysize, ak); t->key->alg->print(t->key->size, ak);
runtime·prints("; val="); runtime·prints("; val=");
h->valalg->print(h->valsize, av); t->elem->alg->print(t->elem->size, av);
runtime·prints("; hit="); runtime·prints("; hit=");
runtime·printint(hit); runtime·printint(hit);
runtime·prints("; res="); runtime·prints("; res=");
@ -994,8 +905,8 @@ runtime·mapassign1(MapType *t, Hmap *h, ...)
if(h == nil) if(h == nil)
runtime·panicstring("assignment to entry in nil map"); runtime·panicstring("assignment to entry in nil map");
ak = (byte*)&h + h->ko2; ak = (byte*)(&h + 1);
av = (byte*)&h + h->vo2; av = ak + runtime·rnd(t->key->size, t->elem->align);
runtime·mapassign(t, h, ak, av); runtime·mapassign(t, h, ak, av);
} }
@ -1010,14 +921,14 @@ runtime·mapdelete(MapType *t, Hmap *h, ...)
if(h == nil) if(h == nil)
runtime·panicstring("deletion of entry in nil map"); runtime·panicstring("deletion of entry in nil map");
ak = (byte*)&h + h->ko2; ak = (byte*)(&h + 1);
runtime·mapassign(t, h, ak, nil); runtime·mapassign(t, h, ak, nil);
if(debug) { if(debug) {
runtime·prints("mapdelete: map="); runtime·prints("mapdelete: map=");
runtime·printpointer(h); runtime·printpointer(h);
runtime·prints("; key="); runtime·prints("; key=");
h->keyalg->print(h->keysize, ak); t->key->alg->print(t->key->size, ak);
runtime·prints("\n"); runtime·prints("\n");
} }
} }
@ -1033,11 +944,11 @@ reflect·mapassign(MapType *t, Hmap *h, uintptr key, uintptr val, bool pres)
if(h == nil) if(h == nil)
runtime·panicstring("assignment to entry in nil map"); runtime·panicstring("assignment to entry in nil map");
if(h->keysize <= sizeof(key)) if(t->key->size <= sizeof(key))
ak = (byte*)&key; ak = (byte*)&key;
else else
ak = (byte*)key; ak = (byte*)key;
if(h->valsize <= sizeof(val)) if(t->elem->size <= sizeof(val))
av = (byte*)&val; av = (byte*)&val;
else else
av = (byte*)val; av = (byte*)val;
@ -1048,13 +959,13 @@ reflect·mapassign(MapType *t, Hmap *h, uintptr key, uintptr val, bool pres)
// mapiterinit(mapType *type, hmap *map[any]any, hiter *any); // mapiterinit(mapType *type, hmap *map[any]any, hiter *any);
void void
runtime·mapiterinit(MapType*, Hmap *h, struct hash_iter *it) runtime·mapiterinit(MapType *t, Hmap *h, struct hash_iter *it)
{ {
if(h == nil) { if(h == nil) {
it->data = nil; it->data = nil;
return; return;
} }
hash_iter_init(h, it); hash_iter_init(t, h, it);
it->data = hash_next(it); it->data = hash_next(it);
if(debug) { if(debug) {
runtime·prints("runtime.mapiterinit: map="); runtime·prints("runtime.mapiterinit: map=");
@ -1109,15 +1020,17 @@ runtime·mapiter1(struct hash_iter *it, ...)
{ {
Hmap *h; Hmap *h;
byte *ak, *res; byte *ak, *res;
Type *key;
h = it->h; h = it->h;
ak = (byte*)&it + h->ko0; ak = (byte*)(&it + 1);
res = it->data; res = it->data;
if(res == nil) if(res == nil)
runtime·throw("runtime.mapiter1: key:val nil pointer"); runtime·throw("runtime.mapiter1: key:val nil pointer");
h->keyalg->copy(h->keysize, ak, res); key = it->t->key;
key->alg->copy(key->size, ak, res);
if(debug) { if(debug) {
runtime·prints("mapiter2: iter="); runtime·prints("mapiter2: iter=");
@ -1131,14 +1044,14 @@ runtime·mapiter1(struct hash_iter *it, ...)
bool bool
runtime·mapiterkey(struct hash_iter *it, void *ak) runtime·mapiterkey(struct hash_iter *it, void *ak)
{ {
Hmap *h;
byte *res; byte *res;
Type *key;
h = it->h;
res = it->data; res = it->data;
if(res == nil) if(res == nil)
return false; return false;
h->keyalg->copy(h->keysize, ak, res); key = it->t->key;
key->alg->copy(key->size, ak, res);
return true; return true;
} }
@ -1149,20 +1062,20 @@ runtime·mapiterkey(struct hash_iter *it, void *ak)
void void
reflect·mapiterkey(struct hash_iter *it, uintptr key, bool ok) reflect·mapiterkey(struct hash_iter *it, uintptr key, bool ok)
{ {
Hmap *h;
byte *res; byte *res;
Type *tkey;
key = 0; key = 0;
ok = false; ok = false;
h = it->h;
res = it->data; res = it->data;
if(res == nil) { if(res == nil) {
key = 0; key = 0;
ok = false; ok = false;
} else { } else {
tkey = it->t->key;
key = 0; key = 0;
if(h->keysize <= sizeof(key)) if(tkey->size <= sizeof(key))
h->keyalg->copy(h->keysize, (byte*)&key, res); tkey->alg->copy(tkey->size, (byte*)&key, res);
else else
key = (uintptr)res; key = (uintptr)res;
ok = true; ok = true;
@ -1191,17 +1104,19 @@ runtime·mapiter2(struct hash_iter *it, ...)
{ {
Hmap *h; Hmap *h;
byte *ak, *av, *res; byte *ak, *av, *res;
MapType *t;
h = it->h; t = it->t;
ak = (byte*)&it + h->ko0; ak = (byte*)(&it + 1);
av = (byte*)&it + h->vo0; av = ak + runtime·rnd(t->key->size, t->elem->align);
res = it->data; res = it->data;
if(res == nil) if(res == nil)
runtime·throw("runtime.mapiter2: key:val nil pointer"); runtime·throw("runtime.mapiter2: key:val nil pointer");
h->keyalg->copy(h->keysize, ak, res); h = it->h;
h->valalg->copy(h->valsize, av, hash_indirect(h, res+h->datavo)); t->key->alg->copy(t->key->size, ak, res);
t->elem->alg->copy(t->elem->size, av, hash_indirect(h, res+h->valoff));
if(debug) { if(debug) {
runtime·prints("mapiter2: iter="); runtime·prints("mapiter2: iter=");

View File

@ -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 */

View File

@ -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)
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)
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)
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)
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)
// 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)
// 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?

View File

@ -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)
{ {

View File

@ -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
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
/* /*
* known to compiler * known to compiler
*/ */
enum {
Structrnd = sizeof(uintptr)
};
/*
* type algorithms - known to compiler
*/
enum enum
{ {
AMEM, AMEM,
@ -376,12 +375,46 @@ enum
ANOEQ128, ANOEQ128,
Amax Amax
}; };
typedef struct Alg Alg;
struct Alg
enum { {
Structrnd = sizeof(uintptr) 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];
void runtime·memhash(uintptr*, uintptr, void*);
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
/* /*
* 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);
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);

View File

@ -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
} }
} }
// 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;

View File

@ -29,10 +29,11 @@ type Type interface{}
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
alg *uintptr // algorithm table (../runtime/runtime.h:/Alg)
string *string // string form; unnecessary but undeniably useful string *string // string form; unnecessary but undeniably useful
*uncommonType // (relatively) uncommon fields *uncommonType // (relatively) uncommon fields
ptrToThis *Type // pointer to this type, if used in binary or has methods ptrToThis *Type // pointer to this type, if used in binary or has methods

View File

@ -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;