mirror of
https://github.com/golang/go
synced 2024-11-22 03:14:41 -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:
parent
cf79411b1d
commit
65bde087ae
@ -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");
|
||||
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 + 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");
|
||||
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 + 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;
|
||||
|
Loading…
Reference in New Issue
Block a user