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

gc: implement nil map support

The spec has defined nil maps this way for months.
I'm behind.

R=ken2
CC=golang-dev
https://golang.org/cl/4901052
This commit is contained in:
Russ Cox 2011-08-17 14:56:27 -04:00
parent cf79411b1d
commit 65bde087ae
8 changed files with 88 additions and 74 deletions

View File

@ -57,12 +57,12 @@ char *runtimeimport =
"func \"\".efaceeq (i1 any, i2 any) bool\n" "func \"\".efaceeq (i1 any, i2 any) bool\n"
"func \"\".ifacethash (i1 any) uint32\n" "func \"\".ifacethash (i1 any) uint32\n"
"func \"\".efacethash (i1 any) uint32\n" "func \"\".efacethash (i1 any) uint32\n"
"func \"\".makemap (key *uint8, val *uint8, hint int64) map[any] any\n" "func \"\".makemap (mapType *uint8, hint int64) map[any] any\n"
"func \"\".mapaccess1 (hmap map[any] any, key any) any\n" "func \"\".mapaccess1 (mapType *uint8, hmap map[any] any, key any) any\n"
"func \"\".mapaccess2 (hmap map[any] any, key any) (val any, pres bool)\n" "func \"\".mapaccess2 (mapType *uint8, hmap map[any] any, key any) (val any, pres bool)\n"
"func \"\".mapassign1 (hmap map[any] any, key any, val any)\n" "func \"\".mapassign1 (mapType *uint8, hmap map[any] any, key any, val any)\n"
"func \"\".mapassign2 (hmap map[any] any, key any, val any, pres bool)\n" "func \"\".mapassign2 (mapType *uint8, hmap map[any] any, key any, val any, pres bool)\n"
"func \"\".mapiterinit (hmap map[any] any, hiter *any)\n" "func \"\".mapiterinit (mapType *uint8, hmap map[any] any, hiter *any)\n"
"func \"\".mapiternext (hiter *any)\n" "func \"\".mapiternext (hiter *any)\n"
"func \"\".mapiter1 (hiter *any) any\n" "func \"\".mapiter1 (hiter *any) any\n"
"func \"\".mapiter2 (hiter *any) (key any, val any)\n" "func \"\".mapiter2 (hiter *any) (key any, val any)\n"

View File

@ -175,7 +175,7 @@ walkrange(Node *n)
argtype(fn, t->down); argtype(fn, t->down);
argtype(fn, t->type); argtype(fn, t->type);
argtype(fn, th); 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()); n->ntest = nod(ONE, nod(OINDEX, hit, nodintconst(0)), nodnil());
fn = syslook("mapiternext", 1); fn = syslook("mapiternext", 1);

View File

@ -80,12 +80,12 @@ func ifacethash(i1 any) (ret uint32)
func efacethash(i1 any) (ret uint32) func efacethash(i1 any) (ret uint32)
// *byte is really *runtime.Type // *byte is really *runtime.Type
func makemap(key, val *byte, hint int64) (hmap map[any]any) func makemap(mapType *byte, hint int64) (hmap map[any]any)
func mapaccess1(hmap map[any]any, key any) (val any) func mapaccess1(mapType *byte, hmap map[any]any, key any) (val any)
func mapaccess2(hmap map[any]any, key any) (val any, pres bool) func mapaccess2(mapType *byte, hmap map[any]any, key any) (val any, pres bool)
func mapassign1(hmap map[any]any, key any, val any) func mapassign1(mapType *byte, hmap map[any]any, key any, val any)
func mapassign2(hmap map[any]any, key any, val any, pres bool) func mapassign2(mapType *byte, hmap map[any]any, key any, val any, pres bool)
func mapiterinit(hmap map[any]any, hiter *any) func mapiterinit(mapType *byte, hmap map[any]any, hiter *any)
func mapiternext(hiter *any) func mapiternext(hiter *any)
func mapiter1(hiter *any) (key any) func mapiter1(hiter *any) (key any)
func mapiter2(hiter *any) (key any, val any) func mapiter2(hiter *any) (key any, val any)

View File

@ -604,7 +604,7 @@ walkexpr(Node **np, NodeList **init)
walkexprlistsafe(n->list, init); walkexprlistsafe(n->list, init);
walkexpr(&r->left, init); walkexpr(&r->left, init);
fn = mapfn("mapaccess2", r->left->type); 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->rlist = list1(r);
n->op = OAS2FUNC; n->op = OAS2FUNC;
goto as2func; goto as2func;
@ -617,7 +617,7 @@ walkexpr(Node **np, NodeList **init)
walkexprlistsafe(n->list, init); walkexprlistsafe(n->list, init);
l = n->list->n; l = n->list->n;
t = l->left->type; 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; goto ret;
case OAS2DOTTYPE: case OAS2DOTTYPE:
@ -852,7 +852,7 @@ walkexpr(Node **np, NodeList **init)
goto ret; goto ret;
t = n->left->type; 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; goto ret;
case ORECV: case ORECV:
@ -1090,8 +1090,7 @@ walkexpr(Node **np, NodeList **init)
argtype(fn, t->type); // any-2 argtype(fn, t->type); // any-2
n = mkcall1(fn, n->type, init, n = mkcall1(fn, n->type, init,
typename(t->down), // key type typename(n->type),
typename(t->type), // value type
conv(n->left, types[TINT64])); conv(n->left, types[TINT64]));
goto ret; goto ret;
@ -1697,6 +1696,7 @@ convas(Node *n, NodeList **init)
if(n->left->op == OINDEXMAP) { if(n->left->op == OINDEXMAP) {
n = mkcall1(mapfn("mapassign1", n->left->left->type), T, init, n = mkcall1(mapfn("mapassign1", n->left->left->type), T, init,
typename(n->left->left->type),
n->left->left, n->left->right, n->right); n->left->left, n->left->right, n->right);
goto out; goto out;
} }

View File

@ -977,7 +977,7 @@ func (v Value) MapIndex(key Value) Value {
flag := (iv.flag | ikey.flag) & flagRO flag := (iv.flag | ikey.flag) & flagRO
elemType := typ.Elem() elemType := typ.Elem()
elemWord, ok := mapaccess(iv.word, ikey.word) elemWord, ok := mapaccess(typ.runtimeType(), iv.word, ikey.word)
if !ok { if !ok {
return Value{} return Value{}
} }
@ -999,7 +999,7 @@ func (v Value) MapKeys() []Value {
if m != 0 { if m != 0 {
mlen = maplen(m) mlen = maplen(m)
} }
it := mapiterinit(m) it := mapiterinit(iv.typ.runtimeType(), m)
a := make([]Value, mlen) a := make([]Value, mlen)
var i int var i int
for i = 0; i < len(a); i++ { 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) 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. // 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 makechan(typ *runtime.Type, size uint32) (ch iword)
func makemap(t *runtime.Type) iword func makemap(t *runtime.Type) iword
func mapaccess(m iword, key iword) (val iword, ok bool) func mapaccess(t *runtime.Type, m iword, key iword) (val iword, ok bool)
func mapassign(m iword, key, val iword, ok bool) func mapassign(t *runtime.Type, m iword, key, val iword, ok bool)
func mapiterinit(m iword) *byte func mapiterinit(t *runtime.Type, m iword) *byte
func mapiterkey(it *byte) (key iword, ok bool) func mapiterkey(it *byte) (key iword, ok bool)
func mapiternext(it *byte) func mapiternext(it *byte)
func maplen(m iword) int32 func maplen(m iword) int32

View File

@ -690,13 +690,17 @@ hash_indirect(Hmap *h, void *p)
static int32 debug = 0; static int32 debug = 0;
// makemap(key, val *Type, hint uint32) (hmap *map[any]any); // makemap(typ *Type, hint uint32) (hmap *map[any]any);
Hmap* Hmap*
runtime·makemap_c(Type *key, Type *val, int64 hint) runtime·makemap_c(MapType *typ, int64 hint)
{ {
Hmap *h; Hmap *h;
int32 keyalg, valalg, keysize, valsize, valsize_in_hash; int32 keyalg, valalg, keysize, valsize, valsize_in_hash;
void (*data_del)(uint32, void*, void*); void (*data_del)(uint32, void*, void*);
Type *key, *val;
key = typ->key;
val = typ->elem;
if(hint < 0 || (int32)hint != hint) if(hint < 0 || (int32)hint != hint)
runtime·panicstring("makemap: size out of range"); runtime·panicstring("makemap: size out of range");
@ -770,9 +774,9 @@ runtime·makemap_c(Type *key, Type *val, int64 hint)
// makemap(key, val *Type, hint int64) (hmap *map[any]any); // makemap(key, val *Type, hint int64) (hmap *map[any]any);
void 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); FLUSH(&ret);
} }
@ -781,17 +785,22 @@ runtime·makemap(Type *key, Type *val, int64 hint, Hmap *ret)
void void
reflect·makemap(MapType *t, Hmap *ret) reflect·makemap(MapType *t, Hmap *ret)
{ {
ret = runtime·makemap_c(t->key, t->elem, 0); ret = runtime·makemap_c(t, 0);
FLUSH(&ret); FLUSH(&ret);
} }
void 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; byte *res;
Type *elem;
if(h == nil) if(h == nil) {
runtime·panicstring("lookup in nil map"); elem = t->elem;
runtime·algarray[elem->alg].copy(elem->size, av, nil);
*pres = false;
return;
}
if(runtime·gcwaiting) if(runtime·gcwaiting)
runtime·gosched(); 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); // mapaccess1(hmap *map[any]any, key any) (val any);
#pragma textflag 7 #pragma textflag 7
void void
runtime·mapaccess1(Hmap *h, ...) runtime·mapaccess1(MapType *t, Hmap *h, ...)
{ {
byte *ak, *av; byte *ak, *av;
bool pres; bool pres;
if(h == nil) if(h == nil) {
runtime·panicstring("lookup in nil map"); 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 + h->ko1; runtime·mapaccess(t, h, ak, av, &pres);
av = (byte*)&h + h->vo1;
runtime·mapaccess(h, ak, av, &pres);
if(debug) { if(debug) {
runtime·prints("runtime.mapaccess1: map="); runtime·prints("runtime.mapaccess1: map=");
@ -838,18 +849,21 @@ runtime·mapaccess1(Hmap *h, ...)
// mapaccess2(hmap *map[any]any, key any) (val any, pres bool); // mapaccess2(hmap *map[any]any, key any) (val any, pres bool);
#pragma textflag 7 #pragma textflag 7
void void
runtime·mapaccess2(Hmap *h, ...) runtime·mapaccess2(MapType *t, Hmap *h, ...)
{ {
byte *ak, *av, *ap; byte *ak, *av, *ap;
if(h == nil) if(h == nil) {
runtime·panicstring("lookup in nil map"); 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 + h->ko1; runtime·mapaccess(t, h, ak, av, ap);
av = (byte*)&h + h->vo1;
ap = (byte*)&h + h->po1;
runtime·mapaccess(h, ak, av, ap);
if(debug) { if(debug) {
runtime·prints("runtime.mapaccess2: map="); runtime·prints("runtime.mapaccess2: map=");
@ -865,39 +879,39 @@ runtime·mapaccess2(Hmap *h, ...)
} }
// For reflect: // 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: // 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. // the actual data if it fits, or else a pointer to the data.
void 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; byte *ak, *av;
if(h == nil) if(t->key->size <= sizeof(key))
runtime·panicstring("lookup in nil map");
if(h->keysize <= sizeof(key))
ak = (byte*)&key; ak = (byte*)&key;
else else
ak = (byte*)key; ak = (byte*)key;
val = 0; val = 0;
pres = false; pres = false;
if(h->valsize <= sizeof(val)) if(t->elem->size <= sizeof(val))
av = (byte*)&val; av = (byte*)&val;
else { else {
av = runtime·mal(h->valsize); av = runtime·mal(t->elem->size);
val = (uintptr)av; val = (uintptr)av;
} }
runtime·mapaccess(h, ak, av, &pres); runtime·mapaccess(t, h, ak, av, &pres);
FLUSH(&val); FLUSH(&val);
FLUSH(&pres); FLUSH(&pres);
} }
void void
runtime·mapassign(Hmap *h, byte *ak, byte *av) runtime·mapassign(MapType *t, Hmap *h, byte *ak, byte *av)
{ {
byte *res; byte *res;
int32 hit; int32 hit;
USED(t);
if(h == nil) if(h == nil)
runtime·panicstring("assignment to entry in nil map"); runtime·panicstring("assignment to entry in nil map");
@ -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 #pragma textflag 7
void void
runtime·mapassign1(Hmap *h, ...) runtime·mapassign1(MapType *t, Hmap *h, ...)
{ {
byte *ak, *av; byte *ak, *av;
@ -944,13 +958,13 @@ runtime·mapassign1(Hmap *h, ...)
ak = (byte*)&h + h->ko2; ak = (byte*)&h + h->ko2;
av = (byte*)&h + h->vo2; 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 #pragma textflag 7
void void
runtime·mapassign2(Hmap *h, ...) runtime·mapassign2(MapType *t, Hmap *h, ...)
{ {
byte *ak, *av, *ap; byte *ak, *av, *ap;
@ -964,7 +978,7 @@ runtime·mapassign2(Hmap *h, ...)
if(*ap == false) if(*ap == false)
av = nil; // delete av = nil; // delete
runtime·mapassign(h, ak, av); runtime·mapassign(t, h, ak, av);
if(debug) { if(debug) {
runtime·prints("mapassign2: map="); runtime·prints("mapassign2: map=");
@ -976,16 +990,16 @@ runtime·mapassign2(Hmap *h, ...)
} }
// For reflect: // 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: // 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. // the actual data if it fits, or else a pointer to the data.
void 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; byte *ak, *av;
if(h == nil) if(h == nil)
runtime·panicstring("lookup in nil map"); runtime·panicstring("assignment to entry in nil map");
if(h->keysize <= sizeof(key)) if(h->keysize <= sizeof(key))
ak = (byte*)&key; ak = (byte*)&key;
else else
@ -996,12 +1010,12 @@ reflect·mapassign(Hmap *h, uintptr key, uintptr val, bool pres)
av = (byte*)val; av = (byte*)val;
if(!pres) if(!pres)
av = nil; 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 void
runtime·mapiterinit(Hmap *h, struct hash_iter *it) runtime·mapiterinit(MapType*, Hmap *h, struct hash_iter *it)
{ {
if(h == nil) { if(h == nil) {
it->data = nil; it->data = nil;
@ -1023,11 +1037,11 @@ runtime·mapiterinit(Hmap *h, struct hash_iter *it)
// For reflect: // For reflect:
// func mapiterinit(h map) (it iter) // func mapiterinit(h map) (it iter)
void void
reflect·mapiterinit(Hmap *h, struct hash_iter *it) reflect·mapiterinit(MapType *t, Hmap *h, struct hash_iter *it)
{ {
it = runtime·mal(sizeof *it); it = runtime·mal(sizeof *it);
FLUSH(&it); FLUSH(&it);
runtime·mapiterinit(h, it); runtime·mapiterinit(t, h, it);
} }
// mapiternext(hiter *any); // mapiternext(hiter *any);

View File

@ -62,6 +62,7 @@ typedef struct Iface Iface;
typedef struct Itab Itab; typedef struct Itab Itab;
typedef struct Eface Eface; typedef struct Eface Eface;
typedef struct Type Type; typedef struct Type Type;
typedef struct MapType MapType;
typedef struct Defer Defer; typedef struct Defer Defer;
typedef struct Panic Panic; typedef struct Panic Panic;
typedef struct Hmap Hmap; typedef struct Hmap Hmap;
@ -616,12 +617,12 @@ int32 runtime·gomaxprocsfunc(int32 n);
void runtime·procyield(uint32); void runtime·procyield(uint32);
void runtime·osyield(void); void runtime·osyield(void);
void runtime·mapassign(Hmap*, byte*, byte*); void runtime·mapassign(MapType*, Hmap*, byte*, byte*);
void runtime·mapaccess(Hmap*, byte*, byte*, bool*); void runtime·mapaccess(MapType*, Hmap*, byte*, byte*, bool*);
void runtime·mapiternext(struct hash_iter*); void runtime·mapiternext(struct hash_iter*);
bool runtime·mapiterkey(struct hash_iter*, void*); bool runtime·mapiterkey(struct hash_iter*, void*);
void runtime·mapiterkeyvalue(struct hash_iter*, void*, 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); Hchan* runtime·makechan_c(Type*, int64);
void runtime·chansend(Hchan*, void*, bool*); void runtime·chansend(Hchan*, void*, bool*);

View File

@ -16,7 +16,6 @@ typedef struct UncommonType UncommonType;
typedef struct InterfaceType InterfaceType; typedef struct InterfaceType InterfaceType;
typedef struct Method Method; typedef struct Method Method;
typedef struct IMethod IMethod; typedef struct IMethod IMethod;
typedef struct MapType MapType;
typedef struct ChanType ChanType; typedef struct ChanType ChanType;
typedef struct SliceType SliceType; typedef struct SliceType SliceType;
typedef struct FuncType FuncType; typedef struct FuncType FuncType;