]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: prep for type-specific algorithms
authorRuss Cox <rsc@golang.org>
Mon, 5 Dec 2011 14:40:22 +0000 (09:40 -0500)
committerRuss Cox <rsc@golang.org>
Mon, 5 Dec 2011 14:40:22 +0000 (09:40 -0500)
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

19 files changed:
src/cmd/gc/builtin.c.boot
src/cmd/gc/go.h
src/cmd/gc/range.c
src/cmd/gc/reflect.c
src/cmd/gc/runtime.go
src/cmd/gc/walk.c
src/cmd/ld/dwarf.c
src/pkg/reflect/type.go
src/pkg/runtime/Makefile
src/pkg/runtime/alg.c [new file with mode: 0644]
src/pkg/runtime/chan.c
src/pkg/runtime/hashmap.c
src/pkg/runtime/hashmap.h
src/pkg/runtime/iface.c
src/pkg/runtime/runtime.c
src/pkg/runtime/runtime.h
src/pkg/runtime/slice.c
src/pkg/runtime/type.go
src/pkg/runtime/type.h

index f6508b55a3f7d97bb8cdd377576cd8875849b0b4..ea73c0ea31e0938f5e9b14a62464a26ce9ace879 100644 (file)
 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";
index 5ac044c82025f3193c06c8fb3e838d2f447ffacd..59f43dd6d6f4ecc544d1c5ef7341a6358cfc2e9f 100644 (file)
@@ -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
index 25d1131ec3dab2631ec0746fa203ca666dbd342b..9bcd833a706d4d1436cea3dac485e48a9abf4e49 100644 (file)
@@ -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);
index d59d1a5397710478124b0a74530ea2b280630097..e765ad6e5b5d66d6bc568e0988719634d8a45acb 100644 (file)
@@ -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
index 1bf2ad482eb6f135639f9557742b40db4c61a44b..96539c42bc96e0780b49925342d83733ea7bd951 100644 (file)
@@ -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
index 2d8ae649139f03b1ae9dd6b5ea72dc98bde70f78..075a801a3030a23d259fa18cd0b5e6fd16d6f27f 100644 (file)
@@ -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,
index 373cf5523736b8831dfa10538178d4c139d55b76..cbd4522039baebe671b6eab4bdc76ee7782869e5 100644 (file)
@@ -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*
index 30483fc094de5fa257a9810b7c8fdffd6eb18cdf..d522a6a0b279d619e30742caae0215fbfd09f2e9 100644 (file)
@@ -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
index 40150d2f6833b28af745c711f0b25cd7f5f6e09e..a7d8ce85fea258f1595b745db98897b12bb459e2 100644 (file)
@@ -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 (file)
index 0000000..e995b0f
--- /dev/null
@@ -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 },
+};
+
index e128accbecbdaf7645f843e7f59496b63c932ad7..bea1a34f8f0e6116d70ea503fcb4b4d73063ebfb 100644 (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))
                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;
index 2ecd3d0fe7c786b0013aa5463b554ce4bc2744cd..642995df897f4eb40270e0f860770522fa0ccf5b 100644 (file)
@@ -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=");
index d5f8a48000b1dd89a1f13cc830aac3fd0043350d..218cfc7d7177555edb4e642d94597721286df0b8 100644 (file)
@@ -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 */
index 940df80571474113900ac7809020a3c48a81e768..c9d020fbebeb69c9127b62db7ad0c8807c85312f 100644 (file)
@@ -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?
index a609a26f80f4ec4a0097780aeca40c08012bcb51..ed46150ea5202d8e58ba2f6802875b2c449e6385 100644 (file)
@@ -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)
 {
index 9324ef76bb902c36eef5cb0e24a7a30b69e2274a..4aade25fe73563f0981e0460154cce5323f9149e 100644 (file)
@@ -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,11 +375,45 @@ enum
        ANOEQ128,
        Amax
 };
+typedef        struct  Alg             Alg;
+struct Alg
+{
+       void    (*hash)(uintptr*, uintptr, void*);
+       void    (*equal)(bool*, uintptr, void*, void*);
+       void    (*print)(uintptr, void*);
+       void    (*copy)(uintptr, void*, void*);
+};
 
+extern Alg     runtime·algarray[Amax];
 
-enum {
-       Structrnd = sizeof(uintptr)
-};
+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);
index 2fe4c6da472e8fcc8ff628e59a8d288eeb756e0d..3bc5cff080c366aed38c53305ff9a9a6a960e586 100644 (file)
@@ -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;
index 30f3ec6423dd550712832d4443ff6b44c741fa87..1e0d723bd0ebc1eb9d54c3d85098c10353dc40e7 100644 (file)
@@ -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.
index 8c80c62d391bb33a315956f845f9bf7c487712f9..c1d9facd10795d65189281969361ca5c3367c076 100644 (file)
@@ -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;