From: Keith Randall Date: Tue, 13 Aug 2013 19:36:03 +0000 (-0700) Subject: runtime: tell GC not to scan internal hashmap structures. X-Git-Tag: go1.2rc2~614 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=0df438c683d7a2b8acb47d767ff37c3b22c1b61d;p=gostls13.git runtime: tell GC not to scan internal hashmap structures. We'll do it ourselves via hash_gciter, thanks. Fixes bug 6119. R=golang-dev, dvyukov, cookieo9, rsc CC=golang-dev https://golang.org/cl/12840043 --- diff --git a/src/pkg/runtime/hashmap.c b/src/pkg/runtime/hashmap.c index 6b89082931..4af408e20f 100644 --- a/src/pkg/runtime/hashmap.c +++ b/src/pkg/runtime/hashmap.c @@ -259,7 +259,10 @@ hash_init(MapType *t, Hmap *h, uint32 hint) // done lazily later. buckets = nil; } else { - buckets = runtime·mallocgc(bucketsize << B, 0, FlagNoZero); + buckets = runtime·mallocgc(bucketsize << B, 0, FlagNoZero | FlagNoPointers); + // Note: the array really does have pointers, but we tell the gc about + // them explicitly via gciter below. We use FlagNoPointers to prevent + // the gc from scanning the bucket array itself. Fixes issue 6119. for(i = 0; i < (uintptr)1 << B; i++) { b = (Bucket*)(buckets + i * bucketsize); clearbucket(b); @@ -330,7 +333,7 @@ evacuate(MapType *t, Hmap *h, uintptr oldbucket) if((hash & newbit) == 0) { if(xi == BUCKETSIZE) { if(checkgc) mstats.next_gc = mstats.heap_alloc; - newx = runtime·mallocgc(h->bucketsize, 0, FlagNoZero); + newx = runtime·mallocgc(h->bucketsize, 0, FlagNoZero | FlagNoPointers); clearbucket(newx); x->overflow = newx; x = newx; @@ -355,7 +358,7 @@ evacuate(MapType *t, Hmap *h, uintptr oldbucket) } else { if(yi == BUCKETSIZE) { if(checkgc) mstats.next_gc = mstats.heap_alloc; - newy = runtime·mallocgc(h->bucketsize, 0, FlagNoZero); + newy = runtime·mallocgc(h->bucketsize, 0, FlagNoZero | FlagNoPointers); clearbucket(newy); y->overflow = newy; y = newy; @@ -451,7 +454,7 @@ hash_grow(MapType *t, Hmap *h) 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((uintptr)h->bucketsize << (h->B + 1), 0, FlagNoZero); + new_buckets = runtime·mallocgc((uintptr)h->bucketsize << (h->B + 1), 0, FlagNoZero | FlagNoPointers); flags = (h->flags & ~(Iterator | OldIterator)); if((h->flags & Iterator) != 0) { flags |= OldIterator; @@ -615,7 +618,7 @@ hash_insert(MapType *t, Hmap *h, void *key, void *value) hash = h->hash0; t->key->alg->hash(&hash, t->key->size, key); if(h->buckets == nil) { - h->buckets = runtime·mallocgc(h->bucketsize, 0, FlagNoZero); + h->buckets = runtime·mallocgc(h->bucketsize, 0, FlagNoZero | FlagNoPointers); b = (Bucket*)(h->buckets); clearbucket(b); } @@ -665,7 +668,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, FlagNoZero); + newb = runtime·mallocgc(h->bucketsize, 0, FlagNoZero | FlagNoPointers); clearbucket(newb); b->overflow = newb; inserti = newb->tophash;