Commit cbc565a8 authored by Keith Randall's avatar Keith Randall

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
parent c9f12d22
...@@ -56,7 +56,7 @@ func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value { ...@@ -56,7 +56,7 @@ func MakeFunc(typ Type, fn func(args []Value) (results []Value)) Value {
impl := &makeFuncImpl{code: code, typ: ftyp, fn: fn} 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 // makeFuncStub is an assembly function that is the code half of
...@@ -87,7 +87,7 @@ func makeMethodValue(op string, v Value) Value { ...@@ -87,7 +87,7 @@ func makeMethodValue(op string, v Value) Value {
// Ignoring the flagMethod bit, v describes the receiver, not the method type. // Ignoring the flagMethod bit, v describes the receiver, not the method type.
fl := v.flag & (flagRO | flagAddr | flagIndir) fl := v.flag & (flagRO | flagAddr | flagIndir)
fl |= flag(v.typ.Kind()) << flagKindShift 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. // v.Type returns the actual type of the method value.
funcType := v.Type().(*rtype) funcType := v.Type().(*rtype)
...@@ -109,7 +109,7 @@ func makeMethodValue(op string, v Value) Value { ...@@ -109,7 +109,7 @@ func makeMethodValue(op string, v Value) Value {
// but we want Interface() and other operations to fail early. // but we want Interface() and other operations to fail early.
methodReceiver(op, fv.rcvr, fv.method) 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 // methodValueCall is an assembly function that is the code half of
......
...@@ -478,6 +478,8 @@ func (t *rtype) FieldAlign() int { return int(t.fieldAlign) } ...@@ -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) 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 *rtype) common() *rtype { return t }
func (t *uncommonType) Method(i int) (m Method) { func (t *uncommonType) Method(i int) (m Method) {
...@@ -496,7 +498,7 @@ func (t *uncommonType) Method(i int) (m Method) { ...@@ -496,7 +498,7 @@ func (t *uncommonType) Method(i int) (m Method) {
mt := p.typ mt := p.typ
m.Type = mt m.Type = mt
fn := unsafe.Pointer(&p.tfn) fn := unsafe.Pointer(&p.tfn)
m.Func = Value{mt, fn, fl} m.Func = Value{mt, fn, 0, fl}
m.Index = i m.Index = i
return return
} }
......
This diff is collapsed.
...@@ -1060,40 +1060,16 @@ runtime·mapaccess2(MapType *t, Hmap *h, byte *ak, byte *av, bool pres) ...@@ -1060,40 +1060,16 @@ runtime·mapaccess2(MapType *t, Hmap *h, byte *ak, byte *av, bool pres)
} }
// For reflect: // For reflect:
// func mapaccess(t type, h map, key iword) (val iword, pres bool) // func mapaccess(t type, h map, key unsafe.Pointer) (val unsafe.Pointer)
// 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 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); runtime·racereadpc(h, runtime·getcallerpc(&t), reflect·mapaccess);
runtime·racereadrangepc(key, t->key->size, 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;
} }
val = hash_lookup(t, h, &key);
FLUSH(&val); FLUSH(&val);
FLUSH(&pres);
} }
// mapassign1(mapType *type, hmap *map[any]any, key *any, val *any); // mapassign1(mapType *type, hmap *map[any]any, key *any, val *any);
...@@ -1148,51 +1124,51 @@ runtime·mapdelete(MapType *t, Hmap *h, byte *ak) ...@@ -1148,51 +1124,51 @@ runtime·mapdelete(MapType *t, Hmap *h, byte *ak)
} }
// For reflect: // For reflect:
// func mapassign(t type h map, key, val iword, pres bool) // func mapassign(t type h map, key, val unsafe.Pointer)
// 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 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) if(h == nil)
runtime·panicstring("assignment to entry in nil map"); runtime·panicstring("assignment to entry in nil map");
if(raceenabled) if(raceenabled) {
runtime·racewritepc(h, runtime·getcallerpc(&t), reflect·mapassign); runtime·racewritepc(h, runtime·getcallerpc(&t), reflect·mapassign);
if(t->key->size <= sizeof(key)) runtime·racereadrangepc(key, t->key->size, runtime·getcallerpc(&t), reflect·mapassign);
ak = (byte*)&key; runtime·racereadrangepc(val, t->elem->size, runtime·getcallerpc(&t), reflect·mapassign);
else }
ak = (byte*)key;
if(!pres) { hash_insert(t, h, key, val);
hash_remove(t, h, ak);
if(debug) { if(debug) {
runtime·prints("mapassign: map="); runtime·prints("mapassign: map=");
runtime·printpointer(h); runtime·printpointer(h);
runtime·prints("; key="); runtime·prints("; key=");
t->key->alg->print(t->key->size, ak); t->key->alg->print(t->key->size, key);
runtime·prints("; val=nil"); runtime·prints("; val=");
t->elem->alg->print(t->elem->size, val);
runtime·prints("\n"); runtime·prints("\n");
} }
} else { }
if(t->elem->size <= sizeof(val))
av = (byte*)&val;
else
av = (byte*)val;
hash_insert(t, h, ak, av); // 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) { if(debug) {
runtime·prints("mapassign: map="); runtime·prints("mapdelete: map=");
runtime·printpointer(h); runtime·printpointer(h);
runtime·prints("; key="); runtime·prints("; key=");
t->key->alg->print(t->key->size, ak); t->key->alg->print(t->key->size, key);
runtime·prints("; val=");
t->elem->alg->print(t->elem->size, av);
runtime·prints("\n"); runtime·prints("\n");
} }
}
} }
// mapiterinit(mapType *type, hmap *map[any]any, hiter *any); // mapiterinit(mapType *type, hmap *map[any]any, hiter *any);
...@@ -1254,34 +1230,12 @@ reflect·mapiternext(struct hash_iter *it) ...@@ -1254,34 +1230,12 @@ reflect·mapiternext(struct hash_iter *it)
} }
// For reflect: // For reflect:
// func mapiterkey(h map) (key iword, ok bool) // func mapiterkey(h map) (key unsafe.Pointer)
// 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 void
reflect·mapiterkey(struct hash_iter *it, uintptr key, bool ok) reflect·mapiterkey(struct hash_iter *it, byte *key)
{ {
byte *res, *r; key = it->key;
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;
}
FLUSH(&key); FLUSH(&key);
FLUSH(&ok);
} }
// For reflect: // For reflect:
......
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