mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20:18 +00:00
backup
This commit is contained in:
parent
75d6b06509
commit
c416faf54d
@ -155,7 +155,7 @@ struct Container{
|
||||
}
|
||||
```
|
||||
|
||||
Add a magic method `_gc_mark() const` to your custom type.
|
||||
Add a magic method `_gc_mark(VM*) const` to your custom type.
|
||||
|
||||
```cpp
|
||||
struct Container{
|
||||
@ -163,7 +163,7 @@ struct Container{
|
||||
std::vector<PyVar> b;
|
||||
// ...
|
||||
|
||||
void _gc_mark() const{
|
||||
void _gc_mark(VM* vm) const{
|
||||
// mark a
|
||||
if(a) PK_OBJ_MARK(a);
|
||||
|
||||
|
@ -81,7 +81,7 @@ struct CodeObject {
|
||||
}
|
||||
|
||||
CodeObject(std::shared_ptr<SourceData> src, const Str& name);
|
||||
void _gc_mark() const;
|
||||
void _gc_mark(VM*) const;
|
||||
};
|
||||
|
||||
enum class FuncType{
|
||||
@ -118,7 +118,7 @@ struct FuncDecl {
|
||||
kwargs.push_back(KwArg{index, key, value});
|
||||
}
|
||||
|
||||
void _gc_mark() const;
|
||||
void _gc_mark(VM*) const;
|
||||
};
|
||||
|
||||
struct NativeFunc {
|
||||
@ -130,8 +130,9 @@ struct NativeFunc {
|
||||
NativeFunc(NativeFuncC f, int argc, any userdata={}): f(f), argc(argc), decl(nullptr), _userdata(std::move(userdata)) {}
|
||||
NativeFunc(NativeFuncC f, FuncDecl_ decl, any userdata={}): f(f), argc(-1), decl(decl), _userdata(std::move(userdata)) {}
|
||||
|
||||
void check_size(VM* vm, ArgsView args) const;
|
||||
PyVar call(VM* vm, ArgsView args) const { return f(vm, args); }
|
||||
void check_size(VM* vm, ArgsView args) const;
|
||||
void _gc_mark(VM*) const;
|
||||
};
|
||||
|
||||
struct Function{
|
||||
@ -142,33 +143,8 @@ struct Function{
|
||||
|
||||
explicit Function(FuncDecl_ decl, PyVar _module, PyVar _class, NameDict_ _closure):
|
||||
decl(decl), _module(_module), _class(_class), _closure(_closure) {}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Py_<Function> final: PyObject {
|
||||
Function _value;
|
||||
template<typename... Args>
|
||||
Py_(Args&&... args): PyObject(), _value(std::forward<Args>(args)...) {
|
||||
// _enable_instance_dict();
|
||||
}
|
||||
void _obj_gc_mark() override {
|
||||
_value.decl->_gc_mark();
|
||||
if(_value._closure != nullptr) _gc_mark_namedict(_value._closure.get());
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Py_<NativeFunc> final: PyObject {
|
||||
NativeFunc _value;
|
||||
template<typename... Args>
|
||||
Py_(Args&&... args): PyObject(), _value(std::forward<Args>(args)...) {
|
||||
// _enable_instance_dict();
|
||||
}
|
||||
void _obj_gc_mark() override {
|
||||
if(_value.decl != nullptr){
|
||||
_value.decl->_gc_mark();
|
||||
}
|
||||
}
|
||||
void _gc_mark(VM*) const;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
@ -169,6 +169,8 @@ inline constexpr bool is_floating_point_v = std::is_same_v<T, float> || std::is_
|
||||
inline const char* PK_HEX_TABLE = "0123456789abcdef";
|
||||
|
||||
struct PyObject;
|
||||
struct Frame;
|
||||
class VM;
|
||||
|
||||
// by default, only `int` and `float` enable SSO
|
||||
// users can specialize this template to enable SSO for other types
|
||||
|
@ -66,7 +66,7 @@ struct Dict{
|
||||
void clear();
|
||||
~Dict();
|
||||
|
||||
void _gc_mark() const;
|
||||
void _gc_mark(VM*) const;
|
||||
};
|
||||
|
||||
} // namespace pkpy
|
@ -117,12 +117,7 @@ struct Frame {
|
||||
|
||||
int curr_lineno() const { return co->lines[ip()].lineno; }
|
||||
|
||||
void _gc_mark() const {
|
||||
PK_OBJ_MARK(_module);
|
||||
co->_gc_mark();
|
||||
// Frame could be stored in a generator, so mark _callable for safety
|
||||
if(_callable != nullptr) PK_OBJ_MARK(_callable);
|
||||
}
|
||||
void _gc_mark(VM* vm) const;
|
||||
};
|
||||
|
||||
struct LinkedFrame{
|
||||
|
@ -61,6 +61,8 @@ struct ManagedHeap{
|
||||
return obj;
|
||||
}
|
||||
|
||||
void _delete(PyVar);
|
||||
|
||||
#if PK_DEBUG_GC_STATS
|
||||
inline static std::map<Type, int> deleted;
|
||||
#endif
|
||||
@ -70,7 +72,6 @@ struct ManagedHeap{
|
||||
bool _should_auto_collect() const { return gc_counter >= gc_threshold; }
|
||||
int collect();
|
||||
void mark();
|
||||
~ManagedHeap();
|
||||
};
|
||||
|
||||
} // namespace pkpy
|
||||
|
@ -23,7 +23,7 @@ struct ArrayIter{
|
||||
ArrayIter(PyVar ref, PyVar* begin, PyVar* end)
|
||||
: ref(ref), begin(begin), end(end), current(begin) {}
|
||||
|
||||
void _gc_mark() const{ PK_OBJ_MARK(ref); }
|
||||
void _gc_mark(VM* vm) const{ PK_OBJ_MARK(ref); }
|
||||
static void _register(VM* vm, PyVar mod, PyVar type);
|
||||
};
|
||||
|
||||
@ -31,7 +31,7 @@ struct StringIter{
|
||||
PyVar ref;
|
||||
int i; // byte index
|
||||
StringIter(PyVar ref) : ref(ref), i(0) {}
|
||||
void _gc_mark() const{ PK_OBJ_MARK(ref); }
|
||||
void _gc_mark(VM* vm) const{ PK_OBJ_MARK(ref); }
|
||||
static void _register(VM* vm, PyVar mod, PyVar type);
|
||||
};
|
||||
|
||||
@ -44,8 +44,8 @@ struct Generator{
|
||||
for(PyVar obj: buffer) s_backup.push_back(obj);
|
||||
}
|
||||
|
||||
void _gc_mark() const{
|
||||
frame._gc_mark();
|
||||
void _gc_mark(VM* vm) const{
|
||||
frame._gc_mark(vm);
|
||||
for(PyVar obj: s_backup) PK_OBJ_MARK(obj);
|
||||
}
|
||||
|
||||
@ -59,7 +59,7 @@ struct DictItemsIter{
|
||||
DictItemsIter(PyVar ref) : ref(ref) {
|
||||
i = PK_OBJ_GET(Dict, ref)._head_idx;
|
||||
}
|
||||
void _gc_mark() const{ PK_OBJ_MARK(ref); }
|
||||
void _gc_mark(VM* vm) const{ PK_OBJ_MARK(ref); }
|
||||
static void _register(VM* vm, PyVar mod, PyVar type);
|
||||
};
|
||||
|
||||
|
@ -6,9 +6,6 @@
|
||||
|
||||
namespace pkpy {
|
||||
|
||||
struct Frame;
|
||||
class VM;
|
||||
|
||||
#if PK_ENABLE_STD_FUNCTION
|
||||
using NativeFuncC = std::function<PyVar(VM*, ArgsView)>;
|
||||
#else
|
||||
@ -25,22 +22,26 @@ struct BoundMethod {
|
||||
PyVar self;
|
||||
PyVar func;
|
||||
BoundMethod(PyVar self, PyVar func) : self(self), func(func) {}
|
||||
void _gc_mark(VM*) const;
|
||||
};
|
||||
|
||||
struct StaticMethod{
|
||||
PyVar func;
|
||||
StaticMethod(PyVar func) : func(func) {}
|
||||
void _gc_mark(VM*) const;
|
||||
};
|
||||
|
||||
struct ClassMethod{
|
||||
PyVar func;
|
||||
ClassMethod(PyVar func) : func(func) {}
|
||||
void _gc_mark(VM*) const;
|
||||
};
|
||||
|
||||
struct Property{
|
||||
PyVar getter;
|
||||
PyVar setter;
|
||||
Property(PyVar getter, PyVar setter) : getter(getter), setter(setter) {}
|
||||
void _gc_mark(VM*) const;
|
||||
};
|
||||
|
||||
struct Range {
|
||||
@ -53,6 +54,7 @@ struct StarWrapper{
|
||||
int level; // either 1 or 2
|
||||
PyVar obj;
|
||||
StarWrapper(int level, PyVar obj) : level(level), obj(obj) {}
|
||||
void _gc_mark(VM*) const;
|
||||
};
|
||||
|
||||
struct Bytes{
|
||||
@ -84,13 +86,19 @@ struct Bytes{
|
||||
~Bytes(){ delete[] _data;}
|
||||
};
|
||||
|
||||
using Super = std::pair<PyVar, Type>;
|
||||
struct Super{
|
||||
PyVar first;
|
||||
Type second;
|
||||
Super(PyVar first, Type second) : first(first), second(second) {}
|
||||
void _gc_mark(VM*) const;
|
||||
};
|
||||
|
||||
struct Slice {
|
||||
PyVar start;
|
||||
PyVar stop;
|
||||
PyVar step;
|
||||
Slice(PyVar start, PyVar stop, PyVar step) : start(start), stop(stop), step(step) {}
|
||||
void _gc_mark(VM*) const;
|
||||
};
|
||||
|
||||
struct PyObject{
|
||||
@ -98,6 +106,8 @@ struct PyObject{
|
||||
bool gc_marked; // whether this object is marked
|
||||
NameDict* _attr;
|
||||
|
||||
void* _value_ptr() noexcept { return 1 + &_attr; }
|
||||
|
||||
bool is_attr_valid() const noexcept { return _attr != nullptr; }
|
||||
|
||||
NameDict& attr() {
|
||||
@ -110,9 +120,6 @@ struct PyObject{
|
||||
return (*_attr)[name];
|
||||
}
|
||||
|
||||
virtual void _obj_gc_mark() = 0;
|
||||
virtual ~PyObject();
|
||||
|
||||
PyObject() : gc_enabled(true), gc_marked(false), _attr(nullptr) {}
|
||||
|
||||
void _enable_instance_dict() {
|
||||
@ -124,6 +131,9 @@ struct PyObject{
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline constexpr int py_sizeof = sizeof(PyObject) + sizeof(T);
|
||||
|
||||
const int kTpIntIndex = 3;
|
||||
const int kTpFloatIndex = 4;
|
||||
|
||||
@ -143,14 +153,7 @@ template <typename T>
|
||||
struct Py_ final: PyObject {
|
||||
static_assert(!std::is_reference_v<T>);
|
||||
static_assert(!is_sso_v<T>);
|
||||
|
||||
T _value;
|
||||
void _obj_gc_mark() override {
|
||||
if constexpr (has_gc_marker<T>::value) {
|
||||
_value._gc_mark();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
Py_(Args&&... args) : PyObject(), _value(std::forward<Args>(args)...) { }
|
||||
};
|
||||
@ -159,9 +162,9 @@ struct MappingProxy{
|
||||
PyVar obj;
|
||||
MappingProxy(PyVar obj) : obj(obj) {}
|
||||
NameDict& attr() { return obj->attr(); }
|
||||
void _gc_mark(VM*) const;
|
||||
};
|
||||
|
||||
void _gc_mark_namedict(NameDict*);
|
||||
StrName _type_name(VM* vm, Type type);
|
||||
template<typename T> T to_void_p(VM*, PyVar);
|
||||
PyVar from_void_p(VM*, void*);
|
||||
@ -181,9 +184,7 @@ obj_get_t<T> PyVar::obj_get(){
|
||||
|
||||
#define PK_OBJ_MARK(obj) \
|
||||
if(!is_tagged(obj) && !(obj)->gc_marked) { \
|
||||
(obj)->gc_marked = true; \
|
||||
(obj)->_obj_gc_mark(); \
|
||||
if((obj)->is_attr_valid()) _gc_mark_namedict((obj)->_attr); \
|
||||
vm->__obj_gc_mark(obj); \
|
||||
}
|
||||
|
||||
#define VAR(x) py_var(vm, x)
|
||||
@ -202,109 +203,12 @@ inline bool try_cast_int(PyVar obj, i64* val) noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
template<>
|
||||
struct Py_<List> final: PyObject {
|
||||
List _value;
|
||||
Py_(List&& val): PyObject(), _value(std::move(val)) {}
|
||||
Py_(const List& val): PyObject(), _value(val) {}
|
||||
|
||||
void _obj_gc_mark() override {
|
||||
for(PyVar obj: _value) PK_OBJ_MARK(obj);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Py_<Tuple> final: PyObject {
|
||||
Tuple _value;
|
||||
Py_(Tuple&& val): PyObject(), _value(std::move(val)) {}
|
||||
Py_(const Tuple& val): PyObject(), _value(val) {}
|
||||
|
||||
void _obj_gc_mark() override {
|
||||
for(PyVar obj: _value) PK_OBJ_MARK(obj);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Py_<MappingProxy> final: PyObject {
|
||||
MappingProxy _value;
|
||||
Py_(MappingProxy val): PyObject(), _value(val) {}
|
||||
void _obj_gc_mark() override {
|
||||
PK_OBJ_MARK(_value.obj);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Py_<BoundMethod> final: PyObject {
|
||||
BoundMethod _value;
|
||||
Py_(BoundMethod val): PyObject(), _value(val) {}
|
||||
void _obj_gc_mark() override {
|
||||
PK_OBJ_MARK(_value.self);
|
||||
PK_OBJ_MARK(_value.func);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Py_<StarWrapper> final: PyObject {
|
||||
StarWrapper _value;
|
||||
Py_(StarWrapper val): PyObject(), _value(val) {}
|
||||
void _obj_gc_mark() override {
|
||||
PK_OBJ_MARK(_value.obj);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Py_<StaticMethod> final: PyObject {
|
||||
StaticMethod _value;
|
||||
Py_(StaticMethod val): PyObject(), _value(val) {}
|
||||
void _obj_gc_mark() override {
|
||||
PK_OBJ_MARK(_value.func);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Py_<ClassMethod> final: PyObject {
|
||||
ClassMethod _value;
|
||||
Py_(ClassMethod val): PyObject(), _value(val) {}
|
||||
void _obj_gc_mark() override {
|
||||
PK_OBJ_MARK(_value.func);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Py_<Property> final: PyObject {
|
||||
Property _value;
|
||||
Py_(Property val): PyObject(), _value(val) {}
|
||||
void _obj_gc_mark() override {
|
||||
PK_OBJ_MARK(_value.getter);
|
||||
PK_OBJ_MARK(_value.setter);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Py_<Slice> final: PyObject {
|
||||
Slice _value;
|
||||
Py_(Slice val): PyObject(), _value(val) {}
|
||||
void _obj_gc_mark() override {
|
||||
PK_OBJ_MARK(_value.start);
|
||||
PK_OBJ_MARK(_value.stop);
|
||||
PK_OBJ_MARK(_value.step);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Py_<Super> final: PyObject {
|
||||
Super _value;
|
||||
template<typename... Args>
|
||||
Py_(Args&&... args): PyObject(), _value(std::forward<Args>(args)...) {}
|
||||
void _obj_gc_mark() override {
|
||||
PK_OBJ_MARK(_value.first);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Py_<DummyInstance> final: PyObject {
|
||||
Py_(): PyObject() { _enable_instance_dict(); }
|
||||
void _obj_gc_mark() override {}
|
||||
Py_(): PyObject() {
|
||||
_enable_instance_dict();
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
@ -313,7 +217,6 @@ struct Py_<Type> final: PyObject {
|
||||
Py_(Type val): PyObject(), _value(val) {
|
||||
_enable_instance_dict(PK_TYPE_ATTR_LOAD_FACTOR);
|
||||
}
|
||||
void _obj_gc_mark() override {}
|
||||
};
|
||||
|
||||
template<>
|
||||
@ -321,7 +224,6 @@ struct Py_<DummyModule> final: PyObject {
|
||||
Py_(): PyObject() {
|
||||
_enable_instance_dict(PK_TYPE_ATTR_LOAD_FACTOR);
|
||||
}
|
||||
void _obj_gc_mark() override {}
|
||||
};
|
||||
|
||||
extern PyVar const PY_NULL;
|
||||
|
@ -7,7 +7,10 @@
|
||||
|
||||
namespace pkpy {
|
||||
|
||||
using List = pod_vector<PyVar, 4>;
|
||||
struct List: pod_vector<PyVar, 4>{
|
||||
using pod_vector<PyVar, 4>::pod_vector;
|
||||
void _gc_mark(VM*) const;
|
||||
};
|
||||
|
||||
struct Tuple {
|
||||
static const int INLINED_SIZE = 4;
|
||||
@ -35,6 +38,7 @@ struct Tuple {
|
||||
PyVar* begin() const { return _args; }
|
||||
PyVar* end() const { return _args + _size; }
|
||||
PyVar* data() const { return _args; }
|
||||
void _gc_mark(VM*) const;
|
||||
};
|
||||
|
||||
// a lightweight view for function args, it does not own the memory
|
||||
|
@ -42,11 +42,35 @@ struct NextBreakpoint{
|
||||
#endif
|
||||
|
||||
struct PyTypeInfo{
|
||||
struct Vt{
|
||||
void (*_dtor)(void*);
|
||||
void (*_gc_mark)(void*, VM*);
|
||||
|
||||
Vt(): _dtor(nullptr), _gc_mark(nullptr) {}
|
||||
|
||||
template<typename T>
|
||||
inline static Vt get(){
|
||||
static_assert(std::is_same_v<T, std::decay_t<T>>);
|
||||
Vt vt;
|
||||
if constexpr(!std::is_trivially_destructible_v<T>){
|
||||
vt._dtor = [](void* p){ ((T*)p)->~T(); };
|
||||
}
|
||||
if constexpr(has_gc_marker<T>::value){
|
||||
vt._gc_mark = [](void* p, VM* vm){ ((T*)p)->_gc_mark(vm); };
|
||||
}
|
||||
return vt;
|
||||
}
|
||||
};
|
||||
|
||||
PyVar obj; // never be garbage collected
|
||||
Type base;
|
||||
PyVar mod; // never be garbage collected
|
||||
StrName name;
|
||||
bool subclass_enabled;
|
||||
Vt vt;
|
||||
|
||||
PyTypeInfo(PyVar obj, Type base, PyVar mod, StrName name, bool subclass_enabled, Vt vt={}):
|
||||
obj(obj), base(base), mod(mod), name(name), subclass_enabled(subclass_enabled), vt(vt) {}
|
||||
|
||||
std::vector<StrName> annotated_fields = {};
|
||||
|
||||
@ -386,7 +410,12 @@ public:
|
||||
|
||||
#if PK_REGION("User Type Registration")
|
||||
PyVar new_module(Str name, Str package="");
|
||||
PyVar new_type_object(PyVar mod, StrName name, Type base, bool subclass_enabled=true);
|
||||
PyVar new_type_object(PyVar mod, StrName name, Type base, bool subclass_enabled, PyTypeInfo::Vt vt={});
|
||||
|
||||
template<typename T>
|
||||
PyVar new_type_object(PyVar mod, StrName name, Type base, bool subclass_enabled){
|
||||
return new_type_object(mod, name, base, subclass_enabled, PyTypeInfo::Vt::get<T>());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Type _tp_user(){ return _find_type_in_cxx_typeid_map<T>(); }
|
||||
@ -455,6 +484,7 @@ public:
|
||||
PyVar __pack_next_retval(unsigned);
|
||||
PyVar __minmax_reduce(bool (VM::*op)(PyVar, PyVar), PyVar args, PyVar key);
|
||||
bool __py_bool_non_trivial(PyVar);
|
||||
void __obj_gc_mark(PyVar);
|
||||
};
|
||||
|
||||
|
||||
@ -595,7 +625,7 @@ __T _py_cast(VM* vm, PyVar obj) { return _py_cast__internal<__T, false>(vm, obj)
|
||||
|
||||
template<typename T>
|
||||
PyVar VM::register_user_class(PyVar mod, StrName name, RegisterFunc _register, Type base, bool subclass_enabled){
|
||||
PyVar type = new_type_object(mod, name, base, subclass_enabled);
|
||||
PyVar type = new_type_object(mod, name, base, subclass_enabled, PyTypeInfo::Vt::get<T>());
|
||||
mod->attr().set(name, type);
|
||||
_cxx_typeid_map[typeid(T)] = PK_OBJ_GET(Type, type);
|
||||
_register(this, mod, type);
|
||||
|
@ -332,7 +332,7 @@ struct Array2d{
|
||||
});
|
||||
}
|
||||
|
||||
void _gc_mark() const{
|
||||
void _gc_mark(VM* vm) const{
|
||||
for(int i = 0; i < numel; i++) PK_OBJ_MARK(data[i]);
|
||||
}
|
||||
|
||||
@ -349,7 +349,7 @@ struct Array2dIter{
|
||||
int i;
|
||||
Array2dIter(PyVar ref) : ref(ref), i(0) {}
|
||||
|
||||
void _gc_mark() const{ PK_OBJ_MARK(ref); }
|
||||
void _gc_mark(VM* vm) const{ PK_OBJ_MARK(ref); }
|
||||
|
||||
static void _register(VM* vm, PyVar mod, PyVar type){
|
||||
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) { return _0; });
|
||||
|
@ -924,7 +924,7 @@ __NEXT_STEP:
|
||||
PyVar _0 = POPX(); // super
|
||||
if(_0 == None) _0 = _t(tp_object);
|
||||
check_type(_0, tp_type);
|
||||
__curr_class = new_type_object(frame->_module, _name, PK_OBJ_GET(Type, _0));
|
||||
__curr_class = new_type_object(frame->_module, _name, PK_OBJ_GET(Type, _0), true);
|
||||
} DISPATCH()
|
||||
case OP_END_CLASS: {
|
||||
PK_ASSERT(__curr_class != nullptr);
|
||||
|
@ -195,7 +195,7 @@ void add_module_c(VM* vm){
|
||||
T val = CAST(T, args[0]); \
|
||||
return vm->new_user_object<Struct>(&val, sizeof(T)); \
|
||||
}); \
|
||||
type = vm->new_type_object(mod, CNAME "_p", vm->_tp_user<VoidP>()); \
|
||||
type = vm->new_type_object(mod, CNAME "_p", vm->_tp_user<VoidP>(), true); \
|
||||
mod->attr().set(CNAME "_p", type); \
|
||||
type_t = PK_OBJ_GET(Type, type); \
|
||||
vm->bind_func(type, "read", 1, [](VM* vm, ArgsView args){ \
|
||||
|
@ -7,14 +7,8 @@ namespace pkpy{
|
||||
blocks.push_back(CodeBlock(CodeBlockType::NO_BLOCK, -1, 0, 0));
|
||||
}
|
||||
|
||||
void CodeObject::_gc_mark() const {
|
||||
for(PyVar v : consts) PK_OBJ_MARK(v);
|
||||
for(auto& decl: func_decls) decl->_gc_mark();
|
||||
}
|
||||
|
||||
struct PySignalObject: PyObject {
|
||||
PySignalObject() : PyObject() { gc_enabled = false; }
|
||||
void _obj_gc_mark() override {}
|
||||
};
|
||||
|
||||
PyVar const PY_NULL(Type(), new PySignalObject());
|
||||
|
@ -18,7 +18,7 @@ namespace pkpy
|
||||
{
|
||||
this->is_reversed = true;
|
||||
}
|
||||
void _gc_mark() const { PK_OBJ_MARK(ref); }
|
||||
void _gc_mark(VM* vm) const { PK_OBJ_MARK(ref); }
|
||||
static void _register(VM *vm, PyVar mod, PyVar type);
|
||||
};
|
||||
void PyDequeIter::_register(VM *vm, PyVar mod, PyVar type)
|
||||
@ -53,7 +53,7 @@ namespace pkpy
|
||||
int findIndex(VM *vm, PyVar obj, int start, int stop); // find the index of the given object in the deque
|
||||
// Special methods
|
||||
static void _register(VM *vm, PyVar mod, PyVar type); // register the type
|
||||
void _gc_mark() const; // needed for container types, mark all objects in the deque for gc
|
||||
void _gc_mark(VM*) const; // needed for container types, mark all objects in the deque for gc
|
||||
};
|
||||
void PyDeque::_register(VM *vm, PyVar mod, PyVar type)
|
||||
{
|
||||
@ -532,7 +532,7 @@ namespace pkpy
|
||||
}
|
||||
}
|
||||
/// @brief marks the deque items for garbage collection
|
||||
void PyDeque::_gc_mark() const
|
||||
void PyDeque::_gc_mark(VM* vm) const
|
||||
{
|
||||
for (PyVar obj : this->dequeItems)
|
||||
PK_OBJ_MARK(obj);
|
||||
|
@ -169,12 +169,4 @@ namespace pkpy{
|
||||
pool128_dealloc(_items);
|
||||
pool64_dealloc(_nodes);
|
||||
}
|
||||
|
||||
void Dict::_gc_mark() const{
|
||||
apply([](PyVar k, PyVar v){
|
||||
PK_OBJ_MARK(k);
|
||||
PK_OBJ_MARK(v);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace pkpy
|
15
src/gc.cpp
15
src/gc.cpp
@ -14,8 +14,7 @@ namespace pkpy{
|
||||
deleted[obj.type] += 1;
|
||||
#endif
|
||||
if(_gc_on_delete) _gc_on_delete(vm, obj);
|
||||
obj->~PyObject();
|
||||
pool128_dealloc(obj.get());
|
||||
_delete(obj);
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,16 +53,4 @@ namespace pkpy{
|
||||
int freed = sweep();
|
||||
return freed;
|
||||
}
|
||||
|
||||
ManagedHeap::~ManagedHeap(){
|
||||
for(PyVar obj: _no_gc) { obj->~PyObject(); pool128_dealloc(obj.get()); }
|
||||
for(PyVar obj: gen) { obj->~PyObject(); pool128_dealloc(obj.get()); }
|
||||
}
|
||||
|
||||
|
||||
void FuncDecl::_gc_mark() const{
|
||||
code->_gc_mark();
|
||||
for(int i=0; i<kwargs.size(); i++) PK_OBJ_MARK(kwargs[i].value);
|
||||
}
|
||||
|
||||
} // namespace pkpy
|
@ -46,11 +46,4 @@ namespace pkpy{
|
||||
_size = 0;
|
||||
return {p, size};
|
||||
}
|
||||
|
||||
PyObject::~PyObject(){
|
||||
if(_attr == nullptr) return;
|
||||
_attr->~NameDict();
|
||||
pool128_dealloc(_attr);
|
||||
}
|
||||
|
||||
} // namespace pkpy
|
215
src/vm.cpp
215
src/vm.cpp
@ -205,21 +205,14 @@ namespace pkpy{
|
||||
return exec(source, "<eval>", EVAL_MODE);
|
||||
}
|
||||
|
||||
PyVar VM::new_type_object(PyVar mod, StrName name, Type base, bool subclass_enabled){
|
||||
PyVar VM::new_type_object(PyVar mod, StrName name, Type base, bool subclass_enabled, PyTypeInfo::Vt vt){
|
||||
PyVar obj = heap._new<Type>(tp_type, Type(_all_types.size()));
|
||||
const PyTypeInfo& base_info = _all_types[base];
|
||||
if(!base_info.subclass_enabled){
|
||||
Str error = _S("type ", base_info.name.escape(), " is not `subclass_enabled`");
|
||||
throw std::runtime_error(error.c_str());
|
||||
}
|
||||
PyTypeInfo info{
|
||||
obj,
|
||||
base,
|
||||
mod,
|
||||
name,
|
||||
subclass_enabled,
|
||||
};
|
||||
_all_types.push_back(info);
|
||||
_all_types.emplace_back(obj, base, mod, name, subclass_enabled, vt);
|
||||
return obj;
|
||||
}
|
||||
|
||||
@ -404,6 +397,10 @@ namespace pkpy{
|
||||
}
|
||||
|
||||
VM::~VM() {
|
||||
// clear managed heap
|
||||
for(PyVar obj: heap.gen) heap._delete(obj);
|
||||
for(PyVar obj: heap._no_gc) heap._delete(obj);
|
||||
// clear everything
|
||||
callstack.clear();
|
||||
s_data.clear();
|
||||
_all_types.clear();
|
||||
@ -430,6 +427,17 @@ bool VM::__py_bool_non_trivial(PyVar obj){
|
||||
return true;
|
||||
}
|
||||
|
||||
void VM::__obj_gc_mark(PyVar obj){
|
||||
obj->gc_marked = true;
|
||||
const PyTypeInfo* ti = _tp_info(obj);
|
||||
if(ti->vt._gc_mark) ti->vt._gc_mark(obj->_value_ptr(), this);
|
||||
if(obj->is_attr_valid()){
|
||||
obj->attr().apply([this](StrName _, PyVar obj){
|
||||
PK_OBJ_MARK(obj);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
List VM::py_list(PyVar it){
|
||||
auto _lock = heap.gc_scope_lock();
|
||||
it = py_iter(it);
|
||||
@ -823,49 +831,49 @@ void VM::__log_s_data(const char* title) {
|
||||
#endif
|
||||
|
||||
void VM::__init_builtin_types(){
|
||||
_all_types.push_back({nullptr, Type(), nullptr, "", false}); // 0 is not used
|
||||
_all_types.push_back({heap._new<Type>(tp_type, tp_object), Type(), nullptr, "object", true});
|
||||
_all_types.push_back({heap._new<Type>(tp_type, tp_type), tp_object, nullptr, "type", false});
|
||||
_all_types.emplace_back(nullptr, Type(), nullptr, "", false); // 0 is not used
|
||||
_all_types.emplace_back(heap._new<Type>(tp_type, tp_object), Type(), nullptr, "object", true);
|
||||
_all_types.emplace_back(heap._new<Type>(tp_type, tp_type), tp_object, nullptr, "type", false);
|
||||
|
||||
auto _new_type = [this](const char* name, Type base=tp_object, bool subclass_enabled=false){
|
||||
PyVar obj = new_type_object(nullptr, name, base, subclass_enabled);
|
||||
return PK_OBJ_GET(Type, obj);
|
||||
auto validate = [](Type type, PyVar ret){
|
||||
Type ret_t = PK_OBJ_GET(Type, ret);
|
||||
if(ret_t != type) exit(-3);
|
||||
};
|
||||
|
||||
if(tp_int != _new_type("int")) exit(-3);
|
||||
if((tp_float != _new_type("float"))) exit(-3);
|
||||
validate(tp_int, new_type_object(nullptr, "int", tp_object, false));
|
||||
validate(tp_float, new_type_object(nullptr, "float", tp_object, false));
|
||||
validate(tp_bool, new_type_object(nullptr, "bool", tp_object, false));
|
||||
|
||||
if(tp_bool != _new_type("bool")) exit(-3);
|
||||
if(tp_str != _new_type("str")) exit(-3);
|
||||
if(tp_list != _new_type("list")) exit(-3);
|
||||
if(tp_tuple != _new_type("tuple")) exit(-3);
|
||||
validate(tp_str, new_type_object<Str>(nullptr, "str", tp_object, false));
|
||||
validate(tp_list, new_type_object<List>(nullptr, "list", tp_object, false));
|
||||
validate(tp_tuple, new_type_object<Tuple>(nullptr, "tuple", tp_object, false));
|
||||
|
||||
if(tp_slice != _new_type("slice")) exit(-3);
|
||||
if(tp_range != _new_type("range")) exit(-3);
|
||||
if(tp_module != _new_type("module")) exit(-3);
|
||||
if(tp_function != _new_type("function")) exit(-3);
|
||||
if(tp_native_func != _new_type("native_func")) exit(-3);
|
||||
if(tp_bound_method != _new_type("bound_method")) exit(-3);
|
||||
validate(tp_slice, new_type_object<Slice>(nullptr, "slice", tp_object, false));
|
||||
validate(tp_range, new_type_object<Range>(nullptr, "range", tp_object, false));
|
||||
validate(tp_module, new_type_object<DummyModule>(nullptr, "module", tp_object, false));
|
||||
validate(tp_function, new_type_object<Function>(nullptr, "function", tp_object, false));
|
||||
validate(tp_native_func, new_type_object<NativeFunc>(nullptr, "native_func", tp_object, false));
|
||||
validate(tp_bound_method, new_type_object<BoundMethod>(nullptr, "bound_method", tp_object, false));
|
||||
|
||||
if(tp_super != _new_type("super")) exit(-3);
|
||||
if(tp_exception != _new_type("Exception", tp_object, true)) exit(-3);
|
||||
if(tp_bytes != _new_type("bytes")) exit(-3);
|
||||
if(tp_mappingproxy != _new_type("mappingproxy")) exit(-3);
|
||||
if(tp_dict != _new_type("dict", tp_object, true)) exit(-3); // dict can be subclassed
|
||||
if(tp_property != _new_type("property")) exit(-3);
|
||||
if(tp_star_wrapper != _new_type("_star_wrapper")) exit(-3);
|
||||
validate(tp_super, new_type_object<Super>(nullptr, "super", tp_object, false));
|
||||
validate(tp_exception, new_type_object<Exception>(nullptr, "Exception", tp_object, true));
|
||||
validate(tp_bytes, new_type_object<Bytes>(nullptr, "bytes", tp_object, false));
|
||||
validate(tp_mappingproxy, new_type_object<MappingProxy>(nullptr, "mappingproxy", tp_object, false));
|
||||
validate(tp_dict, new_type_object<Dict>(nullptr, "dict", tp_object, true));
|
||||
validate(tp_property, new_type_object<Property>(nullptr, "property", tp_object, false));
|
||||
validate(tp_star_wrapper, new_type_object<StarWrapper>(nullptr, "_star_wrapper", tp_object, false));
|
||||
|
||||
if(tp_staticmethod != _new_type("staticmethod")) exit(-3);
|
||||
if(tp_classmethod != _new_type("classmethod")) exit(-3);
|
||||
validate(tp_staticmethod, new_type_object<StaticMethod>(nullptr, "staticmethod", tp_object, false));
|
||||
validate(tp_classmethod, new_type_object<ClassMethod>(nullptr, "classmethod", tp_object, false));
|
||||
|
||||
if(tp_none != _new_type("NoneType")) exit(-3);
|
||||
if(tp_not_implemented != _new_type("NotImplementedType")) exit(-3);
|
||||
if(tp_ellipsis != _new_type("ellipsis")) exit(-3);
|
||||
validate(tp_none, new_type_object(nullptr, "NoneType", tp_object, false));
|
||||
validate(tp_not_implemented, new_type_object(nullptr, "NotImplementedType", tp_object, false));
|
||||
validate(tp_ellipsis, new_type_object(nullptr, "ellipsis", tp_object, false));
|
||||
|
||||
// SyntaxError and IndentationError must be created here
|
||||
Type tp_syntax_error = _new_type("SyntaxError", tp_exception, true);
|
||||
Type tp_indentation_error = _new_type("IndentationError", tp_syntax_error, true);
|
||||
this->StopIteration = _all_types[_new_type("StopIteration", tp_exception)].obj;
|
||||
PyVar SyntaxError = new_type_object(nullptr, "SyntaxError", tp_exception, true);
|
||||
PyVar IndentationError = new_type_object(nullptr, "IndentationError", PK_OBJ_GET(Type, SyntaxError), true);
|
||||
this->StopIteration = new_type_object(nullptr, "StopIteration", tp_exception, true);
|
||||
|
||||
this->builtins = new_module("builtins");
|
||||
|
||||
@ -886,8 +894,8 @@ void VM::__init_builtin_types(){
|
||||
builtins->attr().set("NotImplemented", NotImplemented);
|
||||
builtins->attr().set("slice", _t(tp_slice));
|
||||
builtins->attr().set("Exception", _t(tp_exception));
|
||||
builtins->attr().set("SyntaxError", _t(tp_syntax_error));
|
||||
builtins->attr().set("IndentationError", _t(tp_indentation_error));
|
||||
builtins->attr().set("SyntaxError", SyntaxError);
|
||||
builtins->attr().set("IndentationError", IndentationError);
|
||||
|
||||
__post_init_builtin_types();
|
||||
this->_main = new_module("__main__");
|
||||
@ -1414,26 +1422,11 @@ void VM::__raise_exc(bool re_raise){
|
||||
}
|
||||
}
|
||||
|
||||
void ManagedHeap::mark() {
|
||||
for(PyVar obj: _no_gc) PK_OBJ_MARK(obj);
|
||||
vm->callstack.apply([](Frame& frame){ frame._gc_mark(); });
|
||||
for(PyVar obj: vm->s_data) PK_OBJ_MARK(obj);
|
||||
for(auto [_, co]: vm->__cached_codes) co->_gc_mark();
|
||||
if(vm->__last_exception) PK_OBJ_MARK(vm->__last_exception);
|
||||
if(vm->__curr_class) PK_OBJ_MARK(vm->__curr_class);
|
||||
if(vm->__c.error != nullptr) PK_OBJ_MARK(vm->__c.error);
|
||||
if(_gc_marker_ex) _gc_marker_ex(vm);
|
||||
}
|
||||
|
||||
StrName _type_name(VM *vm, Type type){
|
||||
return vm->_all_types[type].name;
|
||||
}
|
||||
|
||||
void _gc_mark_namedict(NameDict* t){
|
||||
t->apply([](StrName name, PyVar obj){
|
||||
PK_OBJ_MARK(obj);
|
||||
});
|
||||
}
|
||||
|
||||
void VM::bind__getitem__(Type type, PyVar (*f)(VM*, PyVar, PyVar)){
|
||||
_all_types[type].m__getitem__ = f;
|
||||
@ -1757,4 +1750,108 @@ void VM::__breakpoint(){
|
||||
#endif
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
void Function::_gc_mark(VM* vm) const{
|
||||
decl->_gc_mark(vm);
|
||||
if(_closure){
|
||||
_closure->apply([=](StrName _, PyVar obj){
|
||||
PK_OBJ_MARK(obj);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void NativeFunc::_gc_mark(VM* vm) const{
|
||||
if(decl) decl->_gc_mark(vm);
|
||||
}
|
||||
|
||||
void FuncDecl::_gc_mark(VM* vm) const{
|
||||
code->_gc_mark(vm);
|
||||
for(int i=0; i<kwargs.size(); i++) PK_OBJ_MARK(kwargs[i].value);
|
||||
}
|
||||
|
||||
void List::_gc_mark(VM* vm) const{
|
||||
for(PyVar obj: *this) PK_OBJ_MARK(obj);
|
||||
}
|
||||
|
||||
void Tuple::_gc_mark(VM* vm) const{
|
||||
for(PyVar obj: *this) PK_OBJ_MARK(obj);
|
||||
}
|
||||
|
||||
void MappingProxy::_gc_mark(VM* vm) const{
|
||||
PK_OBJ_MARK(obj);
|
||||
}
|
||||
|
||||
void BoundMethod::_gc_mark(VM* vm) const{
|
||||
PK_OBJ_MARK(func);
|
||||
PK_OBJ_MARK(self);
|
||||
}
|
||||
|
||||
void StarWrapper::_gc_mark(VM* vm) const{
|
||||
PK_OBJ_MARK(obj);
|
||||
}
|
||||
|
||||
void StaticMethod::_gc_mark(VM* vm) const{
|
||||
PK_OBJ_MARK(func);
|
||||
}
|
||||
|
||||
void ClassMethod::_gc_mark(VM* vm) const{
|
||||
PK_OBJ_MARK(func);
|
||||
}
|
||||
|
||||
void Property::_gc_mark(VM* vm) const{
|
||||
PK_OBJ_MARK(getter);
|
||||
PK_OBJ_MARK(setter);
|
||||
}
|
||||
|
||||
void Slice::_gc_mark(VM* vm) const{
|
||||
PK_OBJ_MARK(start);
|
||||
PK_OBJ_MARK(stop);
|
||||
PK_OBJ_MARK(step);
|
||||
}
|
||||
|
||||
void Super::_gc_mark(VM* vm) const{
|
||||
PK_OBJ_MARK(first);
|
||||
}
|
||||
|
||||
void Frame::_gc_mark(VM* vm) const {
|
||||
PK_OBJ_MARK(_module);
|
||||
co->_gc_mark(vm);
|
||||
// Frame could be stored in a generator, so mark _callable for safety
|
||||
if(_callable != nullptr) PK_OBJ_MARK(_callable);
|
||||
}
|
||||
|
||||
void ManagedHeap::mark() {
|
||||
for(PyVar obj: _no_gc) PK_OBJ_MARK(obj);
|
||||
vm->callstack.apply([this](Frame& frame){ frame._gc_mark(vm); });
|
||||
for(PyVar obj: vm->s_data) PK_OBJ_MARK(obj);
|
||||
for(auto [_, co]: vm->__cached_codes) co->_gc_mark(vm);
|
||||
if(vm->__last_exception) PK_OBJ_MARK(vm->__last_exception);
|
||||
if(vm->__curr_class) PK_OBJ_MARK(vm->__curr_class);
|
||||
if(vm->__c.error != nullptr) PK_OBJ_MARK(vm->__c.error);
|
||||
if(_gc_marker_ex) _gc_marker_ex(vm);
|
||||
}
|
||||
|
||||
void ManagedHeap::_delete(PyVar obj){
|
||||
PK_DEBUG_ASSERT(!obj.is_sso)
|
||||
const PyTypeInfo* ti = vm->_tp_info(obj);
|
||||
if(ti->vt._dtor) ti->vt._dtor(obj->_value_ptr());
|
||||
if(obj->_attr){
|
||||
obj->_attr->~NameDict();
|
||||
pool128_dealloc(obj->_attr);
|
||||
}
|
||||
pool128_dealloc(obj.get());
|
||||
}
|
||||
|
||||
void Dict::_gc_mark(VM* vm) const{
|
||||
apply([vm](PyVar k, PyVar v){
|
||||
PK_OBJ_MARK(k);
|
||||
PK_OBJ_MARK(v);
|
||||
});
|
||||
}
|
||||
|
||||
void CodeObject::_gc_mark(VM* vm) const {
|
||||
for(PyVar v : consts) PK_OBJ_MARK(v);
|
||||
for(auto& decl: func_decls) decl->_gc_mark(vm);
|
||||
}
|
||||
|
||||
} // namespace pkpy
|
Loading…
x
Reference in New Issue
Block a user