annotate gcc/d/dmd/root/stringtable.c @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
145
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
1
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
2 /* Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
3 * http://www.digitalmars.com
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
4 * Distributed under the Boost Software License, Version 1.0.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
5 * (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
6 * https://github.com/D-Programming-Language/dmd/blob/master/src/root/stringtable.c
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
7 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
8
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
9 #include "dsystem.h" // uint{8|16|32}_t, memcpy()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
10 #include "root.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
11 #include "rmem.h" // mem
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
12 #include "stringtable.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
13 #include "hash.h"
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
14
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
15 #define POOL_BITS 12
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
16 #define POOL_SIZE (1U << POOL_BITS)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
17
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
18 struct StringEntry
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
19 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
20 uint32_t hash;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
21 uint32_t vptr;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
22 };
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
23
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
24 uint32_t StringTable::allocValue(const char *s, size_t length, void *ptrvalue)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
25 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
26 const size_t nbytes = sizeof(StringValue) + length + 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
27
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
28 if (!npools || nfill + nbytes > POOL_SIZE)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
29 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
30 pools = (uint8_t **)mem.xrealloc(pools, ++npools * sizeof(pools[0]));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
31 pools[npools - 1] = (uint8_t *)mem.xmalloc(nbytes > POOL_SIZE ? nbytes : POOL_SIZE);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
32 nfill = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
33 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
34
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
35 StringValue *sv = (StringValue *)&pools[npools - 1][nfill];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
36 sv->ptrvalue = ptrvalue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
37 sv->length = length;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
38 ::memcpy(sv->lstring(), s, length);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
39 sv->lstring()[length] = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
40
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
41 const uint32_t vptr = (uint32_t)(npools << POOL_BITS | nfill);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
42 nfill += nbytes + (-nbytes & 7); // align to 8 bytes
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
43 return vptr;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
44 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
45
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
46 StringValue *StringTable::getValue(uint32_t vptr)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
47 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
48 if (!vptr) return NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
49
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
50 const size_t idx = (vptr >> POOL_BITS) - 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
51 const size_t off = vptr & (POOL_SIZE - 1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
52 return (StringValue *)&pools[idx][off];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
53 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
54
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
55 static size_t nextpow2(size_t val)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
56 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
57 size_t res = 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
58 while (res < val)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
59 res <<= 1;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
60 return res;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
61 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
62
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
63 static const double loadFactor = 0.8;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
64
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
65 void StringTable::_init(size_t size)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
66 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
67 size = nextpow2((size_t)(size / loadFactor));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
68 if (size < 32) size = 32;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
69 table = (StringEntry *)mem.xcalloc(size, sizeof(table[0]));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
70 tabledim = size;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
71 pools = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
72 npools = nfill = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
73 count = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
74 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
75
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
76 void StringTable::reset(size_t size)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
77 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
78 for (size_t i = 0; i < npools; ++i)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
79 mem.xfree(pools[i]);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
80
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
81 mem.xfree(table);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
82 mem.xfree(pools);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
83 table = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
84 pools = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
85 _init(size);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
86 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
87
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
88 StringTable::~StringTable()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
89 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
90 for (size_t i = 0; i < npools; ++i)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
91 mem.xfree(pools[i]);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
92
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
93 mem.xfree(table);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
94 mem.xfree(pools);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
95 table = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
96 pools = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
97 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
98
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
99 size_t StringTable::findSlot(hash_t hash, const char *s, size_t length)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
100 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
101 // quadratic probing using triangular numbers
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
102 // http://stackoverflow.com/questions/2348187/moving-from-linear-probing-to-quadratic-probing-hash-collisons/2349774#2349774
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
103 for (size_t i = hash & (tabledim - 1), j = 1; ;++j)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
104 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
105 StringValue *sv;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
106 if (!table[i].vptr ||
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
107 (table[i].hash == hash &&
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
108 (sv = getValue(table[i].vptr))->length == length &&
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
109 ::memcmp(s, sv->lstring(), length) == 0))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
110 return i;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
111 i = (i + j) & (tabledim - 1);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
112 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
113 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
114
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
115 StringValue *StringTable::lookup(const char *s, size_t length)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
116 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
117 const hash_t hash = calcHash(s, length);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
118 const size_t i = findSlot(hash, s, length);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
119 // printf("lookup %.*s %p\n", (int)length, s, table[i].value ?: NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
120 return getValue(table[i].vptr);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
121 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
122
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
123 StringValue *StringTable::update(const char *s, size_t length)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
124 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
125 const hash_t hash = calcHash(s, length);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
126 size_t i = findSlot(hash, s, length);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
127 if (!table[i].vptr)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
128 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
129 if (++count > tabledim * loadFactor)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
130 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
131 grow();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
132 i = findSlot(hash, s, length);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
133 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
134 table[i].hash = hash;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
135 table[i].vptr = allocValue(s, length, NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
136 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
137 // printf("update %.*s %p\n", (int)length, s, table[i].value ?: NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
138 return getValue(table[i].vptr);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
139 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
140
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
141 StringValue *StringTable::insert(const char *s, size_t length, void *ptrvalue)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
142 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
143 const hash_t hash = calcHash(s, length);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
144 size_t i = findSlot(hash, s, length);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
145 if (table[i].vptr)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
146 return NULL; // already in table
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
147 if (++count > tabledim * loadFactor)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
148 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
149 grow();
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
150 i = findSlot(hash, s, length);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
151 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
152 table[i].hash = hash;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
153 table[i].vptr = allocValue(s, length, ptrvalue);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
154 // printf("insert %.*s %p\n", (int)length, s, table[i].value ?: NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
155 return getValue(table[i].vptr);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
156 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
157
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
158 void StringTable::grow()
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
159 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
160 const size_t odim = tabledim;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
161 StringEntry *otab = table;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
162 tabledim *= 2;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
163 table = (StringEntry *)mem.xcalloc(tabledim, sizeof(table[0]));
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
164
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
165 for (size_t i = 0; i < odim; ++i)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
166 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
167 StringEntry *se = &otab[i];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
168 if (!se->vptr) continue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
169 StringValue *sv = getValue(se->vptr);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
170 table[findSlot(se->hash, sv->lstring(), sv->length)] = *se;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
171 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
172 mem.xfree(otab);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
173 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
174
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
175 /********************************
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
176 * Walk the contents of the string table,
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
177 * calling fp for each entry.
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
178 * Params:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
179 * fp = function to call. Returns !=0 to stop
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
180 * Returns:
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
181 * last return value of fp call
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
182 */
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
183 int StringTable::apply(int (*fp)(StringValue *))
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
184 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
185 for (size_t i = 0; i < tabledim; ++i)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
186 {
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
187 StringEntry *se = &table[i];
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
188 if (!se->vptr) continue;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
189 StringValue *sv = getValue(se->vptr);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
190 int result = (*fp)(sv);
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
191 if (result)
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
192 return result;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
193 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
194 return 0;
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
195 }
1830386684a0 gcc-9.2.0
anatofuz
parents:
diff changeset
196