|
@@ -69,7 +69,7 @@ static void pkpy_Dict__htset(pkpy_Dict* self, int h, int v) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-static int pkpy_Dict__probe(const pkpy_Dict* self, void* vm, pkpy_Var key, int64_t hash) {
|
|
|
|
|
|
|
+static int pkpy_Dict__probe0(const pkpy_Dict* self, void* vm, pkpy_Var key, int64_t hash) {
|
|
|
const int null = pkpy_Dict__idx_null(self);
|
|
const int null = pkpy_Dict__idx_null(self);
|
|
|
const int mask = self->_htcap - 1;
|
|
const int mask = self->_htcap - 1;
|
|
|
for(int h = hash & mask;; h = (h + 1) & mask) {
|
|
for(int h = hash & mask;; h = (h + 1) & mask) {
|
|
@@ -83,6 +83,19 @@ static int pkpy_Dict__probe(const pkpy_Dict* self, void* vm, pkpy_Var key, int64
|
|
|
PK_UNREACHABLE();
|
|
PK_UNREACHABLE();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static int pkpy_Dict__probe1(const pkpy_Dict* self, void* vm, pkpy_Var key, int64_t hash) {
|
|
|
|
|
+ const int null = pkpy_Dict__idx_null(self);
|
|
|
|
|
+ const int mask = self->_htcap - 1;
|
|
|
|
|
+ for(int h = hash & mask;; h = (h + 1) & mask) {
|
|
|
|
|
+ int idx = pkpy_Dict__htget(self, h);
|
|
|
|
|
+ if(idx == null) return h;
|
|
|
|
|
+
|
|
|
|
|
+ struct pkpy_DictEntry* entry = &c11__getitem(struct pkpy_DictEntry, &self->_entries, idx);
|
|
|
|
|
+ if(entry->hash == hash && pkpy_Var__eq__(vm, entry->key, key)) return h;
|
|
|
|
|
+ }
|
|
|
|
|
+ PK_UNREACHABLE();
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
static void pkpy_Dict__extendht(pkpy_Dict* self, void* vm) {
|
|
static void pkpy_Dict__extendht(pkpy_Dict* self, void* vm) {
|
|
|
self->_version += 1;
|
|
self->_version += 1;
|
|
|
free(self->_hashtable);
|
|
free(self->_hashtable);
|
|
@@ -94,14 +107,14 @@ static void pkpy_Dict__extendht(pkpy_Dict* self, void* vm) {
|
|
|
struct pkpy_DictEntry* entry = &c11__getitem(struct pkpy_DictEntry, &self->_entries, i);
|
|
struct pkpy_DictEntry* entry = &c11__getitem(struct pkpy_DictEntry, &self->_entries, i);
|
|
|
if(pkpy_Var__is_null(&entry->key)) continue;
|
|
if(pkpy_Var__is_null(&entry->key)) continue;
|
|
|
|
|
|
|
|
- int h = pkpy_Dict__probe(self, vm, entry->key, entry->hash);
|
|
|
|
|
|
|
+ int h = pkpy_Dict__probe0(self, vm, entry->key, entry->hash);
|
|
|
pkpy_Dict__htset(self, h, i);
|
|
pkpy_Dict__htset(self, h, i);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
bool pkpy_Dict__set(pkpy_Dict* self, void* vm, pkpy_Var key, pkpy_Var val) {
|
|
bool pkpy_Dict__set(pkpy_Dict* self, void* vm, pkpy_Var key, pkpy_Var val) {
|
|
|
int hash = pkpy_Var__hash__(vm, key);
|
|
int hash = pkpy_Var__hash__(vm, key);
|
|
|
- int h = pkpy_Dict__probe(self, vm, key, hash);
|
|
|
|
|
|
|
+ int h = pkpy_Dict__probe1(self, vm, key, hash);
|
|
|
|
|
|
|
|
int idx = pkpy_Dict__htget(self, h);
|
|
int idx = pkpy_Dict__htget(self, h);
|
|
|
if(idx == pkpy_Dict__idx_null(self)) {
|
|
if(idx == pkpy_Dict__idx_null(self)) {
|
|
@@ -114,6 +127,7 @@ bool pkpy_Dict__set(pkpy_Dict* self, void* vm, pkpy_Var key, pkpy_Var val) {
|
|
|
.key = key,
|
|
.key = key,
|
|
|
.val = val,
|
|
.val = val,
|
|
|
}));
|
|
}));
|
|
|
|
|
+ h = pkpy_Dict__probe0(self, vm, key, hash);
|
|
|
pkpy_Dict__htset(self, h, idx);
|
|
pkpy_Dict__htset(self, h, idx);
|
|
|
self->count += 1;
|
|
self->count += 1;
|
|
|
if(self->count >= self->_htcap * 0.75) pkpy_Dict__extendht(self, vm);
|
|
if(self->count >= self->_htcap * 0.75) pkpy_Dict__extendht(self, vm);
|
|
@@ -121,17 +135,31 @@ bool pkpy_Dict__set(pkpy_Dict* self, void* vm, pkpy_Var key, pkpy_Var val) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
struct pkpy_DictEntry* entry = &c11__getitem(struct pkpy_DictEntry, &self->_entries, idx);
|
|
struct pkpy_DictEntry* entry = &c11__getitem(struct pkpy_DictEntry, &self->_entries, idx);
|
|
|
- assert(entry->hash == hash && pkpy_Var__eq__(vm, entry->key, key));
|
|
|
|
|
- entry->val = val;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ if(entry->hash == hash || pkpy_Var__eq__(vm, entry->key, key)) {
|
|
|
|
|
+ entry->val = val;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ self->_version += 1;
|
|
|
|
|
+ self->count += 1;
|
|
|
|
|
+ h = pkpy_Dict__probe0(self, vm, key, hash);
|
|
|
|
|
+ idx = pkpy_Dict__htget(self, h);
|
|
|
|
|
+ struct pkpy_DictEntry* entry = &c11__getitem(struct pkpy_DictEntry, &self->_entries, idx);
|
|
|
|
|
+ entry->key = key;
|
|
|
|
|
+ entry->val = val;
|
|
|
|
|
+ entry->hash = hash;
|
|
|
|
|
+ }
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
bool pkpy_Dict__contains(const pkpy_Dict* self, void* vm, pkpy_Var key) {
|
|
bool pkpy_Dict__contains(const pkpy_Dict* self, void* vm, pkpy_Var key) {
|
|
|
int hash = pkpy_Var__hash__(vm, key);
|
|
int hash = pkpy_Var__hash__(vm, key);
|
|
|
- int h = pkpy_Dict__probe(self, vm, key, hash);
|
|
|
|
|
|
|
+ int h = pkpy_Dict__probe1(self, vm, key, hash);
|
|
|
|
|
|
|
|
int idx = pkpy_Dict__htget(self, h);
|
|
int idx = pkpy_Dict__htget(self, h);
|
|
|
if(idx == pkpy_Dict__idx_null(self)) return false;
|
|
if(idx == pkpy_Dict__idx_null(self)) return false;
|
|
|
|
|
+
|
|
|
|
|
+ struct pkpy_DictEntry* entry = &c11__getitem(struct pkpy_DictEntry, &self->_entries, idx);
|
|
|
|
|
+ assert(entry->hash == hash && pkpy_Var__eq__(vm, entry->key, key));
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -155,7 +183,7 @@ static bool pkpy_Dict__refactor(pkpy_Dict* self, void* vm) {
|
|
|
|
|
|
|
|
int j = self->_entries.count;
|
|
int j = self->_entries.count;
|
|
|
c11_vector__push(struct pkpy_DictEntry, &self->_entries, *entry);
|
|
c11_vector__push(struct pkpy_DictEntry, &self->_entries, *entry);
|
|
|
- int h = pkpy_Dict__probe(self, vm, entry->key, entry->hash);
|
|
|
|
|
|
|
+ int h = pkpy_Dict__probe0(self, vm, entry->key, entry->hash);
|
|
|
pkpy_Dict__htset(self, h, j);
|
|
pkpy_Dict__htset(self, h, j);
|
|
|
}
|
|
}
|
|
|
c11_vector__dtor(&old_entries);
|
|
c11_vector__dtor(&old_entries);
|
|
@@ -164,15 +192,14 @@ static bool pkpy_Dict__refactor(pkpy_Dict* self, void* vm) {
|
|
|
|
|
|
|
|
bool pkpy_Dict__del(pkpy_Dict* self, void* vm, pkpy_Var key) {
|
|
bool pkpy_Dict__del(pkpy_Dict* self, void* vm, pkpy_Var key) {
|
|
|
int hash = pkpy_Var__hash__(vm, key);
|
|
int hash = pkpy_Var__hash__(vm, key);
|
|
|
- int h = pkpy_Dict__probe(self, vm, key, hash);
|
|
|
|
|
|
|
+ int h = pkpy_Dict__probe1(self, vm, key, hash);
|
|
|
int idx = pkpy_Dict__htget(self, h), null = pkpy_Dict__idx_null(self);
|
|
int idx = pkpy_Dict__htget(self, h), null = pkpy_Dict__idx_null(self);
|
|
|
if(idx == null) return false;
|
|
if(idx == null) return false;
|
|
|
|
|
|
|
|
- self->_version += 1;
|
|
|
|
|
struct pkpy_DictEntry* entry = &c11__getitem(struct pkpy_DictEntry, &self->_entries, idx);
|
|
struct pkpy_DictEntry* entry = &c11__getitem(struct pkpy_DictEntry, &self->_entries, idx);
|
|
|
assert(entry->hash == hash && pkpy_Var__eq__(vm, entry->key, key));
|
|
assert(entry->hash == hash && pkpy_Var__eq__(vm, entry->key, key));
|
|
|
|
|
+ self->_version += 1;
|
|
|
pkpy_Var__set_null(&entry->key);
|
|
pkpy_Var__set_null(&entry->key);
|
|
|
- pkpy_Dict__htset(self, h, null);
|
|
|
|
|
self->count -= 1;
|
|
self->count -= 1;
|
|
|
pkpy_Dict__refactor(self, vm);
|
|
pkpy_Dict__refactor(self, vm);
|
|
|
return true;
|
|
return true;
|
|
@@ -180,7 +207,7 @@ bool pkpy_Dict__del(pkpy_Dict* self, void* vm, pkpy_Var key) {
|
|
|
|
|
|
|
|
const pkpy_Var *pkpy_Dict__try_get(const pkpy_Dict* self, void* vm, pkpy_Var key) {
|
|
const pkpy_Var *pkpy_Dict__try_get(const pkpy_Dict* self, void* vm, pkpy_Var key) {
|
|
|
int hash = pkpy_Var__hash__(vm, key);
|
|
int hash = pkpy_Var__hash__(vm, key);
|
|
|
- int h = pkpy_Dict__probe(self, vm, key, hash);
|
|
|
|
|
|
|
+ int h = pkpy_Dict__probe1(self, vm, key, hash);
|
|
|
|
|
|
|
|
int idx = pkpy_Dict__htget(self, h);
|
|
int idx = pkpy_Dict__htget(self, h);
|
|
|
if(idx == pkpy_Dict__idx_null(self)) return NULL;
|
|
if(idx == pkpy_Dict__idx_null(self)) return NULL;
|