7
#define TABLE_MAX_LOAD 0.75
9
void initTable(Table *table) {
11
table->capacityMask = -1;
12
table->entries = NULL;
15
void freeTable(DictuVM *vm, Table *table) {
16
FREE_ARRAY(vm, Entry, table->entries, table->capacityMask + 1);
20
bool tableGet(Table *table, ObjString *key, Value *value) {
21
if (table->count == 0) return false;
24
uint32_t index = key->hash & table->capacityMask;
28
entry = &table->entries[index];
30
if (entry->key == NULL || psl > entry->psl) {
34
if (entry->key == key) {
38
index = (index + 1) & table->capacityMask;
42
*value = entry->value;
46
static void adjustCapacity(DictuVM *vm, Table *table, int capacityMask) {
47
Entry *entries = ALLOCATE(vm, Entry, capacityMask + 1);
48
for (int i = 0; i <= capacityMask; i++) {
49
entries[i].key = NULL;
50
entries[i].value = NIL_VAL;
54
Entry *oldEntries = table->entries;
55
int oldMask = table->capacityMask;
58
table->entries = entries;
59
table->capacityMask = capacityMask;
61
for (int i = 0; i <= oldMask; i++) {
62
Entry *entry = &oldEntries[i];
63
if (entry->key == NULL) continue;
65
tableSet(vm, table, entry->key, entry->value);
68
FREE_ARRAY(vm, Entry, oldEntries, oldMask + 1);
71
bool tableSet(DictuVM *vm, Table *table, ObjString *key, Value value) {
72
if (table->count + 1 > (table->capacityMask + 1) * TABLE_MAX_LOAD) {
73
// Figure out the new table size.
74
int capacityMask = GROW_CAPACITY(table->capacityMask + 1) - 1;
75
adjustCapacity(vm, table, capacityMask);
78
uint32_t index = key->hash & table->capacityMask;
80
bool isNewKey = false;
88
bucket = &table->entries[index];
90
if (bucket->key == NULL) {
94
if (bucket->key == key) {
98
if (entry.psl > bucket->psl) {
106
index = (index + 1) & table->capacityMask;
111
if (isNewKey) table->count++;
115
bool tableDelete(DictuVM *vm, Table *table, ObjString *key) {
117
if (table->count == 0) return false;
119
int capacityMask = table->capacityMask;
120
uint32_t index = key->hash & table->capacityMask;
125
entry = &table->entries[index];
127
if (entry->key == NULL || psl > entry->psl) {
131
if (entry->key == key) {
135
index = (index + 1) & capacityMask;
144
entry->value = NIL_VAL;
147
index = (index + 1) & capacityMask;
148
nextEntry = &table->entries[index];
151
* Stop if we reach an empty bucket or hit a key which
152
* is in its base (original) location.
154
if (nextEntry->key == NULL || nextEntry->psl == 0) {
166
void tableAddAll(DictuVM *vm, Table *from, Table *to) {
167
for (int i = 0; i <= from->capacityMask; i++) {
168
Entry *entry = &from->entries[i];
169
if (entry->key != NULL) {
170
tableSet(vm, to, entry->key, entry->value);
175
// TODO: Return entry here rather than string
176
ObjString *tableFindString(Table *table, const char *chars, int length,
178
// If the table is empty, we definitely won't find it.
179
if (table->count == 0) return NULL;
181
// Figure out where to insert it in the table. Use open addressing and
182
// basic linear probing.
184
uint32_t index = hash & table->capacityMask;
188
Entry *entry = &table->entries[index];
190
if (entry->key == NULL || psl > entry->psl) {
194
if (entry->key->length == length &&
195
entry->key->hash == hash &&
196
memcmp(entry->key->chars, chars, length) == 0) {
201
index = (index + 1) & table->capacityMask;
206
void tableRemoveWhite(DictuVM *vm, Table *table) {
207
for (int i = 0; i <= table->capacityMask; i++) {
208
Entry *entry = &table->entries[i];
209
if (entry->key != NULL && !entry->key->obj.isDark) {
210
tableDelete(vm, table, entry->key);
215
void grayTable(DictuVM *vm, Table *table) {
216
for (int i = 0; i <= table->capacityMask; i++) {
217
Entry *entry = &table->entries[i];
218
grayObject(vm, (Obj *) entry->key);
219
grayValue(vm, entry->value);