فهرست منبع

fix gc issues

blueloveTH 1 سال پیش
والد
کامیت
3e99f46273

+ 2 - 0
include/pocketpy/interpreter/frame.h

@@ -64,3 +64,5 @@ int Frame__exit_block(Frame* self, ValueStack*, int);
 
 UnwindTarget* Frame__find_unwind_target(Frame* self, int iblock);
 void Frame__set_unwind_target(Frame* self, py_TValue* sp);
+
+void Frame__gc_mark(Frame* self);

+ 4 - 2
include/pocketpy/interpreter/vm.h

@@ -21,6 +21,7 @@ typedef struct py_TypeInfo {
     c11_vector /*T=py_Name*/ annotated_fields;
 
     void (*on_end_subclass)(struct py_TypeInfo*);  // backdoor for enum module
+    void (*gc_mark)(void* ud);
 
     /* Magic Slots */
     py_TValue magic[64];
@@ -61,8 +62,9 @@ void VM__pop_frame(VM* self);
 bool pk__parse_int_slice(py_Ref slice, int length, int* start, int* stop, int* step);
 bool pk__normalize_index(int* index, int length);
 
-void pk_list__mark(void* ud, void (*marker)(py_TValue*));
-void pk_dict__mark(void* ud, void (*marker)(py_TValue*));
+void pk__mark_value(py_TValue*);
+void pk__mark_namedict(NameDict*);
+void pk__tp_set_marker(py_Type type, void (*gc_mark)(void*));
 
 bool pk_wrapper__self(int argc, py_Ref argv);
 bool pk_wrapper__NotImplementedError(int argc, py_Ref argv);

+ 2 - 2
python/pickle.py

@@ -1,5 +1,4 @@
 import json
-from c import struct
 import builtins
 
 _BASIC_TYPES = [int, float, str, bool, type(None)]
@@ -142,7 +141,8 @@ class _Unpickler:
         
         # generic object
         cls = _find_class(o[0])
-        if getattr(cls, '__struct__', False):
+        # if getattr(cls, '__struct__', False):
+        if False:
             inst = cls.fromstruct(struct.fromhex(o[1]))
             self.tag(index, inst)
             return inst

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
src/common/_generated.c


+ 6 - 0
src/interpreter/frame.c

@@ -1,4 +1,5 @@
 #include "pocketpy/interpreter/frame.h"
+#include "pocketpy/interpreter/vm.h"
 #include "pocketpy/objects/codeobject.h"
 #include "pocketpy/objects/object.h"
 #include "pocketpy/pocketpy.h"
@@ -133,6 +134,11 @@ void Frame__set_unwind_target(Frame* self, py_TValue* sp) {
     }
 }
 
+void Frame__gc_mark(Frame *self){
+    pk__mark_value(self->module);
+    CodeObject__gc_mark(self->co);
+}
+
 py_TValue* Frame__f_closure_try_get(Frame* self, py_Name name) {
     if(!self->has_function) return NULL;
     Function* ud = py_touserdata(self->p0);

+ 7 - 0
src/interpreter/generator.c

@@ -71,9 +71,16 @@ static bool generator__next__(int argc, py_Ref argv) {
     }
 }
 
+static void generator__gc_mark(void* ud){
+    Generator* gen = ud;
+    if(gen->frame) Frame__gc_mark(gen->frame);
+}
+
 py_Type pk_generator__register() {
     py_Type type = pk_newtype("generator", tp_object, NULL, (py_Dtor)Generator__dtor, false, true);
 
+    pk__tp_set_marker(type, generator__gc_mark);
+
     py_bindmagic(type, __iter__, pk_wrapper__self);
     py_bindmagic(type, __next__, generator__next__);
     return type;

+ 29 - 21
src/interpreter/vm.c

@@ -534,10 +534,23 @@ void PyObject__delete(PyObject* self) {
 
 static void mark_object(PyObject* obj);
 
-static void mark_value(py_TValue* val) {
+void pk__mark_value(py_TValue* val) {
     if(val->is_ptr) mark_object(val->_obj);
 }
 
+void pk__mark_namedict(NameDict* dict) {
+    for(int i = 0; i < dict->count; i++) {
+        NameDict_KV* kv = c11__at(NameDict_KV, dict, i);
+        pk__mark_value(&kv->value);
+    }
+}
+
+void pk__tp_set_marker(py_Type type, void (*gc_mark)(void*)) {
+    py_TypeInfo* ti = c11__at(py_TypeInfo, &pk_current_vm->types, type);
+    assert(ti->gc_mark == NULL);
+    ti->gc_mark = gc_mark;
+}
+
 static void mark_object(PyObject* obj) {
     if(obj->gc_marked) return;
     obj->gc_marked = true;
@@ -545,24 +558,19 @@ static void mark_object(PyObject* obj) {
     if(obj->slots > 0) {
         py_TValue* p = PyObject__slots(obj);
         for(int i = 0; i < obj->slots; i++)
-            mark_value(p + i);
-        return;
-    }
-
-    if(obj->slots == -1) {
+            pk__mark_value(p + i);
+    } else if(obj->slots == -1) {
         NameDict* dict = PyObject__dict(obj);
-        for(int j = 0; j < dict->count; j++) {
-            NameDict_KV* kv = c11__at(NameDict_KV, dict, j);
-            mark_value(&kv->value);
-        }
-        return;
+        pk__mark_namedict(dict);
     }
 
-    if(obj->type == tp_list) {
-        pk_list__mark(PyObject__userdata(obj), mark_value);
-    } else if(obj->type == tp_dict) {
-        pk_dict__mark(PyObject__userdata(obj), mark_value);
-    }
+    py_TypeInfo* types = c11__at(py_TypeInfo, &pk_current_vm->types, obj->type);
+    if(types->gc_mark) { types->gc_mark(PyObject__userdata(obj)); }
+}
+
+void CodeObject__gc_mark(const CodeObject* self) {
+    c11__foreach(py_TValue, &self->consts, i) { pk__mark_value(i); }
+    c11__foreach(FuncDecl_, &self->func_decls, i) { CodeObject__gc_mark(&(*i)->code); }
 }
 
 void ManagedHeap__mark(ManagedHeap* self) {
@@ -574,17 +582,17 @@ void ManagedHeap__mark(ManagedHeap* self) {
     }
     // mark value stack
     for(py_TValue* p = vm->stack.begin; p != vm->stack.end; p++) {
-        mark_value(p);
+        pk__mark_value(p);
     }
     // mark frame
     for(Frame* frame = vm->top_frame; frame; frame = frame->f_back) {
-        mark_value(frame->module);
+        Frame__gc_mark(frame);
     }
     // mark vm's registers
-    mark_value(&vm->last_retval);
-    mark_value(&vm->curr_exception);
+    pk__mark_value(&vm->last_retval);
+    pk__mark_value(&vm->curr_exception);
     for(int i = 0; i < c11__count_array(vm->reg); i++) {
-        mark_value(&vm->reg[i]);
+        pk__mark_value(&vm->reg[i]);
     }
 }
 

+ 1 - 0
src/objects/codeobject.c

@@ -1,5 +1,6 @@
 #include "pocketpy/objects/codeobject.h"
 #include "pocketpy/common/utils.h"
+#include "pocketpy/pocketpy.h"
 #include <stdint.h>
 
 void Bytecode__set_signed_arg(Bytecode* self, int arg) {

+ 9 - 1
src/public/modules.c

@@ -1,3 +1,4 @@
+#include "pocketpy/objects/codeobject.h"
 #include "pocketpy/pocketpy.h"
 
 #include "pocketpy/common/utils.h"
@@ -501,7 +502,6 @@ static bool function__closure__getter(int argc, py_Ref argv) {
     Function* ud = py_touserdata(argv);
     if(!ud->closure) {
         py_newnone(py_retval());
-        return true;
     }
     py_Ref r0 = py_pushtmp();
     py_Ref retval = py_pushtmp();
@@ -520,10 +520,18 @@ static bool function__closure__getter(int argc, py_Ref argv) {
     return true;
 }
 
+static void function__gc_mark(void* ud) {
+    Function* func = ud;
+    if(func->closure) pk__mark_namedict(func->closure);
+    CodeObject__gc_mark(&func->decl->code);
+}
+
 py_Type pk_function__register() {
     py_Type type =
         pk_newtype("function", tp_object, NULL, (void (*)(void*))Function__dtor, false, true);
 
+    pk__tp_set_marker(type, function__gc_mark);
+
     py_bindproperty(type, "__closure__", function__closure__getter, NULL);
     return type;
 }

+ 12 - 10
src/public/py_dict.c

@@ -433,9 +433,21 @@ static bool dict_values(int argc, py_Ref argv) {
     return true;
 }
 
+static void dict__gc_mark(void* ud) {
+    Dict* self = ud;
+    for(int i = 0; i < self->entries.count; i++) {
+        DictEntry* entry = c11__at(DictEntry, &self->entries, i);
+        if(py_isnil(&entry->key)) continue;
+        pk__mark_value(&entry->key);
+        pk__mark_value(&entry->val);
+    }
+}
+
 py_Type pk_dict__register() {
     py_Type type = pk_newtype("dict", tp_object, NULL, (void (*)(void*))Dict__dtor, false, false);
 
+    pk__tp_set_marker(type, dict__gc_mark);
+
     py_bindmagic(type, __new__, dict__new__);
     py_bindmagic(type, __init__, dict__init__);
     py_bindmagic(type, __getitem__, dict__getitem__);
@@ -532,13 +544,3 @@ bool py_dict_apply(py_Ref self, bool (*f)(py_Ref, py_Ref, void*), void* ctx) {
     }
     return true;
 }
-
-void pk_dict__mark(void* ud, void (*marker)(py_TValue*)) {
-    Dict* self = ud;
-    for(int i = 0; i < self->entries.count; i++) {
-        DictEntry* entry = c11__at(DictEntry, &self->entries, i);
-        if(py_isnil(&entry->key)) continue;
-        marker(&entry->key);
-        marker(&entry->val);
-    }
-}

+ 10 - 8
src/public/py_list.c

@@ -44,7 +44,7 @@ int py_list_len(py_Ref self) {
     return userdata->count;
 }
 
-void py_list_swap(py_Ref self, int i, int j){
+void py_list_swap(py_Ref self, int i, int j) {
     py_TValue* data = py_list_data(self);
     py_TValue tmp = data[i];
     data[i] = data[j];
@@ -408,10 +408,19 @@ static bool list__contains__(int argc, py_Ref argv) {
     return pk_arraycontains(py_arg(0), py_arg(1));
 }
 
+static void list__gc_mark(void* ud) {
+    List* self = ud;
+    for(int i = 0; i < self->count; i++) {
+        pk__mark_value(c11__at(py_TValue, self, i));
+    }
+}
+
 py_Type pk_list__register() {
     py_Type type =
         pk_newtype("list", tp_object, NULL, (void (*)(void*))c11_vector__dtor, false, true);
 
+    pk__tp_set_marker(type, list__gc_mark);
+
     py_bindmagic(type, __len__, list__len__);
     py_bindmagic(type, __eq__, list__eq__);
     py_bindmagic(type, __ne__, list__ne__);
@@ -443,10 +452,3 @@ py_Type pk_list__register() {
     py_setdict(py_tpobject(type), __hash__, py_None);
     return type;
 }
-
-void pk_list__mark(void* ud, void (*marker)(py_TValue*)) {
-    List* self = ud;
-    for(int i = 0; i < self->count; i++) {
-        marker(c11__at(py_TValue, self, i));
-    }
-}

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است