fix gc issues

This commit is contained in:
blueloveTH 2024-08-09 12:28:20 +08:00
parent 3caca62f2c
commit 3e99f46273
11 changed files with 83 additions and 45 deletions

View File

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

View File

@ -21,6 +21,7 @@ typedef struct py_TypeInfo {
c11_vector /*T=py_Name*/ annotated_fields; c11_vector /*T=py_Name*/ annotated_fields;
void (*on_end_subclass)(struct py_TypeInfo*); // backdoor for enum module void (*on_end_subclass)(struct py_TypeInfo*); // backdoor for enum module
void (*gc_mark)(void* ud);
/* Magic Slots */ /* Magic Slots */
py_TValue magic[64]; 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__parse_int_slice(py_Ref slice, int length, int* start, int* stop, int* step);
bool pk__normalize_index(int* index, int length); bool pk__normalize_index(int* index, int length);
void pk_list__mark(void* ud, void (*marker)(py_TValue*)); void pk__mark_value(py_TValue*);
void pk_dict__mark(void* ud, void (*marker)(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__self(int argc, py_Ref argv);
bool pk_wrapper__NotImplementedError(int argc, py_Ref argv); bool pk_wrapper__NotImplementedError(int argc, py_Ref argv);

View File

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

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,5 @@
#include "pocketpy/interpreter/frame.h" #include "pocketpy/interpreter/frame.h"
#include "pocketpy/interpreter/vm.h"
#include "pocketpy/objects/codeobject.h" #include "pocketpy/objects/codeobject.h"
#include "pocketpy/objects/object.h" #include "pocketpy/objects/object.h"
#include "pocketpy/pocketpy.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) { py_TValue* Frame__f_closure_try_get(Frame* self, py_Name name) {
if(!self->has_function) return NULL; if(!self->has_function) return NULL;
Function* ud = py_touserdata(self->p0); Function* ud = py_touserdata(self->p0);

View File

@ -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 pk_generator__register() {
py_Type type = pk_newtype("generator", tp_object, NULL, (py_Dtor)Generator__dtor, false, true); 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, __iter__, pk_wrapper__self);
py_bindmagic(type, __next__, generator__next__); py_bindmagic(type, __next__, generator__next__);
return type; return type;

View File

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

View File

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

View File

@ -1,3 +1,4 @@
#include "pocketpy/objects/codeobject.h"
#include "pocketpy/pocketpy.h" #include "pocketpy/pocketpy.h"
#include "pocketpy/common/utils.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); Function* ud = py_touserdata(argv);
if(!ud->closure) { if(!ud->closure) {
py_newnone(py_retval()); py_newnone(py_retval());
return true;
} }
py_Ref r0 = py_pushtmp(); py_Ref r0 = py_pushtmp();
py_Ref retval = py_pushtmp(); py_Ref retval = py_pushtmp();
@ -520,10 +520,18 @@ static bool function__closure__getter(int argc, py_Ref argv) {
return true; 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 pk_function__register() {
py_Type type = py_Type type =
pk_newtype("function", tp_object, NULL, (void (*)(void*))Function__dtor, false, true); 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); py_bindproperty(type, "__closure__", function__closure__getter, NULL);
return type; return type;
} }

View File

@ -433,9 +433,21 @@ static bool dict_values(int argc, py_Ref argv) {
return true; 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 pk_dict__register() {
py_Type type = pk_newtype("dict", tp_object, NULL, (void (*)(void*))Dict__dtor, false, false); 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, __new__, dict__new__);
py_bindmagic(type, __init__, dict__init__); py_bindmagic(type, __init__, dict__init__);
py_bindmagic(type, __getitem__, dict__getitem__); 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; 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);
}
}

View File

@ -408,10 +408,19 @@ static bool list__contains__(int argc, py_Ref argv) {
return pk_arraycontains(py_arg(0), py_arg(1)); 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 pk_list__register() {
py_Type type = py_Type type =
pk_newtype("list", tp_object, NULL, (void (*)(void*))c11_vector__dtor, false, true); 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, __len__, list__len__);
py_bindmagic(type, __eq__, list__eq__); py_bindmagic(type, __eq__, list__eq__);
py_bindmagic(type, __ne__, list__ne__); py_bindmagic(type, __ne__, list__ne__);
@ -443,10 +452,3 @@ py_Type pk_list__register() {
py_setdict(py_tpobject(type), __hash__, py_None); py_setdict(py_tpobject(type), __hash__, py_None);
return type; 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));
}
}