Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix an issue with internal table type #707

Merged
merged 2 commits into from
Dec 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/optionals/unittest/unittest.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ static Value mockNative(DictuVM *vm, int argCount, Value *args) {
pop(vm);
push(vm, OBJ_VAL(mockedClass));

for (int i = 0; i <= klass->publicMethods.capacityMask; ++i) {
for (int i = 0; i < klass->publicMethods.capacity; ++i) {
if (klass->publicMethods.entries[i].key == NULL) {
continue;
}
Expand Down
2 changes: 1 addition & 1 deletion src/vm/datatypes/class.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ static Value methods(DictuVM *vm, int argCount, Value *args) {
ObjList *list = newList(vm);
push(vm, OBJ_VAL(list));

for (int i = 0; i <= klass->publicMethods.capacityMask; ++i) {
for (int i = 0; i < klass->publicMethods.capacity; ++i) {
if (klass->publicMethods.entries[i].key == NULL) {
continue;
}
Expand Down
4 changes: 2 additions & 2 deletions src/vm/datatypes/copy.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ ObjInstance *copyInstance(DictuVM* vm, ObjInstance *oldInstance, bool shallow) {
if (shallow) {
tableAddAll(vm, &oldInstance->publicAttributes, &instance->publicAttributes);
} else {
for (int i = 0; i <= oldInstance->publicAttributes.capacityMask; i++) {
for (int i = 0; i < oldInstance->publicAttributes.capacity; i++) {
Entry *entry = &oldInstance->publicAttributes.entries[i];
if (entry->key != NULL) {
Value val = entry->value;
Expand All @@ -90,7 +90,7 @@ ObjInstance *copyInstance(DictuVM* vm, ObjInstance *oldInstance, bool shallow) {
}
}

for (int i = 0; i <= oldInstance->privateAttributes.capacityMask; i++) {
for (int i = 0; i < oldInstance->privateAttributes.capacity; i++) {
Entry *entry = &oldInstance->privateAttributes.entries[i];
if (entry->key != NULL) {
Value val = entry->value;
Expand Down
2 changes: 1 addition & 1 deletion src/vm/datatypes/enums.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ static Value values(DictuVM *vm, int argCount, Value *args) {
ObjDict *dict = newDict(vm);
push(vm, OBJ_VAL(dict));

for (int i = 0; i < objEnum->values.capacityMask + 1; ++i) {
for (int i = 0; i < objEnum->values.capacity; ++i) {
if (objEnum->values.entries[i].key == NULL) {
continue;
}
Expand Down
10 changes: 5 additions & 5 deletions src/vm/datatypes/instance.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ static Value getAttributes(DictuVM *vm, int argCount, Value *args) {

// Walk the inheritance chain
while (klass != NULL) {
for (int i = 0; i < klass->variables.capacityMask + 1; i++) {
for (int i = 0; i < klass->variables.capacity; i++) {
if (klass->variables.entries[i].key == NULL) {
continue;
}
Expand All @@ -144,7 +144,7 @@ static Value getAttributes(DictuVM *vm, int argCount, Value *args) {
writeValueArray(vm, &fields->values, OBJ_VAL(klass->variables.entries[i].key));
}

for (int i = 0; i < klass->constants.capacityMask + 1; i++) {
for (int i = 0; i < klass->constants.capacity; i++) {
if (klass->constants.entries[i].key == NULL) {
continue;
}
Expand All @@ -170,7 +170,7 @@ static Value getAttributes(DictuVM *vm, int argCount, Value *args) {
ObjList *attributes = newList(vm);
push(vm, OBJ_VAL(attributes));

for (int i = 0; i < instance->publicAttributes.capacityMask + 1; i++) {
for (int i = 0; i < instance->publicAttributes.capacity; i++) {
if (instance->publicAttributes.entries[i].key == NULL) {
continue;
}
Expand All @@ -193,7 +193,7 @@ static Value getAttributes(DictuVM *vm, int argCount, Value *args) {
ObjList *methods = newList(vm);
push(vm, OBJ_VAL(methods));

for (int i = 0; i <= instance->klass->publicMethods.capacityMask; ++i) {
for (int i = 0; i < instance->klass->publicMethods.capacity; ++i) {
if (instance->klass->publicMethods.entries[i].key == NULL) {
continue;
}
Expand Down Expand Up @@ -295,7 +295,7 @@ static Value methods(DictuVM *vm, int argCount, Value *args) {
ObjList *list = newList(vm);
push(vm, OBJ_VAL(list));

for (int i = 0; i <= instance->klass->publicMethods.capacityMask; ++i) {
for (int i = 0; i < instance->klass->publicMethods.capacity; ++i) {
if (instance->klass->publicMethods.entries[i].key == NULL) {
continue;
}
Expand Down
6 changes: 3 additions & 3 deletions src/vm/object.c
Original file line number Diff line number Diff line change
Expand Up @@ -550,21 +550,21 @@ ObjDict *classToDict(DictuVM *vm, Value value) {
push(vm, OBJ_VAL(methodsList));

while (klass != NULL) {
for (int i = 0; i < klass->variables.capacityMask + 1; i++) {
for (int i = 0; i < klass->variables.capacity; i++) {
if (klass->variables.entries[i].key == NULL) {
continue;
}
dictSet(vm, variablesDict, OBJ_VAL(klass->variables.entries[i].key), klass->variables.entries[i].value);
}

for (int i = 0; i < klass->constants.capacityMask + 1; i++) {
for (int i = 0; i < klass->constants.capacity; i++) {
if (klass->constants.entries[i].key == NULL) {
continue;
}
dictSet(vm, constantsDict, OBJ_VAL(klass->constants.entries[i].key), klass->constants.entries[i].value);
}

for (int i = 0; i < klass->publicMethods.capacityMask + 1; i++) {
for (int i = 0; i < klass->publicMethods.capacity; i++) {
if (klass->publicMethods.entries[i].key == NULL) {
continue;
}
Expand Down
48 changes: 22 additions & 26 deletions src/vm/table.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@

void initTable(Table *table) {
table->count = 0;
table->capacityMask = -1;
table->capacity = 0;
table->entries = NULL;
}

void freeTable(DictuVM *vm, Table *table) {
FREE_ARRAY(vm, Entry, table->entries, table->capacityMask + 1);
FREE_ARRAY(vm, Entry, table->entries, table->capacity);
initTable(table);
}

static Entry *findEntry(Entry *entries, int capacityMask,
ObjString *key) {
uint32_t index = key->hash & capacityMask;
uint32_t index = key->hash & (capacityMask - 1);
Entry *tombstone = NULL;

for (;;) {
Expand All @@ -40,30 +40,30 @@ static Entry *findEntry(Entry *entries, int capacityMask,
return entry;
}

index = (index + 1) & capacityMask;
index = (index + 1) & (capacityMask - 1);
}
}

bool tableGet(Table *table, ObjString *key, Value *value) {
if (table->count == 0) return false;

Entry *entry = findEntry(table->entries, table->capacityMask, key);
Entry *entry = findEntry(table->entries, table->capacity, key);
if (entry->key == NULL) return false;

*value = entry->value;
return true;
}

static void adjustCapacity(DictuVM *vm, Table *table, int capacityMask) {
Entry *entries = ALLOCATE(vm, Entry, capacityMask + 1);
for (int i = 0; i <= capacityMask; i++) {
Entry *entries = ALLOCATE(vm, Entry, capacityMask);
for (int i = 0; i < capacityMask; i++) {
entries[i].key = NULL;
entries[i].value = NIL_VAL;
}

table->count = 0;

for (int i = 0; i <= table->capacityMask; i++) {
for (int i = 0; i < table->capacity; i++) {
Entry *entry = &table->entries[i];
if (entry->key == NULL) continue;

Expand All @@ -73,19 +73,18 @@ static void adjustCapacity(DictuVM *vm, Table *table, int capacityMask) {
table->count++;
}

FREE_ARRAY(vm, Entry, table->entries, table->capacityMask + 1);
FREE_ARRAY(vm, Entry, table->entries, table->capacity);
table->entries = entries;
table->capacityMask = capacityMask;
table->capacity = capacityMask;
}

bool tableSet(DictuVM *vm, Table *table, ObjString *key, Value value) {
if (table->count + 1 > (table->capacityMask + 1) * TABLE_MAX_LOAD) {
// Figure out the new table size.
int capacityMask = GROW_CAPACITY(table->capacityMask + 1) - 1;
adjustCapacity(vm, table, capacityMask);
if (table->count + 1 > table->capacity * TABLE_MAX_LOAD) {
int capacity = GROW_CAPACITY(table->capacity);
adjustCapacity(vm, table, capacity);
}

Entry *entry = findEntry(table->entries, table->capacityMask, key);
Entry *entry = findEntry(table->entries, table->capacity, key);
bool isNewKey = entry->key == NULL;
entry->key = key;
entry->value = value;
Expand All @@ -99,19 +98,18 @@ bool tableDelete(DictuVM *vm, Table *table, ObjString *key) {
UNUSED(vm);
if (table->count == 0) return false;

Entry *entry = findEntry(table->entries, table->capacityMask, key);
// Find the entry.
Entry *entry = findEntry(table->entries, table->capacity, key);
if (entry->key == NULL) return false;

// Place a tombstone in the entry.
table->count--;
entry->key = NULL;
entry->value = BOOL_VAL(true);

return true;
}

void tableAddAll(DictuVM *vm, Table *from, Table *to) {
for (int i = 0; i <= from->capacityMask; i++) {
for (int i = 0; i < from->capacity; i++) {
Entry *entry = &from->entries[i];
if (entry->key != NULL) {
tableSet(vm, to, entry->key, entry->value);
Expand All @@ -127,13 +125,12 @@ ObjString *tableFindString(Table *table, const char *chars, int length,

// Figure out where to insert it in the table. Use open addressing and
// basic linear probing.

uint32_t index = hash & table->capacityMask;
uint32_t index = hash & (table->capacity - 1);

for (;;) {
Entry *entry = &table->entries[index];

if (entry->key == NULL) {
// Stop if we find an empty non-tombstone entry.
if (IS_NIL(entry->value)) return NULL;
} else if (entry->key->length == length &&
entry->key->hash == hash &&
Expand All @@ -142,13 +139,12 @@ ObjString *tableFindString(Table *table, const char *chars, int length,
return entry->key;
}

// Try the next slot.
index = (index + 1) & table->capacityMask;
index = (index + 1) & (table->capacity - 1);
}
}

void tableRemoveWhite(DictuVM *vm, Table *table) {
for (int i = 0; i <= table->capacityMask; i++) {
for (int i = 0; i < table->capacity; i++) {
Entry *entry = &table->entries[i];
if (entry->key != NULL && !entry->key->obj.isDark) {
tableDelete(vm, table, entry->key);
Expand All @@ -157,7 +153,7 @@ void tableRemoveWhite(DictuVM *vm, Table *table) {
}

void grayTable(DictuVM *vm, Table *table) {
for (int i = 0; i <= table->capacityMask; i++) {
for (int i = 0; i < table->capacity; i++) {
Entry *entry = &table->entries[i];
grayObject(vm, (Obj *) entry->key);
grayValue(vm, entry->value);
Expand Down
2 changes: 1 addition & 1 deletion src/vm/table.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ typedef struct {

typedef struct {
int count;
int capacityMask;
int capacity;
Entry *entries;
} Table;

Expand Down
2 changes: 1 addition & 1 deletion src/vm/vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -2276,7 +2276,7 @@ static DictuInterpretResult run(DictuVM *vm) {
ObjClass *klass = AS_CLASS(peek(vm, 0));

// If super class is abstract, ensure we have defined all abstract methods
for (int i = 0; i < klass->abstractMethods.capacityMask + 1; i++) {
for (int i = 0; i < klass->abstractMethods.capacity; i++) {
if (klass->abstractMethods.entries[i].key == NULL) {
continue;
}
Expand Down