1
0
mirror of https://github.com/golang/go synced 2024-11-24 02:40:17 -07:00

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
This commit is contained in:
Keith Randall 2013-12-19 15:15:24 -08:00
parent c9f12d2289
commit cbc565a801
4 changed files with 464 additions and 384 deletions

View File

@ -56,7 +56,7 @@ func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value {
impl := &makeFuncImpl{code: code, typ: ftyp, fn: fn}
return Value{t, unsafe.Pointer(impl), flag(Func) << flagKindShift}
return Value{t, unsafe.Pointer(impl), 0, flag(Func) << flagKindShift}
}
// makeFuncStub is an assembly function that is the code half of
@ -87,7 +87,7 @@ func makeMethodValue(op string, v Value) Value {
// Ignoring the flagMethod bit, v describes the receiver, not the method type.
fl := v.flag & (flagRO | flagAddr | flagIndir)
fl |= flag(v.typ.Kind()) << flagKindShift
rcvr := Value{v.typ, v.val, fl}
rcvr := Value{v.typ, v.ptr, v.scalar, fl}
// v.Type returns the actual type of the method value.
funcType := v.Type().(*rtype)
@ -109,7 +109,7 @@ func makeMethodValue(op string, v Value) Value {
// but we want Interface() and other operations to fail early.
methodReceiver(op, fv.rcvr, fv.method)
return Value{funcType, unsafe.Pointer(fv), v.flag&flagRO | flag(Func)<<flagKindShift}
return Value{funcType, unsafe.Pointer(fv), 0, v.flag&flagRO | flag(Func)<<flagKindShift}
}
// methodValueCall is an assembly function that is the code half of

View File

@ -478,6 +478,8 @@ func (t *rtype) FieldAlign() int { return int(t.fieldAlign) }
func (t *rtype) Kind() Kind { return Kind(t.kind & kindMask) }
func (t *rtype) pointers() bool { return t.kind&kindNoPointers == 0 }
func (t *rtype) common() *rtype { return t }
func (t *uncommonType) Method(i int) (m Method) {
@ -496,7 +498,7 @@ func (t *uncommonType) Method(i int) (m Method) {
mt := p.typ
m.Type = mt
fn := unsafe.Pointer(&p.tfn)
m.Func = Value{mt, fn, fl}
m.Func = Value{mt, fn, 0, fl}
m.Index = i
return
}

File diff suppressed because it is too large Load Diff

View File

@ -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: