Subclass cleanup must use exact key match to not call VM during GC sweep
This commit is contained in:
parent
ff23dbbc14
commit
6fa951a0bb
@ -140,6 +140,19 @@ extern int krk_tableGet_fast(KrkTable * table, KrkString * str, KrkValue * value
|
||||
*/
|
||||
extern int krk_tableDelete(KrkTable * table, KrkValue key);
|
||||
|
||||
/**
|
||||
* @brief Remove a key from a hash table, with identity lookup.
|
||||
* @memberof KrkTable
|
||||
*
|
||||
* Scans the table 'table' for the key 'key' and, if found, removes
|
||||
* the entry, replacing it with a tombstone value.
|
||||
*
|
||||
* @param table Table to delete from.
|
||||
* @param key Key to delete.
|
||||
* @return 1 if the value was found and deleted, 0 if it was not present.
|
||||
*/
|
||||
extern int krk_tableDeleteExact(KrkTable * table, KrkValue key);
|
||||
|
||||
/**
|
||||
* @brief Internal table scan function.
|
||||
* @memberof KrkTable
|
||||
|
@ -237,7 +237,7 @@ static void freeObject(KrkObj * object) {
|
||||
krk_freeTable(&_class->methods);
|
||||
krk_freeTable(&_class->subclasses);
|
||||
if (_class->base) {
|
||||
krk_tableDelete(&_class->base->subclasses, OBJECT_VAL(object));
|
||||
krk_tableDeleteExact(&_class->base->subclasses, OBJECT_VAL(object));
|
||||
}
|
||||
FREE(KrkClass, object);
|
||||
break;
|
||||
|
35
src/table.c
35
src/table.c
@ -82,6 +82,29 @@ KrkTableEntry * krk_findEntry(KrkTableEntry * entries, size_t capacity, KrkValue
|
||||
}
|
||||
}
|
||||
|
||||
KrkTableEntry * krk_findEntryExact(KrkTableEntry * entries, size_t capacity, KrkValue key) {
|
||||
uint32_t index;
|
||||
if (krk_hashValue(key, &index)) {
|
||||
return NULL;
|
||||
}
|
||||
index &= (capacity-1);
|
||||
KrkTableEntry * tombstone = NULL;
|
||||
for (;;) {
|
||||
KrkTableEntry * entry = &entries[index];
|
||||
if (IS_KWARGS(entry->key)) {
|
||||
if (IS_NONE(entry->value)) {
|
||||
return tombstone != NULL ? tombstone : entry;
|
||||
} else {
|
||||
if (tombstone == entry) return tombstone;
|
||||
if (tombstone == NULL) tombstone = entry;
|
||||
}
|
||||
} else if (krk_valuesSame(entry->key, key)) {
|
||||
return entry;
|
||||
}
|
||||
index = (index + 1) & (capacity-1);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __TINYC__
|
||||
int __builtin_clz(unsigned int x) {
|
||||
int i = 31;
|
||||
@ -189,6 +212,18 @@ int krk_tableDelete(KrkTable * table, KrkValue key) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int krk_tableDeleteExact(KrkTable * table, KrkValue key) {
|
||||
if (table->count == 0) return 0;
|
||||
KrkTableEntry * entry = krk_findEntryExact(table->entries, table->capacity, key);
|
||||
if (!entry || IS_KWARGS(entry->key)) {
|
||||
return 0;
|
||||
}
|
||||
table->count--;
|
||||
entry->key = KWARGS_VAL(0);
|
||||
entry->value = KWARGS_VAL(0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
KrkString * krk_tableFindString(KrkTable * table, const char * chars, size_t length, uint32_t hash) {
|
||||
if (table->count == 0) return NULL;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user