name-lookup.h (cp_binding_level): Removed unused member names_size.
[official-gcc.git] / libgo / runtime / go-map-index.c
bloba387c4b98bc673b2ac2447533ac8d045dcadddf3
1 /* go-map-index.c -- find or insert an entry in a map.
3 Copyright 2009 The Go Authors. All rights reserved.
4 Use of this source code is governed by a BSD-style
5 license that can be found in the LICENSE file. */
7 #include <stddef.h>
8 #include <stdlib.h>
10 #include "go-alloc.h"
11 #include "go-assert.h"
12 #include "map.h"
14 /* Rehash MAP to a larger size. */
16 static void
17 __go_map_rehash (struct __go_map *map)
19 const struct __go_map_descriptor *descriptor;
20 const struct __go_type_descriptor *key_descriptor;
21 uintptr_t key_offset;
22 size_t key_size;
23 size_t (*hashfn) (const void *, size_t);
24 uintptr_t old_bucket_count;
25 void **old_buckets;
26 uintptr_t new_bucket_count;
27 void **new_buckets;
28 uintptr_t i;
30 descriptor = map->__descriptor;
32 key_descriptor = descriptor->__map_descriptor->__key_type;
33 key_offset = descriptor->__key_offset;
34 key_size = key_descriptor->__size;
35 hashfn = key_descriptor->__hashfn;
37 old_bucket_count = map->__bucket_count;
38 old_buckets = map->__buckets;
40 new_bucket_count = __go_map_next_prime (old_bucket_count * 2);
41 new_buckets = (void **) __go_alloc (new_bucket_count * sizeof (void *));
42 __builtin_memset (new_buckets, 0, new_bucket_count * sizeof (void *));
44 for (i = 0; i < old_bucket_count; ++i)
46 char* entry;
47 char* next;
49 for (entry = old_buckets[i]; entry != NULL; entry = next)
51 size_t key_hash;
52 size_t new_bucket_index;
54 /* We could speed up rehashing at the cost of memory space
55 by caching the hash code. */
56 key_hash = hashfn (entry + key_offset, key_size);
57 new_bucket_index = key_hash % new_bucket_count;
59 next = *(char **) entry;
60 *(char **) entry = new_buckets[new_bucket_index];
61 new_buckets[new_bucket_index] = entry;
65 __go_free (old_buckets);
67 map->__bucket_count = new_bucket_count;
68 map->__buckets = new_buckets;
71 /* Find KEY in MAP, return a pointer to the value. If KEY is not
72 present, then if INSERT is false, return NULL, and if INSERT is
73 true, insert a new value and zero-initialize it before returning a
74 pointer to it. */
76 void *
77 __go_map_index (struct __go_map *map, const void *key, _Bool insert)
79 const struct __go_map_descriptor *descriptor;
80 const struct __go_type_descriptor *key_descriptor;
81 uintptr_t key_offset;
82 _Bool (*equalfn) (const void*, const void*, size_t);
83 size_t key_hash;
84 size_t key_size;
85 size_t bucket_index;
86 char *entry;
88 descriptor = map->__descriptor;
90 key_descriptor = descriptor->__map_descriptor->__key_type;
91 key_offset = descriptor->__key_offset;
92 key_size = key_descriptor->__size;
93 __go_assert (key_size != 0 && key_size != -1UL);
94 equalfn = key_descriptor->__equalfn;
96 key_hash = key_descriptor->__hashfn (key, key_size);
97 bucket_index = key_hash % map->__bucket_count;
99 entry = (char *) map->__buckets[bucket_index];
100 while (entry != NULL)
102 if (equalfn (key, entry + key_offset, key_size))
103 return entry + descriptor->__val_offset;
104 entry = *(char **) entry;
107 if (!insert)
108 return NULL;
110 if (map->__element_count >= map->__bucket_count)
112 __go_map_rehash (map);
113 bucket_index = key_hash % map->__bucket_count;
116 entry = (char *) __go_alloc (descriptor->__entry_size);
117 __builtin_memset (entry, 0, descriptor->__entry_size);
119 __builtin_memcpy (entry + key_offset, key, key_size);
121 *(char **) entry = map->__buckets[bucket_index];
122 map->__buckets[bucket_index] = entry;
124 map->__element_count += 1;
126 return entry + descriptor->__val_offset;