aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/runtime/hashmap.c
diff options
context:
space:
mode:
authorKeith Randall <khr@golang.org>2013-12-19 15:15:24 -0800
committerKeith Randall <khr@golang.org>2013-12-19 15:15:24 -0800
commitcbc565a80156a4dd4108ef5e1e170602415418a8 (patch)
treec94c69baac3f83acf825384b2dff08fa423ccf98 /src/pkg/runtime/hashmap.c
parentc9f12d2289252d56aa88263c56be217255d95ee5 (diff)
downloadgo-cbc565a80156a4dd4108ef5e1e170602415418a8.tar.xz
reflect: rewrite Value to separate out pointer vs. nonpointer info.
Needed for precise gc and copying stacks. reflect.Value now takes 4 words instead of 3. Still to do: - un-iword-ify channel ops. - un-iword-ify method receivers. R=golang-dev, iant, rsc, khr CC=golang-dev https://golang.org/cl/43040043
Diffstat (limited to 'src/pkg/runtime/hashmap.c')
-rw-r--r--src/pkg/runtime/hashmap.c134
1 files changed, 44 insertions, 90 deletions
diff --git a/src/pkg/runtime/hashmap.c b/src/pkg/runtime/hashmap.c
index e42121b044..5d625c15a8 100644
--- a/src/pkg/runtime/hashmap.c
+++ b/src/pkg/runtime/hashmap.c
@@ -1060,40 +1060,16 @@ runtime·mapaccess2(MapType *t, Hmap *h, byte *ak, byte *av, bool pres)
}
// For reflect:
-// 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.
+// func mapaccess(t type, h map, key unsafe.Pointer) (val unsafe.Pointer)
void
-reflect·mapaccess(MapType *t, Hmap *h, uintptr key, uintptr val, bool pres)
+reflect·mapaccess(MapType *t, Hmap *h, byte *key, byte *val)
{
- byte *ak, *av, *r;
-
- if(raceenabled && h != nil)
+ if(raceenabled && h != nil) {
runtime·racereadpc(h, runtime·getcallerpc(&t), reflect·mapaccess);
-
- if(t->key->size <= sizeof(key))
- ak = (byte*)&key;
- else
- ak = (byte*)key;
-
- av = hash_lookup(t, h, &ak);
- if(av == nil) {
- val = 0;
- pres = false;
- } else {
- if(t->elem->size <= sizeof(val)) {
- val = 0; // clear high-order bits if value is smaller than a word
- t->elem->alg->copy(t->elem->size, &val, av);
- } else {
- // make a copy because reflect can hang on to result indefinitely
- r = runtime·cnew(t->elem);
- t->elem->alg->copy(t->elem->size, r, av);
- val = (uintptr)r;
- }
- pres = true;
+ runtime·racereadrangepc(key, t->key->size, runtime·getcallerpc(&t), reflect·mapaccess);
}
+ val = hash_lookup(t, h, &key);
FLUSH(&val);
- FLUSH(&pres);
}
// mapassign1(mapType *type, hmap *map[any]any, key *any, val *any);
@@ -1148,50 +1124,50 @@ runtime·mapdelete(MapType *t, Hmap *h, byte *ak)
}
// For reflect:
-// 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.
+// func mapassign(t type h map, key, val unsafe.Pointer)
void
-reflect·mapassign(MapType *t, Hmap *h, uintptr key, uintptr val, bool pres)
+reflect·mapassign(MapType *t, Hmap *h, byte *key, byte *val)
{
- byte *ak, *av;
-
if(h == nil)
runtime·panicstring("assignment to entry in nil map");
- if(raceenabled)
+ if(raceenabled) {
runtime·racewritepc(h, runtime·getcallerpc(&t), reflect·mapassign);
- if(t->key->size <= sizeof(key))
- ak = (byte*)&key;
- else
- ak = (byte*)key;
- if(!pres) {
- hash_remove(t, h, ak);
+ runtime·racereadrangepc(key, t->key->size, runtime·getcallerpc(&t), reflect·mapassign);
+ runtime·racereadrangepc(val, t->elem->size, runtime·getcallerpc(&t), reflect·mapassign);
+ }
- if(debug) {
- runtime·prints("mapassign: map=");
- runtime·printpointer(h);
- runtime·prints("; key=");
- t->key->alg->print(t->key->size, ak);
- runtime·prints("; val=nil");
- runtime·prints("\n");
- }
- } else {
- if(t->elem->size <= sizeof(val))
- av = (byte*)&val;
- else
- av = (byte*)val;
+ hash_insert(t, h, key, val);
- hash_insert(t, h, ak, av);
+ if(debug) {
+ runtime·prints("mapassign: map=");
+ runtime·printpointer(h);
+ runtime·prints("; key=");
+ t->key->alg->print(t->key->size, key);
+ runtime·prints("; val=");
+ t->elem->alg->print(t->elem->size, val);
+ runtime·prints("\n");
+ }
+}
- if(debug) {
- runtime·prints("mapassign: map=");
- runtime·printpointer(h);
- runtime·prints("; key=");
- t->key->alg->print(t->key->size, ak);
- runtime·prints("; val=");
- t->elem->alg->print(t->elem->size, av);
- runtime·prints("\n");
- }
+// For reflect:
+// func mapdelete(t type h map, key unsafe.Pointer)
+void
+reflect·mapdelete(MapType *t, Hmap *h, byte *key)
+{
+ if(h == nil)
+ runtime·panicstring("delete from nil map");
+ if(raceenabled) {
+ runtime·racewritepc(h, runtime·getcallerpc(&t), reflect·mapassign);
+ runtime·racereadrangepc(key, t->key->size, runtime·getcallerpc(&t), reflect·mapassign);
+ }
+ hash_remove(t, h, key);
+
+ if(debug) {
+ runtime·prints("mapdelete: map=");
+ runtime·printpointer(h);
+ runtime·prints("; key=");
+ t->key->alg->print(t->key->size, key);
+ runtime·prints("\n");
}
}
@@ -1254,34 +1230,12 @@ reflect·mapiternext(struct hash_iter *it)
}
// For reflect:
-// func mapiterkey(h map) (key iword, ok 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.
+// func mapiterkey(h map) (key unsafe.Pointer)
void
-reflect·mapiterkey(struct hash_iter *it, uintptr key, bool ok)
+reflect·mapiterkey(struct hash_iter *it, byte *key)
{
- byte *res, *r;
- Type *tkey;
-
- res = it->key;
- if(res == nil) {
- key = 0;
- ok = false;
- } else {
- tkey = it->t->key;
- if(tkey->size <= sizeof(key)) {
- key = 0; // clear high-order bits if value is smaller than a word
- tkey->alg->copy(tkey->size, (byte*)&key, res);
- } else {
- // make a copy because reflect can hang on to result indefinitely
- r = runtime·cnew(tkey);
- tkey->alg->copy(tkey->size, r, res);
- key = (uintptr)r;
- }
- ok = true;
- }
+ key = it->key;
FLUSH(&key);
- FLUSH(&ok);
}
// For reflect: