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