aboutsummaryrefslogtreecommitdiff
path: root/src/pkg
diff options
context:
space:
mode:
authorJan Ziak <0xe2.0x9a.0x9b@gmail.com>2013-03-25 21:35:46 +0100
committerJan Ziak <0xe2.0x9a.0x9b@gmail.com>2013-03-25 21:35:46 +0100
commitbf1f46180ee348d2d59bebfeda0314450fbcd893 (patch)
tree639e983464a918d289ed041f25f093cb14e486f2 /src/pkg
parentfc4c5b14ef6906f981bf199a78c08942388fc03c (diff)
downloadgo-bf1f46180ee348d2d59bebfeda0314450fbcd893.tar.xz
runtime: optionally check all allocations in hashmap.c
Adds the new debugging constant 'checkgc'. If its value is non-zero all calls to mallocgc() from hashmap.c will start a garbage collection. Fixes #5074. R=golang-dev, khr CC=golang-dev, rsc https://golang.org/cl/7663051
Diffstat (limited to 'src/pkg')
-rw-r--r--src/pkg/runtime/hashmap.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/src/pkg/runtime/hashmap.c b/src/pkg/runtime/hashmap.c
index 0f92becab2..036af5a249 100644
--- a/src/pkg/runtime/hashmap.c
+++ b/src/pkg/runtime/hashmap.c
@@ -126,6 +126,7 @@ enum
{
docheck = 0, // check invariants before and after every op. Slow!!!
debug = 0, // print every operation
+ checkgc = 0 || docheck, // check interaction of mallocgc() with the garbage collector
};
static void
check(MapType *t, Hmap *h)
@@ -253,6 +254,7 @@ hash_init(MapType *t, Hmap *h, uint32 hint)
// allocate initial hash table
// If hint is large zeroing this memory could take a while.
+ if(checkgc) mstats.next_gc = mstats.heap_alloc;
buckets = runtime·mallocgc(bucketsize << B, 0, 1, 0);
for(i = 0; i < (uintptr)1 << B; i++) {
b = (Bucket*)(buckets + i * bucketsize);
@@ -322,6 +324,7 @@ evacuate(MapType *t, Hmap *h, uintptr oldbucket)
// the B'th bit of the hash in this case.
if((hash & newbit) == 0) {
if(xi == BUCKETSIZE) {
+ if(checkgc) mstats.next_gc = mstats.heap_alloc;
newx = runtime·mallocgc(h->bucketsize, 0, 1, 0);
clearbucket(newx);
x->overflow = newx;
@@ -346,6 +349,7 @@ evacuate(MapType *t, Hmap *h, uintptr oldbucket)
xv += h->valuesize;
} else {
if(yi == BUCKETSIZE) {
+ if(checkgc) mstats.next_gc = mstats.heap_alloc;
newy = runtime·mallocgc(h->bucketsize, 0, 1, 0);
clearbucket(newy);
y->overflow = newy;
@@ -441,6 +445,7 @@ hash_grow(MapType *t, Hmap *h)
runtime·throw("evacuation not done in time");
old_buckets = h->buckets;
// NOTE: this could be a big malloc, but since we don't need zeroing it is probably fast.
+ if(checkgc) mstats.next_gc = mstats.heap_alloc;
new_buckets = runtime·mallocgc(h->bucketsize << (h->B + 1), 0, 1, 0);
flags = (h->flags & ~(Iterator | OldIterator));
if((h->flags & Iterator) != 0) {
@@ -611,6 +616,7 @@ hash_insert(MapType *t, Hmap *h, void *key, void *value)
if(inserti == nil) {
// all current buckets are full, allocate a new one.
+ if(checkgc) mstats.next_gc = mstats.heap_alloc;
newb = runtime·mallocgc(h->bucketsize, 0, 1, 0);
clearbucket(newb);
b->overflow = newb;
@@ -621,11 +627,13 @@ hash_insert(MapType *t, Hmap *h, void *key, void *value)
// store new key/value at insert position
if((h->flags & IndirectKey) != 0) {
+ if(checkgc) mstats.next_gc = mstats.heap_alloc;
kmem = runtime·mallocgc(t->key->size, 0, 1, 0);
*(byte**)insertk = kmem;
insertk = kmem;
}
if((h->flags & IndirectValue) != 0) {
+ if(checkgc) mstats.next_gc = mstats.heap_alloc;
vmem = runtime·mallocgc(t->elem->size, 0, 1, 0);
*(byte**)insertv = vmem;
insertv = vmem;