diff options
author | Dan Albert <danalbert@google.com> | 2016-02-24 13:48:45 -0800 |
---|---|---|
committer | Dan Albert <danalbert@google.com> | 2016-02-24 13:51:18 -0800 |
commit | b9de1157289455b0ca26daff519d4a0ddcd1fa13 (patch) | |
tree | 4c56cc0a34b91f17033a40a455f26652304f7b8d /gcc-4.8.3/libgo/runtime/go-map-index.c | |
parent | 098157a754787181cfa10e71325832448ddcea98 (diff) | |
download | toolchain_gcc-b9de1157289455b0ca26daff519d4a0ddcd1fa13.tar.gz toolchain_gcc-b9de1157289455b0ca26daff519d4a0ddcd1fa13.tar.bz2 toolchain_gcc-b9de1157289455b0ca26daff519d4a0ddcd1fa13.zip |
Update 4.8.1 to 4.8.3.
My previous drop was the wrong version. The platform mingw is
currently using 4.8.3, not 4.8.1 (not sure how I got that wrong).
From ftp://ftp.gnu.org/gnu/gcc/gcc-4.8.3/gcc-4.8.3.tar.bz2.
Bug: http://b/26523949
Change-Id: Id85f1bdcbbaf78c7d0b5a69e74c798a08f341c35
Diffstat (limited to 'gcc-4.8.3/libgo/runtime/go-map-index.c')
-rw-r--r-- | gcc-4.8.3/libgo/runtime/go-map-index.c | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/gcc-4.8.3/libgo/runtime/go-map-index.c b/gcc-4.8.3/libgo/runtime/go-map-index.c new file mode 100644 index 000000000..499641c5e --- /dev/null +++ b/gcc-4.8.3/libgo/runtime/go-map-index.c @@ -0,0 +1,135 @@ +/* go-map-index.c -- find or insert an entry in a map. + + Copyright 2009 The Go Authors. All rights reserved. + Use of this source code is governed by a BSD-style + license that can be found in the LICENSE file. */ + +#include <stddef.h> +#include <stdlib.h> + +#include "runtime.h" +#include "go-alloc.h" +#include "go-assert.h" +#include "map.h" + +/* Rehash MAP to a larger size. */ + +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; + uintptr_t (*hashfn) (const void *, uintptr_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; +} + +/* Find KEY in MAP, return a pointer to the value. If KEY is not + present, then if INSERT is false, return NULL, and if INSERT is + true, insert a new value and zero-initialize it before returning a + pointer to it. */ + +void * +__go_map_index (struct __go_map *map, const void *key, _Bool insert) +{ + const struct __go_map_descriptor *descriptor; + const struct __go_type_descriptor *key_descriptor; + uintptr_t key_offset; + _Bool (*equalfn) (const void*, const void*, uintptr_t); + size_t key_hash; + size_t key_size; + size_t bucket_index; + char *entry; + + if (map == NULL) + { + if (insert) + runtime_panicstring ("assignment to entry in nil map"); + return NULL; + } + + descriptor = map->__descriptor; + + key_descriptor = descriptor->__map_descriptor->__key_type; + key_offset = descriptor->__key_offset; + key_size = key_descriptor->__size; + __go_assert (key_size != -1UL); + equalfn = key_descriptor->__equalfn; + + key_hash = key_descriptor->__hashfn (key, key_size); + bucket_index = key_hash % map->__bucket_count; + + entry = (char *) map->__buckets[bucket_index]; + while (entry != NULL) + { + if (equalfn (key, entry + key_offset, key_size)) + return entry + descriptor->__val_offset; + entry = *(char **) entry; + } + + if (!insert) + return NULL; + + if (map->__element_count >= map->__bucket_count) + { + __go_map_rehash (map); + bucket_index = key_hash % map->__bucket_count; + } + + entry = (char *) __go_alloc (descriptor->__entry_size); + __builtin_memset (entry, 0, descriptor->__entry_size); + + __builtin_memcpy (entry + key_offset, key, key_size); + + *(char **) entry = map->__buckets[bucket_index]; + map->__buckets[bucket_index] = entry; + + map->__element_count += 1; + + return entry + descriptor->__val_offset; +} |