diff --git a/src/interpreter/vm.c b/src/interpreter/vm.c index 1cf4ad4f..eb5109a6 100644 --- a/src/interpreter/vm.c +++ b/src/interpreter/vm.c @@ -637,7 +637,6 @@ void ManagedHeap__mark(ManagedHeap* self) { // mark value stack for(py_TValue* p = vm->stack.begin; p < vm->stack.sp; p++) { // assert(p->type != tp_nil); - if(py_isnil(p)) continue; pk__mark_value(p); } // mark modules diff --git a/src/objects/namedict.c b/src/objects/namedict.c index 86f006f6..7e89c6df 100644 --- a/src/objects/namedict.c +++ b/src/objects/namedict.c @@ -5,27 +5,29 @@ #include #include +#define HASH_KEY(__k) ((uintptr_t)(__k) >> 3U) + #define HASH_PROBE_0(__k, ok, i) \ ok = false; \ - i = (uintptr_t)(__k)&self->mask; \ + i = HASH_KEY(__k) & self->mask; \ do { \ if(self->items[i].key == (__k)) { \ ok = true; \ break; \ } \ if(self->items[i].key == NULL) break; \ - i = (5 * i + 1) & self->mask; \ + i = (i + 1) & self->mask; \ } while(true); #define HASH_PROBE_1(__k, ok, i) \ ok = false; \ - i = (uintptr_t)(__k)&self->mask; \ + i = HASH_KEY(__k) & self->mask; \ while(self->items[i].key != NULL) { \ if(self->items[i].key == (__k)) { \ ok = true; \ break; \ } \ - i = (5 * i + 1) & self->mask; \ + i = (i + 1) & self->mask; \ } static void NameDict__set_capacity_and_alloc_items(NameDict* self, int val) { @@ -111,12 +113,12 @@ bool NameDict__del(NameDict* self, py_Name key) { self->items[i].value = *py_NIL(); self->length--; /* tidy */ - uint32_t posToRemove = i; - uint32_t posToShift = posToRemove; + uintptr_t posToRemove = i; + uintptr_t posToShift = posToRemove; while(true) { - posToShift = (5 * posToShift + 1) & self->mask; + posToShift = (posToShift + 1) & self->mask; if(self->items[posToShift].key == NULL) break; - uintptr_t hash_z = (uintptr_t)self->items[posToShift].key; + uintptr_t hash_z = HASH_KEY(self->items[posToShift].key); uintptr_t insertPos = hash_z & self->mask; bool cond1 = insertPos <= posToRemove; bool cond2 = posToRemove <= posToShift; @@ -124,6 +126,7 @@ bool NameDict__del(NameDict* self, py_Name key) { // chain wrapped around capacity (posToShift < insertPos && (cond1 || cond2))) { NameDict_KV tmp = self->items[posToRemove]; + assert(tmp.key == NULL); self->items[posToRemove] = self->items[posToShift]; self->items[posToShift] = tmp; posToRemove = posToShift; @@ -141,4 +144,5 @@ void NameDict__clear(NameDict* self) { } #undef HASH_PROBE_0 -#undef HASH_PROBE_1 \ No newline at end of file +#undef HASH_PROBE_1 +#undef HASH_KEY \ No newline at end of file diff --git a/src/public/py_exception.c b/src/public/py_exception.c index 93238296..4fb0d117 100644 --- a/src/public/py_exception.c +++ b/src/public/py_exception.c @@ -20,9 +20,14 @@ void py_BaseException__stpush(py_Frame* frame, frame_dump->lineno = lineno; frame_dump->name = func_name ? c11_string__new(func_name) : NULL; - if(py_debugger_isattached() && frame != NULL) { - py_Frame_newlocals(frame, &frame_dump->locals); - py_Frame_newglobals(frame, &frame_dump->globals); + if(py_debugger_isattached()) { + if(frame != NULL) { + py_Frame_newlocals(frame, &frame_dump->locals); + py_Frame_newglobals(frame, &frame_dump->globals); + } else { + py_newdict(&frame_dump->locals); + py_newdict(&frame_dump->globals); + } } } diff --git a/tests/08_dict.py b/tests/08_dict.py index 992603f7..48833e7b 100644 --- a/tests/08_dict.py +++ b/tests/08_dict.py @@ -165,4 +165,17 @@ for i in range(len(data)): b.append(z) if i % 3 == 0: y = b.pop() - delattr(a, y) \ No newline at end of file + delattr(a, y) + +# bug test +d = { + '__name__': '__main__', + '__package__': '', + '__path__': '__main__', + 'a': [], + 'gc': 1, +} + +del d['a'] +assert 'a' not in d +assert d['gc'] == 1 \ No newline at end of file diff --git a/tests/71_gc_bug.py b/tests/71_gc_bug.py index c462fcde..d7656516 100644 --- a/tests/71_gc_bug.py +++ b/tests/71_gc_bug.py @@ -1,9 +1,35 @@ -a=[] -import gc -gc.collect() +# a=[] +# import gc +# gc.collect() -# a.append(a) -print(list(globals().items())) -del a -print(list(globals().items())) -gc.collect() +# # a.append(a) +# print(globals().items()) +# del a +# print(list(globals().items())) +# print(globals()['gc']) +# gc.collect() + +d = object() +d.__name__ = '__main__' +d.__package__ = '' +d.__path__ = '__main__' +d.a = [] +d.gc = 1 + +print('-' * 100) +assert d.gc == 1 +del d.a + +assert not hasattr(d, 'a') +assert d.gc == 1 + +# [0, 1, 6, 7, 4, 5, 2, 3] + +# 0 __name__ [0] +# 1 __package__ [1] +# 2 nil +# 3 nil +# 4 gc [4] +# 5 nil +# 6 __path__ [2] +# 7 a [3] \ No newline at end of file