Browse Source

fix a bug

blueloveTH 6 months ago
parent
commit
9a23eb6c9e
5 changed files with 70 additions and 23 deletions
  1. 0 1
      src/interpreter/vm.c
  2. 13 9
      src/objects/namedict.c
  3. 8 3
      src/public/py_exception.c
  4. 14 1
      tests/08_dict.py
  5. 35 9
      tests/71_gc_bug.py

+ 0 - 1
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

+ 13 - 9
src/objects/namedict.c

@@ -5,27 +5,29 @@
 #include <string.h>
 #include <assert.h>
 
+#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
+#undef HASH_PROBE_1
+#undef HASH_KEY

+ 8 - 3
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);
+        }
     }
 }
 

+ 14 - 1
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)
+        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

+ 35 - 9
tests/71_gc_bug.py

@@ -1,9 +1,35 @@
-a=[]
-import gc
-gc.collect()
-
-# a.append(a)
-print(list(globals().items()))
-del a
-print(list(globals().items()))
-gc.collect()
+# a=[]
+# import gc
+# 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]