From b9ccd077dc478fca2e8bd00633c1a60a54f342d8 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 5 Dec 2011 09:40:22 -0500 Subject: [PATCH] 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 --- src/cmd/gc/builtin.c.boot | 210 +++++++++++------------ src/cmd/gc/go.h | 29 ---- src/cmd/gc/range.c | 4 +- src/cmd/gc/reflect.c | 10 +- src/cmd/gc/runtime.go | 2 +- src/cmd/gc/walk.c | 2 +- src/cmd/ld/dwarf.c | 2 +- src/pkg/reflect/type.go | 3 +- src/pkg/runtime/Makefile | 1 + src/pkg/runtime/alg.c | 345 ++++++++++++++++++++++++++++++++++++++ src/pkg/runtime/chan.c | 9 +- src/pkg/runtime/hashmap.c | 291 ++++++++++++-------------------- src/pkg/runtime/hashmap.h | 1 + src/pkg/runtime/iface.c | 63 ++++--- src/pkg/runtime/runtime.c | 332 ------------------------------------ src/pkg/runtime/runtime.h | 60 +++++-- src/pkg/runtime/slice.c | 6 +- src/pkg/runtime/type.go | 19 ++- src/pkg/runtime/type.h | 3 +- 19 files changed, 670 insertions(+), 722 deletions(-) create mode 100644 src/pkg/runtime/alg.c diff --git a/src/cmd/gc/builtin.c.boot b/src/cmd/gc/builtin.c.boot index f6508b55a3..ea73c0ea31 100644 --- a/src/cmd/gc/builtin.c.boot +++ b/src/cmd/gc/builtin.c.boot @@ -1,116 +1,116 @@ char *runtimeimport = "package runtime\n" "import runtime \"runtime\"\n" - "func @\"\".new (typ *byte) *any\n" - "func @\"\".panicindex ()\n" - "func @\"\".panicslice ()\n" - "func @\"\".throwreturn ()\n" - "func @\"\".throwinit ()\n" - "func @\"\".panicwrap (? string, ? string, ? string)\n" - "func @\"\".panic (? interface { })\n" - "func @\"\".recover (? *int32) interface { }\n" - "func @\"\".printbool (? bool)\n" - "func @\"\".printfloat (? float64)\n" - "func @\"\".printint (? int64)\n" - "func @\"\".printuint (? uint64)\n" - "func @\"\".printcomplex (? complex128)\n" - "func @\"\".printstring (? string)\n" - "func @\"\".printpointer (? any)\n" - "func @\"\".printiface (? any)\n" - "func @\"\".printeface (? any)\n" - "func @\"\".printslice (? any)\n" - "func @\"\".printnl ()\n" - "func @\"\".printsp ()\n" - "func @\"\".goprintf ()\n" - "func @\"\".concatstring ()\n" - "func @\"\".append ()\n" - "func @\"\".appendslice (typ *byte, x any, y []any) any\n" - "func @\"\".appendstr (typ *byte, x []byte, y string) []byte\n" - "func @\"\".cmpstring (? string, ? string) int\n" - "func @\"\".slicestring (? string, ? int, ? int) string\n" - "func @\"\".slicestring1 (? string, ? int) string\n" - "func @\"\".intstring (? int64) string\n" - "func @\"\".slicebytetostring (? []byte) string\n" - "func @\"\".slicerunetostring (? []rune) string\n" - "func @\"\".stringtoslicebyte (? string) []byte\n" - "func @\"\".stringtoslicerune (? string) []rune\n" - "func @\"\".stringiter (? string, ? int) int\n" - "func @\"\".stringiter2 (? string, ? int) (retk int, retv rune)\n" - "func @\"\".slicecopy (to any, fr any, wid uint32) int\n" - "func @\"\".slicestringcopy (to any, fr any) int\n" - "func @\"\".convI2E (elem any) any\n" - "func @\"\".convI2I (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 @\"\".assertE2E (typ *byte, iface any) any\n" - "func @\"\".assertE2E2 (typ *byte, iface any) (ret any, ok bool)\n" - "func @\"\".assertE2I (typ *byte, iface any) any\n" - "func @\"\".assertE2I2 (typ *byte, iface any) (ret any, ok bool)\n" - "func @\"\".assertE2T (typ *byte, iface any) any\n" - "func @\"\".assertE2T2 (typ *byte, iface any) (ret any, ok bool)\n" - "func @\"\".assertI2E (typ *byte, iface any) any\n" - "func @\"\".assertI2E2 (typ *byte, iface any) (ret any, ok bool)\n" - "func @\"\".assertI2I (typ *byte, iface any) any\n" - "func @\"\".assertI2I2 (typ *byte, iface any) (ret any, ok bool)\n" - "func @\"\".assertI2T (typ *byte, iface any) any\n" - "func @\"\".assertI2T2 (typ *byte, iface any) (ret any, ok bool)\n" - "func @\"\".ifaceeq (i1 any, i2 any) bool\n" - "func @\"\".efaceeq (i1 any, i2 any) bool\n" - "func @\"\".ifacethash (i1 any) uint32\n" - "func @\"\".efacethash (i1 any) uint32\n" - "func @\"\".makemap (mapType *byte, hint int64) map[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 @\"\".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 @\"\".mapiterinit (mapType *byte, hmap map[any] any, hiter *any)\n" - "func @\"\".mapdelete (mapType *byte, hmap map[any] any, key any)\n" - "func @\"\".mapiternext (hiter *any)\n" - "func @\"\".mapiter1 (hiter *any) any\n" - "func @\"\".mapiter2 (hiter *any) (key any, val any)\n" - "func @\"\".makechan (chanType *byte, hint int64) chan any\n" - "func @\"\".chanrecv1 (chanType *byte, hchan <-chan any) any\n" - "func @\"\".chanrecv2 (chanType *byte, hchan <-chan any) (elem any, received bool)\n" - "func @\"\".chansend1 (chanType *byte, hchan chan<- any, elem any)\n" - "func @\"\".closechan (hchan any)\n" - "func @\"\".selectnbsend (chanType *byte, hchan chan<- any, elem 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 @\"\".newselect (size int) *byte\n" - "func @\"\".selectsend (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 @\"\".selectdefault (sel *byte) bool\n" - "func @\"\".selectgo (sel *byte)\n" - "func @\"\".block ()\n" - "func @\"\".makeslice (typ *byte, nel int64, cap int64) []any\n" - "func @\"\".growslice (typ *byte, old []any, n int64) []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 @\"\".slicearray (old *any, nel uint64, lb uint64, hb uint64, width uint64) []any\n" - "func @\"\".closure ()\n" - "func @\"\".int64div (? int64, ? int64) int64\n" - "func @\"\".uint64div (? uint64, ? uint64) uint64\n" - "func @\"\".int64mod (? int64, ? int64) int64\n" - "func @\"\".uint64mod (? uint64, ? uint64) uint64\n" - "func @\"\".float64toint64 (? float64) int64\n" - "func @\"\".float64touint64 (? float64) uint64\n" - "func @\"\".int64tofloat64 (? int64) float64\n" - "func @\"\".uint64tofloat64 (? uint64) float64\n" - "func @\"\".complex128div (num complex128, den complex128) complex128\n" + "func @\"\".new(typ *byte) *any\n" + "func @\"\".panicindex()\n" + "func @\"\".panicslice()\n" + "func @\"\".throwreturn()\n" + "func @\"\".throwinit()\n" + "func @\"\".panicwrap(? string, ? string, ? string)\n" + "func @\"\".panic(? interface {})\n" + "func @\"\".recover(? *int32) interface {}\n" + "func @\"\".printbool(? bool)\n" + "func @\"\".printfloat(? float64)\n" + "func @\"\".printint(? int64)\n" + "func @\"\".printuint(? uint64)\n" + "func @\"\".printcomplex(? complex128)\n" + "func @\"\".printstring(? string)\n" + "func @\"\".printpointer(? any)\n" + "func @\"\".printiface(? any)\n" + "func @\"\".printeface(? any)\n" + "func @\"\".printslice(? any)\n" + "func @\"\".printnl()\n" + "func @\"\".printsp()\n" + "func @\"\".goprintf()\n" + "func @\"\".concatstring()\n" + "func @\"\".append()\n" + "func @\"\".appendslice(typ *byte, x any, y []any) any\n" + "func @\"\".appendstr(typ *byte, x []byte, y string) []byte\n" + "func @\"\".cmpstring(? string, ? string) int\n" + "func @\"\".slicestring(? string, ? int, ? int) string\n" + "func @\"\".slicestring1(? string, ? int) string\n" + "func @\"\".intstring(? int64) string\n" + "func @\"\".slicebytetostring(? []byte) string\n" + "func @\"\".slicerunetostring(? []rune) string\n" + "func @\"\".stringtoslicebyte(? string) []byte\n" + "func @\"\".stringtoslicerune(? string) []rune\n" + "func @\"\".stringiter(? string, ? int) int\n" + "func @\"\".stringiter2(? string, ? int) (retk int, retv rune)\n" + "func @\"\".copy(to any, fr any, wid uint32) int\n" + "func @\"\".slicestringcopy(to any, fr any) int\n" + "func @\"\".convI2E(elem any) any\n" + "func @\"\".convI2I(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 @\"\".assertE2E(typ *byte, iface any) any\n" + "func @\"\".assertE2E2(typ *byte, iface any) (ret any, ok bool)\n" + "func @\"\".assertE2I(typ *byte, iface any) any\n" + "func @\"\".assertE2I2(typ *byte, iface any) (ret any, ok bool)\n" + "func @\"\".assertE2T(typ *byte, iface any) any\n" + "func @\"\".assertE2T2(typ *byte, iface any) (ret any, ok bool)\n" + "func @\"\".assertI2E(typ *byte, iface any) any\n" + "func @\"\".assertI2E2(typ *byte, iface any) (ret any, ok bool)\n" + "func @\"\".assertI2I(typ *byte, iface any) any\n" + "func @\"\".assertI2I2(typ *byte, iface any) (ret any, ok bool)\n" + "func @\"\".assertI2T(typ *byte, iface any) any\n" + "func @\"\".assertI2T2(typ *byte, iface any) (ret any, ok bool)\n" + "func @\"\".ifaceeq(i1 any, i2 any) bool\n" + "func @\"\".efaceeq(i1 any, i2 any) bool\n" + "func @\"\".ifacethash(i1 any) uint32\n" + "func @\"\".efacethash(i1 any) uint32\n" + "func @\"\".makemap(mapType *byte, hint int64) map[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 @\"\".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 @\"\".mapiterinit(mapType *byte, hmap map[any]any, hiter *any)\n" + "func @\"\".mapdelete(mapType *byte, hmap map[any]any, key any)\n" + "func @\"\".mapiternext(hiter *any)\n" + "func @\"\".mapiter1(hiter *any) any\n" + "func @\"\".mapiter2(hiter *any) (key any, val any)\n" + "func @\"\".makechan(chanType *byte, hint int64) chan any\n" + "func @\"\".chanrecv1(chanType *byte, hchan <-chan any) any\n" + "func @\"\".chanrecv2(chanType *byte, hchan <-chan any) (elem any, received bool)\n" + "func @\"\".chansend1(chanType *byte, hchan chan<- any, elem any)\n" + "func @\"\".closechan(hchan any)\n" + "func @\"\".selectnbsend(chanType *byte, hchan chan<- any, elem 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 @\"\".newselect(size int) *byte\n" + "func @\"\".selectsend(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 @\"\".selectdefault(sel *byte) bool\n" + "func @\"\".selectgo(sel *byte)\n" + "func @\"\".block()\n" + "func @\"\".makeslice(typ *byte, nel int64, cap int64) []any\n" + "func @\"\".growslice(typ *byte, old []any, n int64) []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 @\"\".slicearray(old *any, nel uint64, lb uint64, hb uint64, width uint64) []any\n" + "func @\"\".closure()\n" + "func @\"\".int64div(? int64, ? int64) int64\n" + "func @\"\".uint64div(? uint64, ? uint64) uint64\n" + "func @\"\".int64mod(? int64, ? int64) int64\n" + "func @\"\".uint64mod(? uint64, ? uint64) uint64\n" + "func @\"\".float64toint64(? float64) int64\n" + "func @\"\".float64touint64(? float64) uint64\n" + "func @\"\".int64tofloat64(? int64) float64\n" + "func @\"\".uint64tofloat64(? uint64) float64\n" + "func @\"\".complex128div(num complex128, den complex128) complex128\n" "\n" "$$\n"; char *unsafeimport = "package unsafe\n" "import runtime \"runtime\"\n" "type @\"\".Pointer uintptr\n" - "func @\"\".Offsetof (? any) uintptr\n" - "func @\"\".Sizeof (? any) uintptr\n" - "func @\"\".Alignof (? any) uintptr\n" - "func @\"\".Typeof (i interface { }) interface { }\n" - "func @\"\".Reflect (i interface { }) (typ interface { }, addr @\"\".Pointer)\n" - "func @\"\".Unreflect (typ interface { }, addr @\"\".Pointer) interface { }\n" - "func @\"\".New (typ interface { }) @\"\".Pointer\n" - "func @\"\".NewArray (typ interface { }, n int) @\"\".Pointer\n" + "func @\"\".Offsetof(? any) uintptr\n" + "func @\"\".Sizeof(? any) uintptr\n" + "func @\"\".Alignof(? any) uintptr\n" + "func @\"\".Typeof(i interface {}) interface {}\n" + "func @\"\".Reflect(i interface {}) (typ interface {}, addr @\"\".Pointer)\n" + "func @\"\".Unreflect(typ interface {}, addr @\"\".Pointer) interface {}\n" + "func @\"\".New(typ interface {}) @\"\".Pointer\n" + "func @\"\".NewArray(typ interface {}, n int) @\"\".Pointer\n" "\n" "$$\n"; diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index 5ac044c820..59f43dd6d6 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -72,35 +72,6 @@ struct Strlit 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 { Mpscale = 29, // safely smaller than bits in a long diff --git a/src/cmd/gc/range.c b/src/cmd/gc/range.c index 25d1131ec3..9bcd833a70 100644 --- a/src/cmd/gc/range.c +++ b/src/cmd/gc/range.c @@ -167,7 +167,9 @@ walkrange(Node *n) case TMAP: th = typ(TARRAY); 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); fn = syslook("mapiterinit", 1); diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c index d59d1a5397..e765ad6e5b 100644 --- a/src/cmd/gc/reflect.c +++ b/src/cmd/gc/reflect.c @@ -553,10 +553,15 @@ haspointers(Type *t) static int dcommontype(Sym *s, int ot, Type *t) { - int i; + int i, sizeofAlg; Sym *sptr; + static Sym *algarray; char *p; + sizeofAlg = 4*widthptr; + if(algarray == nil) + algarray = pkglookup("algarray", runtimepkg); + dowidth(t); 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 = 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); // fieldAlign i = kinds[t->etype]; @@ -595,6 +600,7 @@ dcommontype(Sym *s, int ot, Type *t) if(!haspointers(t)) i |= KindNoPointers; ot = duint8(s, ot, i); // kind + ot = dsymptr(s, ot, algarray, algtype(t)*sizeofAlg); p = smprint("%-uT", t); //print("dcommontype: %s\n", p); ot = dgostringptr(s, ot, p); // string diff --git a/src/cmd/gc/runtime.go b/src/cmd/gc/runtime.go index 1bf2ad482e..96539c42bc 100644 --- a/src/cmd/gc/runtime.go +++ b/src/cmd/gc/runtime.go @@ -52,7 +52,7 @@ func stringtoslicebyte(string) []byte func stringtoslicerune(string) []rune func stringiter(string, int) int 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 // interface conversions diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c index 2d8ae64913..075a801a30 100644 --- a/src/cmd/gc/walk.c +++ b/src/cmd/gc/walk.c @@ -1078,7 +1078,7 @@ walkexpr(Node **np, NodeList **init) if(n->right->type->etype == TSTRING) fn = syslook("slicestringcopy", 1); else - fn = syslook("slicecopy", 1); + fn = syslook("copy", 1); argtype(fn, n->left->type); argtype(fn, n->right->type); n = mkcall1(fn, n->type, init, diff --git a/src/cmd/ld/dwarf.c b/src/cmd/ld/dwarf.c index 373cf55237..cbd4522039 100644 --- a/src/cmd/ld/dwarf.c +++ b/src/cmd/ld/dwarf.c @@ -775,7 +775,7 @@ enum { KindNoPointers = 1<<7, // size of Type interface header + CommonType structure. - CommonSize = 2*PtrSize+ 4*PtrSize + 8, + CommonSize = 2*PtrSize+ 5*PtrSize + 8, }; static Reloc* diff --git a/src/pkg/reflect/type.go b/src/pkg/reflect/type.go index 30483fc094..d522a6a0b2 100644 --- a/src/pkg/reflect/type.go +++ b/src/pkg/reflect/type.go @@ -241,10 +241,11 @@ const ( type commonType struct { size uintptr hash uint32 - alg uint8 + _ uint8 align uint8 fieldAlign uint8 kind uint8 + alg *uintptr string *string *uncommonType ptrToThis *runtime.Type diff --git a/src/pkg/runtime/Makefile b/src/pkg/runtime/Makefile index 40150d2f68..a7d8ce85fe 100644 --- a/src/pkg/runtime/Makefile +++ b/src/pkg/runtime/Makefile @@ -63,6 +63,7 @@ OFILES_arm=\ vlrt.$O\ OFILES=\ + alg.$O\ asm.$O\ atomic.$O\ cgocall.$O\ diff --git a/src/pkg/runtime/alg.c b/src/pkg/runtime/alg.c new file mode 100644 index 0000000000..e995b0f5a7 --- /dev/null +++ b/src/pkg/runtime/alg.c @@ -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 }, +}; + diff --git a/src/pkg/runtime/chan.c b/src/pkg/runtime/chan.c index e128accbec..bea1a34f8f 100644 --- a/src/pkg/runtime/chan.c +++ b/src/pkg/runtime/chan.c @@ -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)) 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 n = sizeof(*c); while(n & MAXALIGN) @@ -105,12 +100,12 @@ runtime·makechan_c(ChanType *t, int64 hint) // allocate memory in one call c = (Hchan*)runtime·mal(n + hint*elem->size); c->elemsize = elem->size; - c->elemalg = &runtime·algarray[elem->alg]; + c->elemalg = elem->alg; c->elemalign = elem->align; c->dataqsiz = hint; 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); return c; diff --git a/src/pkg/runtime/hashmap.c b/src/pkg/runtime/hashmap.c index 2ecd3d0fe7..642995df89 100644 --- a/src/pkg/runtime/hashmap.c +++ b/src/pkg/runtime/hashmap.c @@ -6,41 +6,14 @@ #include "hashmap.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() */ uint32 count; /* elements in table - must be first */ - uint8 datasize; /* amount of data to store in entry */ 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 */ - 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 */ - - 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 { @@ -58,7 +31,7 @@ struct hash_subtable { 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 */ /* 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) \ ((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 */ 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 bytes = elemsize << power; struct hash_subtable *st; - int32 limit_bytes = h->max_probes * elemsize; - int32 max_probes = h->max_probes; + int32 limit_bytes = HASH_MAX_PROBES * elemsize; + int32 max_probes = HASH_MAX_PROBES; if (bytes < limit_bytes) { limit_bytes = bytes; @@ -127,12 +101,7 @@ init_sizes (int64 hint, int32 *init_power, int32 *max_power) } static void -hash_init (Hmap *h, - int32 datasize, - hash_hash_t (*data_hash) (uint32, void *), - uint32 (*data_eq) (uint32, void *, void *), - void (*data_del) (uint32, void *, void *), - int64 hint) +hash_init (Hmap *h, int32 datasize, int64 hint) { int32 init_power; int32 max_power; @@ -143,15 +112,11 @@ hash_init (Hmap *h, init_sizes (hint, &init_power, &max_power); h->datasize = datasize; h->max_power = max_power; - h->max_probes = 15; assert (h->datasize == datasize); assert (h->max_power == max_power); assert (sizeof (void *) <= h->datasize || h->max_power == 255); h->count = 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); } @@ -199,11 +164,11 @@ hash_remove_n (struct hash_subtable *st, struct hash_entry *dst_e, int32 n) } 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); static void -hash_conv (Hmap *h, +hash_conv (MapType *t, Hmap *h, struct hash_subtable *st, int32 flags, hash_hash_t hash, struct hash_entry *e) @@ -238,13 +203,13 @@ hash_conv (Hmap *h, (ne <= st->last && (e_hash = ne->hash) != HASH_NIL && (e_hash & prefix_mask) == current)) { 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); memcpy(dummy_result, e->data, h->datasize); e = ne; while (e <= st->last && (e_hash = e->hash) != HASH_NIL && (e_hash & prefix_mask) == current) { 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); memcpy(dummy_result, e->data, h->datasize); e = HASH_OFFSET (e, elemsize); @@ -266,7 +231,7 @@ hash_conv (Hmap *h, } 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; 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)) { hash_hash_t hash = e->hash; 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); memcpy(dummy_result, e->data, h->datasize); used++; @@ -290,16 +255,20 @@ hash_grow (Hmap *h, struct hash_subtable **pst, int32 flags) } 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]); - hash_hash_t hash = (*h->data_hash) (h->keysize, data) & ~HASH_MASK; + hash_hash_t hash; struct hash_subtable *st = h->st; int32 used = 0; hash_hash_t e_hash; struct hash_entry *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); for (;;) { int32 shift = HASH_BITS - (st->power + used); @@ -319,7 +288,7 @@ hash_lookup (Hmap *h, void *data, void **pres) e = HASH_OFFSET (e, elemsize); } 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; return (1); } @@ -331,16 +300,20 @@ hash_lookup (Hmap *h, void *data, void **pres) } 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]); - hash_hash_t hash = (*h->data_hash) (h->keysize, data) & ~HASH_MASK; + hash_hash_t hash; struct hash_subtable *st = h->st; int32 used = 0; hash_hash_t e_hash; struct hash_entry *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); for (;;) { int32 shift = HASH_BITS - (st->power + used); @@ -360,8 +333,9 @@ hash_remove (Hmap *h, void *data, void *arg) e = HASH_OFFSET (e, elemsize); } while (e != end_e && ((e_hash = e->hash) ^ hash) < HASH_SUBHASH) { - if (HASH_DATA_EQ (h, data, e->data)) { /* a match */ - (*h->data_del) (h->datavo, arg, e->data); + if (HASH_DATA_EQ (eq, t, h, data, e->data)) { /* a match */ + if (h->indirectval) + free (*(void**)((byte*)e->data + h->valoff)); hash_remove_n (st, e, 1); h->count--; return (1); @@ -373,10 +347,11 @@ hash_remove (Hmap *h, void *data, void *arg) } 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) { int32 elemsize = h->datasize + offsetof (struct hash_entry, data[0]); + bool eq; if ((flags & HASH_REHASH) == 0) { 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; hash_hash_t ins_e_hash; 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; return (1); } @@ -447,17 +422,22 @@ hash_insert_internal (struct hash_subtable **pst, int32 flags, hash_hash_t hash, } h->changes++; if (st->power < h->max_power) { - hash_grow (h, pst, flags); + hash_grow (t, h, pst, flags); } else { - hash_conv (h, st, flags, hash, start_e); + hash_conv (t, h, st, flags, hash, start_e); } } } 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 */ return (rc); @@ -528,7 +508,7 @@ Again: last = sub->last; 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); hash_hash_t last_hash = it->last_hash; if (start < sub->start) { @@ -599,12 +579,13 @@ Again: } 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->changes = h->changes; it->i = 0; it->h = h; + it->t = t; it->last_hash = 0; it->subtable_state[0].e = h->st->entry; it->subtable_state[0].start = h->st->entry; @@ -701,24 +682,6 @@ enum { 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** hash_indirect(Hmap *h, void *p) { @@ -734,8 +697,7 @@ Hmap* runtime·makemap_c(MapType *typ, int64 hint) { Hmap *h; - int32 keyalg, valalg, keysize, valsize, valsize_in_hash; - void (*data_del)(uint32, void*, void*); + int32 valsize_in_hash; Type *key, *val; key = typ->key; @@ -744,68 +706,30 @@ runtime·makemap_c(MapType *typ, int64 hint) if(hint < 0 || (int32)hint != hint) runtime·panicstring("makemap: size out of range"); - keyalg = key->alg; - 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); + if(key->alg->hash == runtime·nohash) 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)); - valsize_in_hash = valsize; - data_del = donothing; - if (valsize > MaxValsize) { + valsize_in_hash = val->size; + if (val->size > MaxValsize) { h->indirectval = 1; - data_del = freedata; valsize_in_hash = sizeof(void*); } - // align value inside data so that mark-sweep gc can find it. - // might remove in the future and just assume datavo == keysize. - h->datavo = keysize; + // Align value inside data so that mark-sweep gc can find it. + h->valoff = key->size; 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, - 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]; + hash_init(h, h->valoff+valsize_in_hash, hint); // these calculations are compiler dependent. // 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) { - runtime·printf("makemap: map=%p; keysize=%d; valsize=%d; keyalg=%d; valalg=%d; offsets=%d,%d; %d,%d,%d; %d,%d,%d\n", - h, keysize, valsize, keyalg, valalg, h->ko0, h->vo0, h->ko1, h->vo1, h->po1, h->ko2, h->vo2, h->po2); + runtime·printf("makemap: map=%p; keysize=%p; valsize=%p; keyalg=%p; valalg=%p\n", + h, key->size, val->size, key->alg, val->alg); } return h; @@ -834,9 +758,9 @@ runtime·mapaccess(MapType *t, Hmap *h, byte *ak, byte *av, bool *pres) byte *res; Type *elem; + elem = t->elem; if(h == nil) { - elem = t->elem; - runtime·algarray[elem->alg].copy(elem->size, av, nil); + elem->alg->copy(elem->size, av, nil); *pres = false; return; } @@ -845,12 +769,12 @@ runtime·mapaccess(MapType *t, Hmap *h, byte *ak, byte *av, bool *pres) runtime·gosched(); res = nil; - if(hash_lookup(h, ak, (void**)&res)) { + if(hash_lookup(t, h, ak, (void**)&res)) { *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 { *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; bool pres; - if(h == nil) { - ak = (byte*)(&h + 1); - av = ak + runtime·rnd(t->key->size, Structrnd); - } else { - ak = (byte*)&h + h->ko1; - av = (byte*)&h + h->vo1; - } + ak = (byte*)(&h + 1); + av = ak + runtime·rnd(t->key->size, Structrnd); runtime·mapaccess(t, h, ak, av, &pres); @@ -876,9 +795,9 @@ runtime·mapaccess1(MapType *t, Hmap *h, ...) runtime·prints("runtime.mapaccess1: map="); runtime·printpointer(h); runtime·prints("; key="); - h->keyalg->print(h->keysize, ak); + t->key->alg->print(t->key->size, ak); runtime·prints("; val="); - h->valalg->print(h->valsize, av); + t->elem->alg->print(t->elem->size, av); runtime·prints("; pres="); runtime·printbool(pres); runtime·prints("\n"); @@ -892,15 +811,9 @@ runtime·mapaccess2(MapType *t, Hmap *h, ...) { byte *ak, *av, *ap; - if(h == nil) { - ak = (byte*)(&h + 1); - av = ak + runtime·rnd(t->key->size, Structrnd); - ap = av + t->elem->size; - } else { - ak = (byte*)&h + h->ko1; - av = (byte*)&h + h->vo1; - ap = (byte*)&h + h->po1; - } + ak = (byte*)(&h + 1); + av = ak + runtime·rnd(t->key->size, Structrnd); + ap = av + t->elem->size; runtime·mapaccess(t, h, ak, av, ap); @@ -908,9 +821,9 @@ runtime·mapaccess2(MapType *t, Hmap *h, ...) runtime·prints("runtime.mapaccess2: map="); runtime·printpointer(h); runtime·prints("; key="); - h->keyalg->print(h->keysize, ak); + t->key->alg->print(t->key->size, ak); runtime·prints("; val="); - h->valalg->print(h->valsize, av); + t->elem->alg->print(t->key->size, av); runtime·prints("; pres="); runtime·printbool(*ap); runtime·prints("\n"); @@ -949,33 +862,31 @@ runtime·mapassign(MapType *t, Hmap *h, byte *ak, byte *av) byte *res; int32 hit; - USED(t); - if(h == nil) runtime·panicstring("assignment to entry in nil map"); if(runtime·gcwaiting) runtime·gosched(); - res = nil; if(av == nil) { - hash_remove(h, ak, (void**)&res); + hash_remove(t, h, ak); return; } - hit = hash_insert(h, ak, (void**)&res); + res = nil; + hit = hash_insert(t, h, ak, (void**)&res); if(!hit && h->indirectval) - *(void**)(res+h->datavo) = runtime·mal(h->valsize); - h->keyalg->copy(h->keysize, res, ak); - h->valalg->copy(h->valsize, hash_indirect(h, res+h->datavo), av); + *(void**)(res+h->valoff) = runtime·mal(t->elem->size); + t->key->alg->copy(t->key->size, res, ak); + t->elem->alg->copy(t->elem->size, hash_indirect(h, res+h->valoff), av); if(debug) { runtime·prints("mapassign: map="); runtime·printpointer(h); runtime·prints("; key="); - h->keyalg->print(h->keysize, ak); + t->key->alg->print(t->key->size, ak); runtime·prints("; val="); - h->valalg->print(h->valsize, av); + t->elem->alg->print(t->elem->size, av); runtime·prints("; hit="); runtime·printint(hit); runtime·prints("; res="); @@ -994,8 +905,8 @@ runtime·mapassign1(MapType *t, Hmap *h, ...) if(h == nil) runtime·panicstring("assignment to entry in nil map"); - ak = (byte*)&h + h->ko2; - av = (byte*)&h + h->vo2; + ak = (byte*)(&h + 1); + av = ak + runtime·rnd(t->key->size, t->elem->align); runtime·mapassign(t, h, ak, av); } @@ -1010,14 +921,14 @@ runtime·mapdelete(MapType *t, Hmap *h, ...) if(h == nil) runtime·panicstring("deletion of entry in nil map"); - ak = (byte*)&h + h->ko2; + ak = (byte*)(&h + 1); runtime·mapassign(t, h, ak, nil); if(debug) { runtime·prints("mapdelete: map="); runtime·printpointer(h); runtime·prints("; key="); - h->keyalg->print(h->keysize, ak); + t->key->alg->print(t->key->size, ak); runtime·prints("\n"); } } @@ -1033,11 +944,11 @@ reflect·mapassign(MapType *t, Hmap *h, uintptr key, uintptr val, bool pres) if(h == nil) runtime·panicstring("assignment to entry in nil map"); - if(h->keysize <= sizeof(key)) + if(t->key->size <= sizeof(key)) ak = (byte*)&key; else ak = (byte*)key; - if(h->valsize <= sizeof(val)) + if(t->elem->size <= sizeof(val)) av = (byte*)&val; else 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); void -runtime·mapiterinit(MapType*, Hmap *h, struct hash_iter *it) +runtime·mapiterinit(MapType *t, Hmap *h, struct hash_iter *it) { if(h == nil) { it->data = nil; return; } - hash_iter_init(h, it); + hash_iter_init(t, h, it); it->data = hash_next(it); if(debug) { runtime·prints("runtime.mapiterinit: map="); @@ -1109,15 +1020,17 @@ runtime·mapiter1(struct hash_iter *it, ...) { Hmap *h; byte *ak, *res; + Type *key; h = it->h; - ak = (byte*)&it + h->ko0; + ak = (byte*)(&it + 1); res = it->data; if(res == nil) 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) { runtime·prints("mapiter2: iter="); @@ -1131,14 +1044,14 @@ runtime·mapiter1(struct hash_iter *it, ...) bool runtime·mapiterkey(struct hash_iter *it, void *ak) { - Hmap *h; byte *res; + Type *key; - h = it->h; res = it->data; if(res == nil) return false; - h->keyalg->copy(h->keysize, ak, res); + key = it->t->key; + key->alg->copy(key->size, ak, res); return true; } @@ -1149,20 +1062,20 @@ runtime·mapiterkey(struct hash_iter *it, void *ak) void reflect·mapiterkey(struct hash_iter *it, uintptr key, bool ok) { - Hmap *h; byte *res; + Type *tkey; key = 0; ok = false; - h = it->h; res = it->data; if(res == nil) { key = 0; ok = false; } else { + tkey = it->t->key; key = 0; - if(h->keysize <= sizeof(key)) - h->keyalg->copy(h->keysize, (byte*)&key, res); + if(tkey->size <= sizeof(key)) + tkey->alg->copy(tkey->size, (byte*)&key, res); else key = (uintptr)res; ok = true; @@ -1191,17 +1104,19 @@ runtime·mapiter2(struct hash_iter *it, ...) { Hmap *h; byte *ak, *av, *res; + MapType *t; - h = it->h; - ak = (byte*)&it + h->ko0; - av = (byte*)&it + h->vo0; + t = it->t; + ak = (byte*)(&it + 1); + av = ak + runtime·rnd(t->key->size, t->elem->align); res = it->data; if(res == nil) runtime·throw("runtime.mapiter2: key:val nil pointer"); - h->keyalg->copy(h->keysize, ak, res); - h->valalg->copy(h->valsize, av, hash_indirect(h, res+h->datavo)); + h = it->h; + 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) { runtime·prints("mapiter2: iter="); diff --git a/src/pkg/runtime/hashmap.h b/src/pkg/runtime/hashmap.h index d5f8a48000..218cfc7d71 100644 --- a/src/pkg/runtime/hashmap.h +++ b/src/pkg/runtime/hashmap.h @@ -86,6 +86,7 @@ struct hash_iter { hash_hash_t last_hash; /* last hash value returned */ hash_hash_t cycle; /* hash value where we started */ struct Hmap *h; /* the hash table */ + MapType *t; /* the map type */ struct hash_iter_sub { struct hash_entry *e; /* pointer into subtable */ struct hash_entry *start; /* start of subtable */ diff --git a/src/pkg/runtime/iface.c b/src/pkg/runtime/iface.c index 940df80571..c9d020fbeb 100644 --- a/src/pkg/runtime/iface.c +++ b/src/pkg/runtime/iface.c @@ -159,17 +159,18 @@ out: static void copyin(Type *t, void *src, void **dst) { - int32 wid, alg; + uintptr size; void *p; + Alg *alg; - wid = t->size; + size = t->size; alg = t->alg; - if(wid <= sizeof(*dst)) - runtime·algarray[alg].copy(wid, dst, src); + if(size <= sizeof(*dst)) + alg->copy(size, dst, src); else { - p = runtime·mal(wid); - runtime·algarray[alg].copy(wid, p, src); + p = runtime·mal(size); + alg->copy(size, p, src); *dst = p; } } @@ -177,15 +178,16 @@ copyin(Type *t, void *src, void **dst) static void copyout(Type *t, void **src, void *dst) { - int32 wid, alg; + uintptr size; + Alg *alg; - wid = t->size; + size = t->size; alg = t->alg; - if(wid <= sizeof(*src)) - runtime·algarray[alg].copy(wid, dst, src); + if(size <= sizeof(*src)) + alg->copy(size, dst, src); else - runtime·algarray[alg].copy(wid, dst, *src); + alg->copy(size, dst, *src); } // 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 ifacehash1(void *data, Type *t) { - int32 alg, wid; + Alg *alg; + uintptr size, h; Eface err; if(t == nil) return 0; alg = t->alg; - wid = t->size; - if(runtime·algarray[alg].hash == runtime·nohash) { + size = t->size; + if(alg->hash == runtime·nohash) { // calling nohash will panic too, // but we can print a better error. runtime·newErrorString(runtime·catstring(runtime·gostringnocopy((byte*)"hash of unhashable type "), *t->string), &err); runtime·panic(err); } - if(wid <= sizeof(data)) - return runtime·algarray[alg].hash(wid, &data); - return runtime·algarray[alg].hash(wid, data); + h = 0; + if(size <= sizeof(data)) + alg->hash(&h, size, &data); + else + alg->hash(&h, size, data); + return h; } uintptr @@ -584,22 +590,27 @@ runtime·efacehash(Eface a) static bool ifaceeq1(void *data1, void *data2, Type *t) { - int32 alg, wid; + uintptr size; + Alg *alg; Eface err; + bool eq; 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, // but we can print a better error. runtime·newErrorString(runtime·catstring(runtime·gostringnocopy((byte*)"comparing uncomparable type "), *t->string), &err); runtime·panic(err); } - if(wid <= sizeof(data1)) - return runtime·algarray[alg].equal(wid, &data1, &data2); - return runtime·algarray[alg].equal(wid, data1, data2); + eq = 0; + if(size <= sizeof(data1)) + alg->equal(&eq, size, &data1, &data2); + else + alg->equal(&eq, size, data1, data2); + return eq; } bool @@ -701,7 +712,7 @@ unsafe·Reflect(Eface e, Eface rettype, void *retaddr) if(e.type->size <= sizeof(uintptr)) { // Copy data into x ... 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 // 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, // to preserve value semantics for interface data. 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; } @@ -734,7 +745,7 @@ unsafe·Unreflect(Eface typ, void *addr, Eface e) // Interface holds either pointer to data // or copy of original data. 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 { // Easier: already a pointer to data. // TODO(rsc): Should this make a copy? diff --git a/src/pkg/runtime/runtime.c b/src/pkg/runtime/runtime.c index a609a26f80..ed46150ea5 100644 --- a/src/pkg/runtime/runtime.c +++ b/src/pkg/runtime/runtime.c @@ -322,338 +322,6 @@ runtime·check(void) 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 runtime·Caller(int32 skip, uintptr retpc, String retfile, int32 retline, bool retbool) { diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h index 9324ef76bb..4aade25fe7 100644 --- a/src/pkg/runtime/runtime.h +++ b/src/pkg/runtime/runtime.h @@ -43,7 +43,6 @@ typedef int32 intptr; */ typedef uint8 bool; typedef uint8 byte; -typedef struct Alg Alg; typedef struct Func Func; typedef struct G G; typedef struct Gobuf Gobuf; @@ -260,13 +259,6 @@ struct Stktop uintptr free; // if free>0, call stackfree using free as size 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 { int32 flags; @@ -356,6 +348,13 @@ struct Timer /* * known to compiler */ +enum { + Structrnd = sizeof(uintptr) +}; + +/* + * type algorithms - known to compiler + */ enum { AMEM, @@ -376,12 +375,46 @@ enum ANOEQ128, Amax }; - - -enum { - Structrnd = sizeof(uintptr) +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]; + +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 */ @@ -410,7 +443,6 @@ struct Panic /* * external data */ -extern Alg runtime·algarray[Amax]; extern String runtime·emptystring; G* runtime·allg; G* runtime·lastg; @@ -498,8 +530,6 @@ bool runtime·ifaceeq_c(Iface, Iface); bool runtime·efaceeq_c(Eface, Eface); uintptr runtime·ifacehash(Iface); uintptr runtime·efacehash(Eface); -uintptr runtime·nohash(uint32, void*); -uint32 runtime·noequal(uint32, void*, void*); void* runtime·malloc(uintptr size); void runtime·free(void *v); bool runtime·addfinalizer(void*, void(*fn)(void*), int32); diff --git a/src/pkg/runtime/slice.c b/src/pkg/runtime/slice.c index 2fe4c6da47..3bc5cff080 100644 --- a/src/pkg/runtime/slice.c +++ b/src/pkg/runtime/slice.c @@ -11,7 +11,7 @@ static int32 debug = 0; static void makeslice1(SliceType*, int32, 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 // 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 -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) { ret = 0; diff --git a/src/pkg/runtime/type.go b/src/pkg/runtime/type.go index 30f3ec6423..1e0d723bd0 100644 --- a/src/pkg/runtime/type.go +++ b/src/pkg/runtime/type.go @@ -27,15 +27,16 @@ type Type interface{} // All types begin with a few common fields needed for // the interface runtime. type commonType struct { - size uintptr // size in bytes - hash uint32 // hash of type; avoids computation in hash tables - alg uint8 // algorithm for copy+hash+cmp (../runtime/runtime.h:/AMEM) - align uint8 // alignment of variable with this type - fieldAlign uint8 // alignment of struct field with this type - kind uint8 // enumeration for C - string *string // string form; unnecessary but undeniably useful - *uncommonType // (relatively) uncommon fields - ptrToThis *Type // pointer to this type, if used in binary or has methods + size uintptr // size in bytes + hash uint32 // hash of type; avoids computation in hash tables + _ uint8 // unused + align uint8 // alignment of variable with this type + fieldAlign uint8 // alignment of struct field with this type + kind uint8 // enumeration for C + alg *uintptr // algorithm table (../runtime/runtime.h:/Alg) + string *string // string form; unnecessary but undeniably useful + *uncommonType // (relatively) uncommon fields + ptrToThis *Type // pointer to this type, if used in binary or has methods } // Values for commonType.kind. diff --git a/src/pkg/runtime/type.h b/src/pkg/runtime/type.h index 8c80c62d39..c1d9facd10 100644 --- a/src/pkg/runtime/type.h +++ b/src/pkg/runtime/type.h @@ -23,10 +23,11 @@ struct CommonType { uintptr size; uint32 hash; - uint8 alg; + uint8 _unused; uint8 align; uint8 fieldAlign; uint8 kind; + Alg *alg; String *string; UncommonType *x; Type *ptrto;