Commit fb3ed166 authored by Keith Randall's avatar Keith Randall

runtime: fix gdb printing of maps

Fixes #5098

R=minux.ma, bradfitz, khr, rsc
CC=golang-dev
https://golang.org/cl/7746045
parent c1786a9e
...@@ -1130,14 +1130,24 @@ mkinternaltypename(char *base, char *arg1, char *arg2) ...@@ -1130,14 +1130,24 @@ mkinternaltypename(char *base, char *arg1, char *arg2)
return n; return n;
} }
// synthesizemaptypes is way too closely married to runtime/hashmap.c
enum {
MaxKeySize = 128,
MaxValSize = 128,
BucketSize = 8,
};
static void static void
synthesizemaptypes(DWDie *die) synthesizemaptypes(DWDie *die)
{ {
DWDie *hash, *dwh, *keytype, *valtype; DWDie *hash, *bucket, *dwh, *dwhk, *dwhv, *dwhb, *keytype, *valtype, *fld;
int indirect_key, indirect_val;
int keysize, valsize;
DWAttr *a;
hash = defgotype(lookup_or_diag("type.runtime.hmap")); hash = walktypedef(defgotype(lookup_or_diag("type.runtime.hmap")));
bucket = walktypedef(defgotype(lookup_or_diag("type.runtime.bucket")));
if (hash == nil) if (hash == nil)
return; return;
...@@ -1146,8 +1156,59 @@ synthesizemaptypes(DWDie *die) ...@@ -1146,8 +1156,59 @@ synthesizemaptypes(DWDie *die)
if (die->abbrev != DW_ABRV_MAPTYPE) if (die->abbrev != DW_ABRV_MAPTYPE)
continue; continue;
keytype = (DWDie*) getattr(die, DW_AT_internal_key_type)->data; keytype = walktypedef((DWDie*) getattr(die, DW_AT_internal_key_type)->data);
valtype = (DWDie*) getattr(die, DW_AT_internal_val_type)->data; valtype = walktypedef((DWDie*) getattr(die, DW_AT_internal_val_type)->data);
// compute size info like hashmap.c does.
a = getattr(keytype, DW_AT_byte_size);
keysize = a ? a->value : PtrSize; // We don't store size with Pointers
a = getattr(valtype, DW_AT_byte_size);
valsize = a ? a->value : PtrSize;
indirect_key = 0;
indirect_val = 0;
if(keysize > MaxKeySize) {
keysize = PtrSize;
indirect_key = 1;
}
if(valsize > MaxValSize) {
valsize = PtrSize;
indirect_val = 1;
}
// Construct type to represent an array of BucketSize keys
dwhk = newdie(&dwtypes, DW_ABRV_ARRAYTYPE,
mkinternaltypename("[]key",
getattr(keytype, DW_AT_name)->data, nil));
newattr(dwhk, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize * keysize, 0);
newrefattr(dwhk, DW_AT_type, indirect_key ? defptrto(keytype) : keytype);
fld = newdie(dwhk, DW_ABRV_ARRAYRANGE, "size");
newattr(fld, DW_AT_upper_bound, DW_CLS_CONSTANT, BucketSize, 0);
newrefattr(fld, DW_AT_type, find_or_diag(&dwtypes, "uintptr"));
// Construct type to represent an array of BucketSize values
dwhv = newdie(&dwtypes, DW_ABRV_ARRAYTYPE,
mkinternaltypename("[]val",
getattr(valtype, DW_AT_name)->data, nil));
newattr(dwhv, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize * valsize, 0);
newrefattr(dwhv, DW_AT_type, indirect_val ? defptrto(valtype) : valtype);
fld = newdie(dwhv, DW_ABRV_ARRAYRANGE, "size");
newattr(fld, DW_AT_upper_bound, DW_CLS_CONSTANT, BucketSize, 0);
newrefattr(fld, DW_AT_type, find_or_diag(&dwtypes, "uintptr"));
// Construct bucket<K,V>
dwhb = newdie(&dwtypes, DW_ABRV_STRUCTTYPE,
mkinternaltypename("bucket",
getattr(keytype, DW_AT_name)->data,
getattr(valtype, DW_AT_name)->data));
copychildren(dwhb, bucket);
fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "keys");
newrefattr(fld, DW_AT_type, dwhk);
newmemberoffsetattr(fld, BucketSize + PtrSize);
fld = newdie(dwhb, DW_ABRV_STRUCTFIELD, "values");
newrefattr(fld, DW_AT_type, dwhv);
newmemberoffsetattr(fld, BucketSize + PtrSize + BucketSize * keysize);
newattr(dwhb, DW_AT_byte_size, DW_CLS_CONSTANT, BucketSize + PtrSize + BucketSize * keysize + BucketSize * valsize, 0);
substitutetype(dwhb, "overflow", defptrto(dwhb));
// Construct hash<K,V> // Construct hash<K,V>
dwh = newdie(&dwtypes, DW_ABRV_STRUCTTYPE, dwh = newdie(&dwtypes, DW_ABRV_STRUCTTYPE,
...@@ -1155,9 +1216,12 @@ synthesizemaptypes(DWDie *die) ...@@ -1155,9 +1216,12 @@ synthesizemaptypes(DWDie *die)
getattr(keytype, DW_AT_name)->data, getattr(keytype, DW_AT_name)->data,
getattr(valtype, DW_AT_name)->data)); getattr(valtype, DW_AT_name)->data));
copychildren(dwh, hash); copychildren(dwh, hash);
substitutetype(dwh, "buckets", defptrto(dwhb));
substitutetype(dwh, "oldbuckets", defptrto(dwhb));
newattr(dwh, DW_AT_byte_size, DW_CLS_CONSTANT, newattr(dwh, DW_AT_byte_size, DW_CLS_CONSTANT,
getattr(hash, DW_AT_byte_size)->value, nil); getattr(hash, DW_AT_byte_size)->value, nil);
// make map type a pointer to hash<K,V>
newrefattr(die, DW_AT_type, defptrto(dwh)); newrefattr(die, DW_AT_type, defptrto(dwh));
} }
} }
......
...@@ -222,7 +222,7 @@ hash_init(MapType *t, Hmap *h, uint32 hint) ...@@ -222,7 +222,7 @@ hash_init(MapType *t, Hmap *h, uint32 hint)
keysize = sizeof(byte*); keysize = sizeof(byte*);
} }
valuesize = t->elem->size; valuesize = t->elem->size;
if(valuesize >= MAXVALUESIZE) { if(valuesize > MAXVALUESIZE) {
flags |= IndirectValue; flags |= IndirectValue;
valuesize = sizeof(byte*); valuesize = sizeof(byte*);
} }
......
...@@ -84,26 +84,35 @@ class MapTypePrinter: ...@@ -84,26 +84,35 @@ class MapTypePrinter:
return str(self.val.type) return str(self.val.type)
def children(self): def children(self):
stab = self.val['st'] B = self.val['b']
i = 0 buckets = self.val['buckets']
for v in self.traverse_hash(stab): oldbuckets = self.val['oldbuckets']
yield ("[%d]" % i, v['key']) flags = self.val['flags']
yield ("[%d]" % (i + 1), v['val']) inttype = self.val['hash0'].type
i += 2 cnt = 0
for bucket in xrange(2 ** B):
def traverse_hash(self, stab): bp = buckets + bucket
ptr = stab['entry'].address if oldbuckets:
last = stab['last'] oldbucket = bucket & (2 ** (B - 1) - 1)
while ptr <= last: oldbp = oldbuckets + oldbucket
v = ptr.dereference() oldb = oldbp.dereference()
ptr = ptr + 1 if (oldb['overflow'].cast(inttype) & 1) == 0: # old bucket not evacuated yet
if v['hash'] == 0: continue if bucket >= 2 ** (B - 1): continue # already did old bucket
if v['hash'] & 63 == 63: # subtable bp = oldbp
for v in self.traverse_hash(v['key'].cast(self.val['st'].type)): while bp:
yield v b = bp.dereference()
else: for i in xrange(8):
yield v if b['tophash'][i] != 0:
k = b['keys'][i]
v = b['values'][i]
if flags & 1:
k = k.dereference()
if flags & 2:
v = v.dereference()
yield '%d' % cnt, k
yield '%d' % (cnt + 1), v
cnt += 2
bp = b['overflow']
class ChanTypePrinter: class ChanTypePrinter:
"""Pretty print chan[T] types. """Pretty print chan[T] types.
......
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