mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-19 19:10:17 +00:00
fix gc issues
This commit is contained in:
parent
3caca62f2c
commit
3e99f46273
@ -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);
|
@ -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);
|
||||
|
@ -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
|
||||
|
File diff suppressed because one or more lines are too long
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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,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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user