]> Cypherpunks repositories - gostls13.git/commitdiff
gc: implement nil map support
authorRuss Cox <rsc@golang.org>
Wed, 17 Aug 2011 18:56:27 +0000 (14:56 -0400)
committerRuss Cox <rsc@golang.org>
Wed, 17 Aug 2011 18:56:27 +0000 (14:56 -0400)
The spec has defined nil maps this way for months.
I'm behind.

R=ken2
CC=golang-dev
https://golang.org/cl/4901052

src/cmd/gc/builtin.c.boot
src/cmd/gc/range.c
src/cmd/gc/runtime.go
src/cmd/gc/walk.c
src/pkg/reflect/value.go
src/pkg/runtime/hashmap.c
src/pkg/runtime/runtime.h
src/pkg/runtime/type.h

index 6419873a28c7eef1366ec452f94bb9f801948350..84eef6982df11442c6fb7501fa1cbcf730a89c47 100644 (file)
@@ -57,12 +57,12 @@ char *runtimeimport =
        "func \"\".efaceeq (i1 any, i2 any) bool\n"
        "func \"\".ifacethash (i1 any) uint32\n"
        "func \"\".efacethash (i1 any) uint32\n"
-       "func \"\".makemap (key *uint8, val *uint8, hint int64) map[any] any\n"
-       "func \"\".mapaccess1 (hmap map[any] any, key any) any\n"
-       "func \"\".mapaccess2 (hmap map[any] any, key any) (val any, pres bool)\n"
-       "func \"\".mapassign1 (hmap map[any] any, key any, val any)\n"
-       "func \"\".mapassign2 (hmap map[any] any, key any, val any, pres bool)\n"
-       "func \"\".mapiterinit (hmap map[any] any, hiter *any)\n"
+       "func \"\".makemap (mapType *uint8, hint int64) map[any] any\n"
+       "func \"\".mapaccess1 (mapType *uint8, hmap map[any] any, key any) any\n"
+       "func \"\".mapaccess2 (mapType *uint8, hmap map[any] any, key any) (val any, pres bool)\n"
+       "func \"\".mapassign1 (mapType *uint8, hmap map[any] any, key any, val any)\n"
+       "func \"\".mapassign2 (mapType *uint8, hmap map[any] any, key any, val any, pres bool)\n"
+       "func \"\".mapiterinit (mapType *uint8, hmap map[any] any, hiter *any)\n"
        "func \"\".mapiternext (hiter *any)\n"
        "func \"\".mapiter1 (hiter *any) any\n"
        "func \"\".mapiter2 (hiter *any) (key any, val any)\n"
index fb33e4e4855f7555e8743a086fa8eb919adf237b..5ce693ae35cc60f7438f37d5886642a98948432c 100644 (file)
@@ -175,7 +175,7 @@ walkrange(Node *n)
                argtype(fn, t->down);
                argtype(fn, t->type);
                argtype(fn, th);
-               init = list(init, mkcall1(fn, T, nil, ha, nod(OADDR, hit, N)));
+               init = list(init, mkcall1(fn, T, nil, typename(t), ha, nod(OADDR, hit, N)));
                n->ntest = nod(ONE, nod(OINDEX, hit, nodintconst(0)), nodnil());
 
                fn = syslook("mapiternext", 1);
index 7254f874e85be055de7bc835bf483ec797da13ef..64098ab137cc1b0d43d2619c726ebb797f2cfef4 100644 (file)
@@ -80,12 +80,12 @@ func ifacethash(i1 any) (ret uint32)
 func efacethash(i1 any) (ret uint32)
 
 // *byte is really *runtime.Type
-func makemap(key, val *byte, hint int64) (hmap map[any]any)
-func mapaccess1(hmap map[any]any, key any) (val any)
-func mapaccess2(hmap map[any]any, key any) (val any, pres bool)
-func mapassign1(hmap map[any]any, key any, val any)
-func mapassign2(hmap map[any]any, key any, val any, pres bool)
-func mapiterinit(hmap map[any]any, hiter *any)
+func makemap(mapType *byte, hint int64) (hmap map[any]any)
+func mapaccess1(mapType *byte, hmap map[any]any, key any) (val any)
+func mapaccess2(mapType *byte, hmap map[any]any, key any) (val any, pres bool)
+func mapassign1(mapType *byte, hmap map[any]any, key any, val any)
+func mapassign2(mapType *byte, hmap map[any]any, key any, val any, pres bool)
+func mapiterinit(mapType *byte, hmap map[any]any, hiter *any)
 func mapiternext(hiter *any)
 func mapiter1(hiter *any) (key any)
 func mapiter2(hiter *any) (key any, val any)
index 0383e5a6a50bc70f18670474aa3cbd7340cf741a..7a39db2d80aee68f387069dd1b8d1fe719554f58 100644 (file)
@@ -604,7 +604,7 @@ walkexpr(Node **np, NodeList **init)
                walkexprlistsafe(n->list, init);
                walkexpr(&r->left, init);
                fn = mapfn("mapaccess2", r->left->type);
-               r = mkcall1(fn, getoutargx(fn->type), init, r->left, r->right);
+               r = mkcall1(fn, getoutargx(fn->type), init, typename(r->left->type), r->left, r->right);
                n->rlist = list1(r);
                n->op = OAS2FUNC;
                goto as2func;
@@ -617,7 +617,7 @@ walkexpr(Node **np, NodeList **init)
                walkexprlistsafe(n->list, init);
                l = n->list->n;
                t = l->left->type;
-               n = mkcall1(mapfn("mapassign2", t), T, init, l->left, l->right, n->rlist->n, n->rlist->next->n);
+               n = mkcall1(mapfn("mapassign2", t), T, init, typename(t), l->left, l->right, n->rlist->n, n->rlist->next->n);
                goto ret;
 
        case OAS2DOTTYPE:
@@ -852,7 +852,7 @@ walkexpr(Node **np, NodeList **init)
                        goto ret;
 
                t = n->left->type;
-               n = mkcall1(mapfn("mapaccess1", t), t->type, init, n->left, n->right);
+               n = mkcall1(mapfn("mapaccess1", t), t->type, init, typename(t), n->left, n->right);
                goto ret;
 
        case ORECV:
@@ -1090,8 +1090,7 @@ walkexpr(Node **np, NodeList **init)
                argtype(fn, t->type);   // any-2
 
                n = mkcall1(fn, n->type, init,
-                       typename(t->down),      // key type
-                       typename(t->type),              // value type
+                       typename(n->type),
                        conv(n->left, types[TINT64]));
                goto ret;
 
@@ -1697,6 +1696,7 @@ convas(Node *n, NodeList **init)
 
        if(n->left->op == OINDEXMAP) {
                n = mkcall1(mapfn("mapassign1", n->left->left->type), T, init,
+                       typename(n->left->left->type),
                        n->left->left, n->left->right, n->right);
                goto out;
        }
index 87d12bb0b715a9de687f7938b77ab010bb57ffd8..e40b4349100dce59dcf544ddf8c9a312c574cb14 100644 (file)
@@ -977,7 +977,7 @@ func (v Value) MapIndex(key Value) Value {
 
        flag := (iv.flag | ikey.flag) & flagRO
        elemType := typ.Elem()
-       elemWord, ok := mapaccess(iv.word, ikey.word)
+       elemWord, ok := mapaccess(typ.runtimeType(), iv.word, ikey.word)
        if !ok {
                return Value{}
        }
@@ -999,7 +999,7 @@ func (v Value) MapKeys() []Value {
        if m != 0 {
                mlen = maplen(m)
        }
-       it := mapiterinit(m)
+       it := mapiterinit(iv.typ.runtimeType(), m)
        a := make([]Value, mlen)
        var i int
        for i = 0; i < len(a); i++ {
@@ -1309,7 +1309,7 @@ func (v Value) SetMapIndex(key, val Value) {
                ival = convertForAssignment("reflect.Value.SetMapIndex", nil, iv.typ.Elem(), ival)
        }
 
-       mapassign(iv.word, ikey.word, ival.word, ival.kind != Invalid)
+       mapassign(iv.typ.runtimeType(), iv.word, ikey.word, ival.word, ival.kind != Invalid)
 }
 
 // SetUint sets v's underlying value to x.
@@ -1725,9 +1725,9 @@ func chansend(ch iword, val iword, nb bool) bool
 
 func makechan(typ *runtime.Type, size uint32) (ch iword)
 func makemap(t *runtime.Type) iword
-func mapaccess(m iword, key iword) (val iword, ok bool)
-func mapassign(m iword, key, val iword, ok bool)
-func mapiterinit(m iword) *byte
+func mapaccess(t *runtime.Type, m iword, key iword) (val iword, ok bool)
+func mapassign(t *runtime.Type, m iword, key, val iword, ok bool)
+func mapiterinit(t *runtime.Type, m iword) *byte
 func mapiterkey(it *byte) (key iword, ok bool)
 func mapiternext(it *byte)
 func maplen(m iword) int32
index 179a56375b1219f9b145d22c0587122bb67f4c5a..0c0e3e4a2de49553506764705e2253673c89585c 100644 (file)
@@ -690,13 +690,17 @@ hash_indirect(Hmap *h, void *p)
 
 static int32   debug   = 0;
 
-// makemap(key, val *Type, hint uint32) (hmap *map[any]any);
+// makemap(typ *Type, hint uint32) (hmap *map[any]any);
 Hmap*
-runtime·makemap_c(Type *key, Type *val, int64 hint)
+runtime·makemap_c(MapType *typ, int64 hint)
 {
        Hmap *h;
        int32 keyalg, valalg, keysize, valsize, valsize_in_hash;
        void (*data_del)(uint32, void*, void*);
+       Type *key, *val;
+       
+       key = typ->key;
+       val = typ->elem;
 
        if(hint < 0 || (int32)hint != hint)
                runtime·panicstring("makemap: size out of range");
@@ -770,9 +774,9 @@ runtime·makemap_c(Type *key, Type *val, int64 hint)
 
 // makemap(key, val *Type, hint int64) (hmap *map[any]any);
 void
-runtime·makemap(Type *key, Type *val, int64 hint, Hmap *ret)
+runtime·makemap(MapType *typ, int64 hint, Hmap *ret)
 {
-       ret = runtime·makemap_c(key, val, hint);
+       ret = runtime·makemap_c(typ, hint);
        FLUSH(&ret);
 }
 
@@ -781,17 +785,22 @@ runtime·makemap(Type *key, Type *val, int64 hint, Hmap *ret)
 void
 reflect·makemap(MapType *t, Hmap *ret)
 {
-       ret = runtime·makemap_c(t->key, t->elem, 0);
+       ret = runtime·makemap_c(t, 0);
        FLUSH(&ret);
 }
 
 void
-runtime·mapaccess(Hmap *h, byte *ak, byte *av, bool *pres)
+runtime·mapaccess(MapType *t, Hmap *h, byte *ak, byte *av, bool *pres)
 {
        byte *res;
+       Type *elem;
 
-       if(h == nil)
-               runtime·panicstring("lookup in nil map");
+       if(h == nil) {
+               elem = t->elem;
+               runtime·algarray[elem->alg].copy(elem->size, av, nil);
+               *pres = false;
+               return;
+       }
 
        if(runtime·gcwaiting)
                runtime·gosched();
@@ -809,18 +818,20 @@ runtime·mapaccess(Hmap *h, byte *ak, byte *av, bool *pres)
 // mapaccess1(hmap *map[any]any, key any) (val any);
 #pragma textflag 7
 void
-runtime·mapaccess1(Hmap *h, ...)
+runtime·mapaccess1(MapType *t, Hmap *h, ...)
 {
        byte *ak, *av;
        bool pres;
 
-       if(h == nil)
-               runtime·panicstring("lookup in nil map");
-
-       ak = (byte*)&h + h->ko1;
-       av = (byte*)&h + h->vo1;
+       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;
+       }
 
-       runtime·mapaccess(h, ak, av, &pres);
+       runtime·mapaccess(t, h, ak, av, &pres);
 
        if(debug) {
                runtime·prints("runtime.mapaccess1: map=");
@@ -838,18 +849,21 @@ runtime·mapaccess1(Hmap *h, ...)
 // mapaccess2(hmap *map[any]any, key any) (val any, pres bool);
 #pragma textflag 7
 void
-runtime·mapaccess2(Hmap *h, ...)
+runtime·mapaccess2(MapType *t, Hmap *h, ...)
 {
        byte *ak, *av, *ap;
 
-       if(h == nil)
-               runtime·panicstring("lookup in nil map");
-
-       ak = (byte*)&h + h->ko1;
-       av = (byte*)&h + h->vo1;
-       ap = (byte*)&h + h->po1;
+       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;
+       }
 
-       runtime·mapaccess(h, ak, av, ap);
+       runtime·mapaccess(t, h, ak, av, ap);
 
        if(debug) {
                runtime·prints("runtime.mapaccess2: map=");
@@ -865,39 +879,39 @@ runtime·mapaccess2(Hmap *h, ...)
 }
 
 // For reflect:
-//     func mapaccess(h map, key iword) (val iword, pres bool)
+//     func mapaccess(t type, h map, key iword) (val iword, pres bool)
 // where an iword is the same word an interface value would use:
 // the actual data if it fits, or else a pointer to the data.
 void
-reflect·mapaccess(Hmap *h, uintptr key, uintptr val, bool pres)
+reflect·mapaccess(MapType *t, Hmap *h, uintptr key, uintptr val, bool pres)
 {
        byte *ak, *av;
 
-       if(h == nil)
-               runtime·panicstring("lookup in nil map");
-       if(h->keysize <= sizeof(key))
+       if(t->key->size <= sizeof(key))
                ak = (byte*)&key;
        else
                ak = (byte*)key;
        val = 0;
        pres = false;
-       if(h->valsize <= sizeof(val))
+       if(t->elem->size <= sizeof(val))
                av = (byte*)&val;
        else {
-               av = runtime·mal(h->valsize);
+               av = runtime·mal(t->elem->size);
                val = (uintptr)av;
        }
-       runtime·mapaccess(h, ak, av, &pres);
+       runtime·mapaccess(t, h, ak, av, &pres);
        FLUSH(&val);
        FLUSH(&pres);
 }
 
 void
-runtime·mapassign(Hmap *h, byte *ak, byte *av)
+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");
 
@@ -931,10 +945,10 @@ runtime·mapassign(Hmap *h, byte *ak, byte *av)
        }
 }
 
-// mapassign1(hmap *map[any]any, key any, val any);
+// mapassign1(mapType *type, hmap *map[any]any, key any, val any);
 #pragma textflag 7
 void
-runtime·mapassign1(Hmap *h, ...)
+runtime·mapassign1(MapType *t, Hmap *h, ...)
 {
        byte *ak, *av;
 
@@ -944,13 +958,13 @@ runtime·mapassign1(Hmap *h, ...)
        ak = (byte*)&h + h->ko2;
        av = (byte*)&h + h->vo2;
 
-       runtime·mapassign(h, ak, av);
+       runtime·mapassign(t, h, ak, av);
 }
 
-// mapassign2(hmap *map[any]any, key any, val any, pres bool);
+// mapassign2(mapType *type, hmap *map[any]any, key any, val any, pres bool);
 #pragma textflag 7
 void
-runtime·mapassign2(Hmap *h, ...)
+runtime·mapassign2(MapType *t, Hmap *h, ...)
 {
        byte *ak, *av, *ap;
 
@@ -964,7 +978,7 @@ runtime·mapassign2(Hmap *h, ...)
        if(*ap == false)
                av = nil;       // delete
 
-       runtime·mapassign(h, ak, av);
+       runtime·mapassign(t, h, ak, av);
 
        if(debug) {
                runtime·prints("mapassign2: map=");
@@ -976,16 +990,16 @@ runtime·mapassign2(Hmap *h, ...)
 }
 
 // For reflect:
-//     func mapassign(h map, key, val iword, pres bool)
+//     func mapassign(t type h map, key, val iword, pres bool)
 // where an iword is the same word an interface value would use:
 // the actual data if it fits, or else a pointer to the data.
 void
-reflect·mapassign(Hmap *h, uintptr key, uintptr val, bool pres)
+reflect·mapassign(MapType *t, Hmap *h, uintptr key, uintptr val, bool pres)
 {
        byte *ak, *av;
 
        if(h == nil)
-               runtime·panicstring("lookup in nil map");
+               runtime·panicstring("assignment to entry in nil map");
        if(h->keysize <= sizeof(key))
                ak = (byte*)&key;
        else
@@ -996,12 +1010,12 @@ reflect·mapassign(Hmap *h, uintptr key, uintptr val, bool pres)
                av = (byte*)val;
        if(!pres)
                av = nil;
-       runtime·mapassign(h, ak, av);
+       runtime·mapassign(t, h, ak, av);
 }
 
-// mapiterinit(hmap *map[any]any, hiter *any);
+// mapiterinit(mapType *type, hmap *map[any]any, hiter *any);
 void
-runtime·mapiterinit(Hmap *h, struct hash_iter *it)
+runtime·mapiterinit(MapType*, Hmap *h, struct hash_iter *it)
 {
        if(h == nil) {
                it->data = nil;
@@ -1023,11 +1037,11 @@ runtime·mapiterinit(Hmap *h, struct hash_iter *it)
 // For reflect:
 //     func mapiterinit(h map) (it iter)
 void
-reflect·mapiterinit(Hmap *h, struct hash_iter *it)
+reflect·mapiterinit(MapType *t, Hmap *h, struct hash_iter *it)
 {
        it = runtime·mal(sizeof *it);
        FLUSH(&it);
-       runtime·mapiterinit(h, it);
+       runtime·mapiterinit(t, h, it);
 }
 
 // mapiternext(hiter *any);
index 3c503e430b590f69e78e5f380b70c9855888def2..9719c30f01c905145d6aadc070e83bcca62e5bf5 100644 (file)
@@ -62,6 +62,7 @@ typedef       struct  Iface           Iface;
 typedef        struct  Itab            Itab;
 typedef        struct  Eface           Eface;
 typedef        struct  Type            Type;
+typedef        struct  MapType         MapType;
 typedef        struct  Defer           Defer;
 typedef        struct  Panic           Panic;
 typedef        struct  Hmap            Hmap;
@@ -616,12 +617,12 @@ int32     runtime·gomaxprocsfunc(int32 n);
 void   runtime·procyield(uint32);
 void   runtime·osyield(void);
 
-void   runtime·mapassign(Hmap*, byte*, byte*);
-void   runtime·mapaccess(Hmap*, byte*, byte*, bool*);
+void   runtime·mapassign(MapType*, Hmap*, byte*, byte*);
+void   runtime·mapaccess(MapType*, Hmap*, byte*, byte*, bool*);
 void   runtime·mapiternext(struct hash_iter*);
 bool   runtime·mapiterkey(struct hash_iter*, void*);
 void   runtime·mapiterkeyvalue(struct hash_iter*, void*, void*);
-Hmap*  runtime·makemap_c(Type*, Type*, int64);
+Hmap*  runtime·makemap_c(MapType*, int64);
 
 Hchan* runtime·makechan_c(Type*, int64);
 void   runtime·chansend(Hchan*, void*, bool*);
index 1adb6dc2e7345f7a34d28f746f0bcd1730d74ae1..d4067556de87a9ddcf1fe7fe26c3d9311d66305a 100644 (file)
@@ -16,7 +16,6 @@ typedef struct UncommonType UncommonType;
 typedef struct InterfaceType InterfaceType;
 typedef struct Method Method;
 typedef struct IMethod IMethod;
-typedef struct MapType MapType;
 typedef struct ChanType ChanType;
 typedef struct SliceType SliceType;
 typedef struct FuncType FuncType;