]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: tell GC not to scan internal hashmap structures.
authorKeith Randall <khr@golang.org>
Tue, 13 Aug 2013 19:36:03 +0000 (12:36 -0700)
committerKeith Randall <khr@golang.org>
Tue, 13 Aug 2013 19:36:03 +0000 (12:36 -0700)
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

src/pkg/runtime/hashmap.c

index 6b89082931f9b68d0236ff95220954c305b04d6c..4af408e20ff778d39b4966f5c9cfa572e36e70f0 100644 (file)
@@ -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;