Commit 65bde087 authored by Russ Cox's avatar Russ Cox

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
parent cf79411b
......@@ -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"
......
......@@ -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);
......
......@@ -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)
......
......@@ -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;
}
......
......@@ -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
......
......@@ -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);
......
......@@ -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*);
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment