static void __go_map_rehash (struct __go_map *map) { const struct __go_map_descriptor *descriptor; const struct __go_type_descriptor *key_descriptor; uintptr_t key_offset; size_t key_size; size_t (*hashfn) (const void *, size_t); uintptr_t old_bucket_count; void **old_buckets; uintptr_t new_bucket_count; void **new_buckets; uintptr_t i; descriptor = map->__descriptor; key_descriptor = descriptor->__map_descriptor->__key_type; key_offset = descriptor->__key_offset; key_size = key_descriptor->__size; hashfn = key_descriptor->__hashfn; old_bucket_count = map->__bucket_count; old_buckets = map->__buckets; new_bucket_count = __go_map_next_prime (old_bucket_count * 2); new_buckets = (void **) __go_alloc (new_bucket_count * sizeof (void *)); __builtin_memset (new_buckets, 0, new_bucket_count * sizeof (void *)); for (i = 0; i < old_bucket_count; ++i) { char* entry; char* next; for (entry = old_buckets[i]; entry != NULL; entry = next) { size_t key_hash; size_t new_bucket_index; /* We could speed up rehashing at the cost of memory space by caching the hash code. */ key_hash = hashfn (entry + key_offset, key_size); new_bucket_index = key_hash % new_bucket_count; next = *(char **) entry; *(char **) entry = new_buckets[new_bucket_index]; new_buckets[new_bucket_index] = entry; } } __go_free (old_buckets); map->__bucket_count = new_bucket_count; map->__buckets = new_buckets; }
struct __go_map * __go_new_map (const struct __go_map_descriptor *descriptor, uintptr_t entries) { struct __go_map *ret; if ((uintptr_t) (int) entries != entries) __go_panic_msg ("map size out of range"); if (entries == 0) entries = 5; else entries = __go_map_next_prime (entries); ret = (struct __go_map *) __go_alloc (sizeof (struct __go_map)); ret->__descriptor = descriptor; ret->__element_count = 0; ret->__bucket_count = entries; ret->__buckets = (void **) __go_alloc (entries * sizeof (void *)); __builtin_memset (ret->__buckets, 0, entries * sizeof (void *)); return ret; }
struct __go_map * __go_new_map (const struct __go_map_descriptor *descriptor, uintptr_t entries) { int32 ientries; struct __go_map *ret; /* The master library limits map entries to int32, so we do too. */ ientries = (int32) entries; if (ientries < 0 || (uintptr_t) ientries != entries) runtime_panicstring ("map size out of range"); if (entries == 0) entries = 5; else entries = __go_map_next_prime (entries); ret = (struct __go_map *) __go_alloc (sizeof (struct __go_map)); ret->__descriptor = descriptor; ret->__element_count = 0; ret->__bucket_count = entries; ret->__buckets = (void **) __go_alloc (entries * sizeof (void *)); __builtin_memset (ret->__buckets, 0, entries * sizeof (void *)); return ret; }