mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
init
This commit is contained in:
parent
4ab7c10ed1
commit
f5a4c37968
@ -88,7 +88,7 @@ struct Struct{
|
|||||||
};
|
};
|
||||||
|
|
||||||
static_assert(sizeof(Py_<Struct>) <= 64);
|
static_assert(sizeof(Py_<Struct>) <= 64);
|
||||||
static_assert(sizeof(Py_<Tuple>) <= 64);
|
static_assert(sizeof(Py_<Tuple>) <= 128);
|
||||||
|
|
||||||
/***********************************************/
|
/***********************************************/
|
||||||
template<typename Tp>
|
template<typename Tp>
|
||||||
|
@ -148,7 +148,7 @@ template<>
|
|||||||
struct Py_<Function> final: PyObject {
|
struct Py_<Function> final: PyObject {
|
||||||
Function _value;
|
Function _value;
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
Py_(Type type, Args&&... args): PyObject(type), _value(std::forward<Args>(args)...) {
|
Py_(Args&&... args): PyObject(), _value(std::forward<Args>(args)...) {
|
||||||
// _enable_instance_dict();
|
// _enable_instance_dict();
|
||||||
}
|
}
|
||||||
void _obj_gc_mark() override {
|
void _obj_gc_mark() override {
|
||||||
@ -161,7 +161,7 @@ template<>
|
|||||||
struct Py_<NativeFunc> final: PyObject {
|
struct Py_<NativeFunc> final: PyObject {
|
||||||
NativeFunc _value;
|
NativeFunc _value;
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
Py_(Type type, Args&&... args): PyObject(type), _value(std::forward<Args>(args)...) {
|
Py_(Args&&... args): PyObject(), _value(std::forward<Args>(args)...) {
|
||||||
// _enable_instance_dict();
|
// _enable_instance_dict();
|
||||||
}
|
}
|
||||||
void _obj_gc_mark() override {
|
void _obj_gc_mark() override {
|
||||||
|
@ -125,10 +125,6 @@ struct Type {
|
|||||||
#define PK_DEBUG_ASSERT(x)
|
#define PK_DEBUG_ASSERT(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct PyObject;
|
|
||||||
using PyVar = PyObject *;
|
|
||||||
#define PK_BITS(p) (reinterpret_cast<i64>(p))
|
|
||||||
|
|
||||||
// is_pod_v<> for c++17 and c++20
|
// is_pod_v<> for c++17 and c++20
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline constexpr bool is_pod_v = std::is_trivially_copyable_v<T> && std::is_standard_layout_v<T>;
|
inline constexpr bool is_pod_v = std::is_trivially_copyable_v<T> && std::is_standard_layout_v<T>;
|
||||||
@ -172,4 +168,45 @@ 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;
|
||||||
|
// using PyVar = PyObject *;
|
||||||
|
|
||||||
|
struct PyVar final{
|
||||||
|
Type type;
|
||||||
|
bool is_sso;
|
||||||
|
uint8_t flags;
|
||||||
|
char _bytes[12];
|
||||||
|
|
||||||
|
PyVar(): type(), is_sso(false), flags(0) { }
|
||||||
|
PyVar(std::nullptr_t): type(), is_sso(false), flags(0) { }
|
||||||
|
PyVar(Type type, bool is_sso): type(type), is_sso(is_sso), flags(0) { }
|
||||||
|
PyVar(Type type, PyObject* p): type(type), is_sso(false), flags(0) { as<PyObject*>() = p; }
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T& as() const {
|
||||||
|
static_assert(!std::is_reference_v<T>);
|
||||||
|
PK_DEBUG_ASSERT(is_sso)
|
||||||
|
return *(T*)_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
operator bool() const { return type; }
|
||||||
|
|
||||||
|
bool operator==(const PyVar& other) const {
|
||||||
|
return memcmp(this, &other, sizeof(PyVar)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const PyVar& other) const {
|
||||||
|
return memcmp(this, &other, sizeof(PyVar)) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(std::nullptr_t) const { return !type; }
|
||||||
|
bool operator!=(std::nullptr_t) const { return type; }
|
||||||
|
|
||||||
|
PyObject* get() const { return as<PyObject*>(); }
|
||||||
|
i64 hash() const { return as<i64>(); }
|
||||||
|
PyObject* operator->() const { return as<PyObject*>(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(PyVar) == 16 && is_pod_v<PyVar>);
|
||||||
|
|
||||||
} // namespace pkpy
|
} // namespace pkpy
|
||||||
|
@ -18,7 +18,7 @@ struct Dict{
|
|||||||
int next;
|
int next;
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr int __Capacity = 8;
|
static constexpr int __Capacity = 4;
|
||||||
static constexpr float __LoadFactor = 0.67f;
|
static constexpr float __LoadFactor = 0.67f;
|
||||||
static_assert(sizeof(Item) * __Capacity <= 128);
|
static_assert(sizeof(Item) * __Capacity <= 128);
|
||||||
static_assert(sizeof(ItemNode) * __Capacity <= 64);
|
static_assert(sizeof(ItemNode) * __Capacity <= 64);
|
||||||
|
@ -97,7 +97,7 @@ struct CodeEmitContext{
|
|||||||
bool is_compiling_class = false;
|
bool is_compiling_class = false;
|
||||||
int base_stack_size = 0;
|
int base_stack_size = 0;
|
||||||
|
|
||||||
std::map<void*, int> _co_consts_nonstring_dedup_map;
|
std::map<PyVar, int> _co_consts_nonstring_dedup_map;
|
||||||
std::map<std::string, int, std::less<>> _co_consts_string_dedup_map;
|
std::map<std::string, int, std::less<>> _co_consts_string_dedup_map;
|
||||||
|
|
||||||
int get_loop() const;
|
int get_loop() const;
|
||||||
|
@ -132,7 +132,7 @@ struct LinkedFrame{
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct CallStack{
|
struct CallStack{
|
||||||
static_assert(sizeof(LinkedFrame) <= 64 && std::is_trivially_destructible_v<LinkedFrame>);
|
static_assert(sizeof(LinkedFrame) <= 128 && std::is_trivially_destructible_v<LinkedFrame>);
|
||||||
|
|
||||||
LinkedFrame* _tail;
|
LinkedFrame* _tail;
|
||||||
int _size;
|
int _size;
|
||||||
@ -144,7 +144,7 @@ struct CallStack{
|
|||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
void emplace(Args&&... args){
|
void emplace(Args&&... args){
|
||||||
_tail = new(pool64_alloc<LinkedFrame>()) LinkedFrame(_tail, std::forward<Args>(args)...);
|
_tail = new(pool128_alloc<LinkedFrame>()) LinkedFrame(_tail, std::forward<Args>(args)...);
|
||||||
++_size;
|
++_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,7 +152,7 @@ struct CallStack{
|
|||||||
PK_DEBUG_ASSERT(!empty())
|
PK_DEBUG_ASSERT(!empty())
|
||||||
LinkedFrame* p = _tail;
|
LinkedFrame* p = _tail;
|
||||||
_tail = p->f_back;
|
_tail = p->f_back;
|
||||||
pool64_dealloc(p);
|
pool128_dealloc(p);
|
||||||
--_size;
|
--_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,8 @@ struct ManagedHeap{
|
|||||||
PyVar gcnew(Type type, Args&&... args){
|
PyVar gcnew(Type type, Args&&... args){
|
||||||
using __T = Py_<std::decay_t<T>>;
|
using __T = Py_<std::decay_t<T>>;
|
||||||
// https://github.com/pocketpy/pocketpy/issues/94#issuecomment-1594784476
|
// https://github.com/pocketpy/pocketpy/issues/94#issuecomment-1594784476
|
||||||
PyVar obj = new(pool64_alloc<__T>()) Py_<std::decay_t<T>>(type, std::forward<Args>(args)...);
|
PyObject* p = new(pool64_alloc<__T>()) Py_<std::decay_t<T>>(std::forward<Args>(args)...);
|
||||||
|
PyVar obj(type, p);
|
||||||
gen.push_back(obj);
|
gen.push_back(obj);
|
||||||
gc_counter++;
|
gc_counter++;
|
||||||
return obj;
|
return obj;
|
||||||
@ -52,7 +53,8 @@ struct ManagedHeap{
|
|||||||
PyVar _new(Type type, Args&&... args){
|
PyVar _new(Type type, Args&&... args){
|
||||||
using __T = Py_<std::decay_t<T>>;
|
using __T = Py_<std::decay_t<T>>;
|
||||||
// https://github.com/pocketpy/pocketpy/issues/94#issuecomment-1594784476
|
// https://github.com/pocketpy/pocketpy/issues/94#issuecomment-1594784476
|
||||||
PyVar obj = new(pool64_alloc<__T>()) Py_<std::decay_t<T>>(type, std::forward<Args>(args)...);
|
PyObject* p = new(pool64_alloc<__T>()) Py_<std::decay_t<T>>(std::forward<Args>(args)...);
|
||||||
|
PyVar obj(type, p);
|
||||||
obj->gc_enabled = false;
|
obj->gc_enabled = false;
|
||||||
_no_gc.push_back(obj);
|
_no_gc.push_back(obj);
|
||||||
return obj;
|
return obj;
|
||||||
|
@ -10,6 +10,9 @@ void pool64_dealloc(void*) noexcept;
|
|||||||
void* pool128_alloc(size_t) noexcept;
|
void* pool128_alloc(size_t) noexcept;
|
||||||
void pool128_dealloc(void*) noexcept;
|
void pool128_dealloc(void*) noexcept;
|
||||||
|
|
||||||
|
void* pool256_alloc(size_t) noexcept;
|
||||||
|
void pool256_dealloc(void*) noexcept;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void* pool64_alloc() noexcept{
|
void* pool64_alloc() noexcept{
|
||||||
return pool64_alloc(sizeof(T));
|
return pool64_alloc(sizeof(T));
|
||||||
@ -20,9 +23,15 @@ void* pool128_alloc() noexcept{
|
|||||||
return pool128_alloc(sizeof(T));
|
return pool128_alloc(sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void* pool256_alloc() noexcept{
|
||||||
|
return pool256_alloc(sizeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
void pools_shrink_to_fit() noexcept;
|
void pools_shrink_to_fit() noexcept;
|
||||||
|
|
||||||
std::string pool64_info() noexcept;
|
std::string pool64_info() noexcept;
|
||||||
std::string pool128_info() noexcept;
|
std::string pool128_info() noexcept;
|
||||||
|
std::string pool256_info() noexcept;
|
||||||
|
|
||||||
}; // namespace pkpy
|
}; // namespace pkpy
|
||||||
|
@ -8,12 +8,12 @@ namespace pkpy{
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr T default_invalid_value(){
|
constexpr T default_invalid_value(){
|
||||||
if constexpr(std::is_pointer_v<T>) return nullptr;
|
if constexpr(std::is_same_v<PyVar, T>) return nullptr;
|
||||||
else if constexpr(std::is_same_v<int, T>) return -1;
|
else if constexpr(std::is_same_v<int, T>) return -1;
|
||||||
else return Discarded();
|
else return Discarded();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PK_SMALL_NAME_DICT_CAPACITY 8
|
#define PK_SMALL_NAME_DICT_CAPACITY 6
|
||||||
#define PK_SMALL_NAME_DICT_LOOP(B) for(int i=0; i<PK_SMALL_NAME_DICT_CAPACITY; i++) { B }
|
#define PK_SMALL_NAME_DICT_LOOP(B) for(int i=0; i<PK_SMALL_NAME_DICT_CAPACITY; i++) { B }
|
||||||
|
|
||||||
template<typename V>
|
template<typename V>
|
||||||
|
@ -96,7 +96,6 @@ struct Slice {
|
|||||||
struct PyObject{
|
struct PyObject{
|
||||||
bool gc_enabled; // whether this object is managed by GC
|
bool gc_enabled; // whether this object is managed by GC
|
||||||
bool gc_marked; // whether this object is marked
|
bool gc_marked; // whether this object is marked
|
||||||
Type type;
|
|
||||||
NameDict* _attr;
|
NameDict* _attr;
|
||||||
|
|
||||||
bool is_attr_valid() const noexcept { return _attr != nullptr; }
|
bool is_attr_valid() const noexcept { return _attr != nullptr; }
|
||||||
@ -114,7 +113,7 @@ struct PyObject{
|
|||||||
virtual void _obj_gc_mark() = 0;
|
virtual void _obj_gc_mark() = 0;
|
||||||
virtual ~PyObject();
|
virtual ~PyObject();
|
||||||
|
|
||||||
PyObject(Type type) : gc_enabled(true), gc_marked(false), type(type), _attr(nullptr) {}
|
PyObject() : gc_enabled(true), gc_marked(false), _attr(nullptr) {}
|
||||||
|
|
||||||
void _enable_instance_dict() {
|
void _enable_instance_dict() {
|
||||||
_attr = new(pool128_alloc<NameDict>()) NameDict();
|
_attr = new(pool128_alloc<NameDict>()) NameDict();
|
||||||
@ -128,15 +127,13 @@ struct PyObject{
|
|||||||
const int kTpIntIndex = 2;
|
const int kTpIntIndex = 2;
|
||||||
const int kTpFloatIndex = 3;
|
const int kTpFloatIndex = 3;
|
||||||
|
|
||||||
inline bool is_tagged(PyVar p) noexcept { return (PK_BITS(p) & 0b11) != 0b00; }
|
inline bool is_tagged(PyVar p) noexcept { return p.is_sso; }
|
||||||
inline bool is_small_int(PyVar p) noexcept { return (PK_BITS(p) & 0b11) == 0b10; }
|
inline bool is_float(PyVar p) noexcept { return p.type.index == kTpFloatIndex; }
|
||||||
inline bool is_heap_int(PyVar p) noexcept { return !is_tagged(p) && p->type.index == kTpIntIndex; }
|
inline bool is_int(PyVar p) noexcept { return p.type.index == kTpIntIndex; }
|
||||||
inline bool is_float(PyVar p) noexcept { return !is_tagged(p) && p->type.index == kTpFloatIndex; }
|
|
||||||
inline bool is_int(PyVar p) noexcept { return is_small_int(p) || is_heap_int(p); }
|
|
||||||
|
|
||||||
inline bool is_type(PyVar obj, Type type) {
|
inline bool is_type(PyVar obj, Type type) {
|
||||||
PK_DEBUG_ASSERT(obj != nullptr)
|
PK_DEBUG_ASSERT(obj != nullptr)
|
||||||
return is_small_int(obj) ? type.index == kTpIntIndex : obj->type == type;
|
return obj.type == type;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename, typename=void> struct has_gc_marker : std::false_type {};
|
template <typename, typename=void> struct has_gc_marker : std::false_type {};
|
||||||
@ -154,7 +151,7 @@ struct Py_ final: PyObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
Py_(Type type, Args&&... args) : PyObject(type), _value(std::forward<Args>(args)...) { }
|
Py_(Args&&... args) : PyObject(), _value(std::forward<Args>(args)...) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MappingProxy{
|
struct MappingProxy{
|
||||||
@ -169,7 +166,7 @@ template<typename T> T to_void_p(VM*, PyVar);
|
|||||||
PyVar from_void_p(VM*, void*);
|
PyVar from_void_p(VM*, void*);
|
||||||
|
|
||||||
|
|
||||||
#define PK_OBJ_GET(T, obj) (((Py_<T>*)(obj))->_value)
|
#define PK_OBJ_GET(T, obj) (obj.is_sso ? obj.as<T>() : (((Py_<T>*)(obj.get()))->_value))
|
||||||
|
|
||||||
#define PK_OBJ_MARK(obj) \
|
#define PK_OBJ_MARK(obj) \
|
||||||
if(!is_tagged(obj) && !(obj)->gc_marked) { \
|
if(!is_tagged(obj) && !(obj)->gc_marked) { \
|
||||||
@ -186,30 +183,19 @@ PyVar from_void_p(VM*, void*);
|
|||||||
#define CAST_DEFAULT(T, x, default_value) (x != vm->None) ? py_cast<T>(vm, x) : (default_value)
|
#define CAST_DEFAULT(T, x, default_value) (x != vm->None) ? py_cast<T>(vm, x) : (default_value)
|
||||||
|
|
||||||
/*****************************************************************/
|
/*****************************************************************/
|
||||||
template<>
|
|
||||||
struct Py_<i64> final: PyObject {
|
|
||||||
i64 _value;
|
|
||||||
Py_(Type type, i64 val): PyObject(type), _value(val) {}
|
|
||||||
void _obj_gc_mark() override {}
|
|
||||||
};
|
|
||||||
|
|
||||||
inline bool try_cast_int(PyVar obj, i64* val) noexcept {
|
inline bool try_cast_int(PyVar obj, i64* val) noexcept {
|
||||||
if(is_small_int(obj)){
|
if(is_int(obj)){
|
||||||
*val = PK_BITS(obj) >> 2;
|
*val = obj.as<i64>();
|
||||||
return true;
|
return true;
|
||||||
}else if(is_heap_int(obj)){
|
|
||||||
*val = PK_OBJ_GET(i64, obj);
|
|
||||||
return true;
|
|
||||||
}else{
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct Py_<List> final: PyObject {
|
struct Py_<List> final: PyObject {
|
||||||
List _value;
|
List _value;
|
||||||
Py_(Type type, List&& val): PyObject(type), _value(std::move(val)) {}
|
Py_(List&& val): PyObject(), _value(std::move(val)) {}
|
||||||
Py_(Type type, const List& val): PyObject(type), _value(val) {}
|
Py_(const List& val): PyObject(), _value(val) {}
|
||||||
|
|
||||||
void _obj_gc_mark() override {
|
void _obj_gc_mark() override {
|
||||||
for(PyVar obj: _value) PK_OBJ_MARK(obj);
|
for(PyVar obj: _value) PK_OBJ_MARK(obj);
|
||||||
@ -219,8 +205,8 @@ struct Py_<List> final: PyObject {
|
|||||||
template<>
|
template<>
|
||||||
struct Py_<Tuple> final: PyObject {
|
struct Py_<Tuple> final: PyObject {
|
||||||
Tuple _value;
|
Tuple _value;
|
||||||
Py_(Type type, Tuple&& val): PyObject(type), _value(std::move(val)) {}
|
Py_(Tuple&& val): PyObject(), _value(std::move(val)) {}
|
||||||
Py_(Type type, const Tuple& val): PyObject(type), _value(val) {}
|
Py_(const Tuple& val): PyObject(), _value(val) {}
|
||||||
|
|
||||||
void _obj_gc_mark() override {
|
void _obj_gc_mark() override {
|
||||||
for(PyVar obj: _value) PK_OBJ_MARK(obj);
|
for(PyVar obj: _value) PK_OBJ_MARK(obj);
|
||||||
@ -230,7 +216,7 @@ struct Py_<Tuple> final: PyObject {
|
|||||||
template<>
|
template<>
|
||||||
struct Py_<MappingProxy> final: PyObject {
|
struct Py_<MappingProxy> final: PyObject {
|
||||||
MappingProxy _value;
|
MappingProxy _value;
|
||||||
Py_(Type type, MappingProxy val): PyObject(type), _value(val) {}
|
Py_(MappingProxy val): PyObject(), _value(val) {}
|
||||||
void _obj_gc_mark() override {
|
void _obj_gc_mark() override {
|
||||||
PK_OBJ_MARK(_value.obj);
|
PK_OBJ_MARK(_value.obj);
|
||||||
}
|
}
|
||||||
@ -239,7 +225,7 @@ struct Py_<MappingProxy> final: PyObject {
|
|||||||
template<>
|
template<>
|
||||||
struct Py_<BoundMethod> final: PyObject {
|
struct Py_<BoundMethod> final: PyObject {
|
||||||
BoundMethod _value;
|
BoundMethod _value;
|
||||||
Py_(Type type, BoundMethod val): PyObject(type), _value(val) {}
|
Py_(BoundMethod val): PyObject(), _value(val) {}
|
||||||
void _obj_gc_mark() override {
|
void _obj_gc_mark() override {
|
||||||
PK_OBJ_MARK(_value.self);
|
PK_OBJ_MARK(_value.self);
|
||||||
PK_OBJ_MARK(_value.func);
|
PK_OBJ_MARK(_value.func);
|
||||||
@ -249,7 +235,7 @@ struct Py_<BoundMethod> final: PyObject {
|
|||||||
template<>
|
template<>
|
||||||
struct Py_<StarWrapper> final: PyObject {
|
struct Py_<StarWrapper> final: PyObject {
|
||||||
StarWrapper _value;
|
StarWrapper _value;
|
||||||
Py_(Type type, StarWrapper val): PyObject(type), _value(val) {}
|
Py_(StarWrapper val): PyObject(), _value(val) {}
|
||||||
void _obj_gc_mark() override {
|
void _obj_gc_mark() override {
|
||||||
PK_OBJ_MARK(_value.obj);
|
PK_OBJ_MARK(_value.obj);
|
||||||
}
|
}
|
||||||
@ -258,7 +244,7 @@ struct Py_<StarWrapper> final: PyObject {
|
|||||||
template<>
|
template<>
|
||||||
struct Py_<StaticMethod> final: PyObject {
|
struct Py_<StaticMethod> final: PyObject {
|
||||||
StaticMethod _value;
|
StaticMethod _value;
|
||||||
Py_(Type type, StaticMethod val): PyObject(type), _value(val) {}
|
Py_(StaticMethod val): PyObject(), _value(val) {}
|
||||||
void _obj_gc_mark() override {
|
void _obj_gc_mark() override {
|
||||||
PK_OBJ_MARK(_value.func);
|
PK_OBJ_MARK(_value.func);
|
||||||
}
|
}
|
||||||
@ -267,7 +253,7 @@ struct Py_<StaticMethod> final: PyObject {
|
|||||||
template<>
|
template<>
|
||||||
struct Py_<ClassMethod> final: PyObject {
|
struct Py_<ClassMethod> final: PyObject {
|
||||||
ClassMethod _value;
|
ClassMethod _value;
|
||||||
Py_(Type type, ClassMethod val): PyObject(type), _value(val) {}
|
Py_(ClassMethod val): PyObject(), _value(val) {}
|
||||||
void _obj_gc_mark() override {
|
void _obj_gc_mark() override {
|
||||||
PK_OBJ_MARK(_value.func);
|
PK_OBJ_MARK(_value.func);
|
||||||
}
|
}
|
||||||
@ -276,7 +262,7 @@ struct Py_<ClassMethod> final: PyObject {
|
|||||||
template<>
|
template<>
|
||||||
struct Py_<Property> final: PyObject {
|
struct Py_<Property> final: PyObject {
|
||||||
Property _value;
|
Property _value;
|
||||||
Py_(Type type, Property val): PyObject(type), _value(val) {}
|
Py_(Property val): PyObject(), _value(val) {}
|
||||||
void _obj_gc_mark() override {
|
void _obj_gc_mark() override {
|
||||||
PK_OBJ_MARK(_value.getter);
|
PK_OBJ_MARK(_value.getter);
|
||||||
PK_OBJ_MARK(_value.setter);
|
PK_OBJ_MARK(_value.setter);
|
||||||
@ -286,7 +272,7 @@ struct Py_<Property> final: PyObject {
|
|||||||
template<>
|
template<>
|
||||||
struct Py_<Slice> final: PyObject {
|
struct Py_<Slice> final: PyObject {
|
||||||
Slice _value;
|
Slice _value;
|
||||||
Py_(Type type, Slice val): PyObject(type), _value(val) {}
|
Py_(Slice val): PyObject(), _value(val) {}
|
||||||
void _obj_gc_mark() override {
|
void _obj_gc_mark() override {
|
||||||
PK_OBJ_MARK(_value.start);
|
PK_OBJ_MARK(_value.start);
|
||||||
PK_OBJ_MARK(_value.stop);
|
PK_OBJ_MARK(_value.stop);
|
||||||
@ -298,7 +284,7 @@ template<>
|
|||||||
struct Py_<Super> final: PyObject {
|
struct Py_<Super> final: PyObject {
|
||||||
Super _value;
|
Super _value;
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
Py_(Type type, Args&&... args): PyObject(type), _value(std::forward<Args>(args)...) {}
|
Py_(Args&&... args): PyObject(), _value(std::forward<Args>(args)...) {}
|
||||||
void _obj_gc_mark() override {
|
void _obj_gc_mark() override {
|
||||||
PK_OBJ_MARK(_value.first);
|
PK_OBJ_MARK(_value.first);
|
||||||
}
|
}
|
||||||
@ -306,16 +292,14 @@ struct Py_<Super> final: PyObject {
|
|||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct Py_<DummyInstance> final: PyObject {
|
struct Py_<DummyInstance> final: PyObject {
|
||||||
Py_(Type type): PyObject(type) {
|
Py_(): PyObject() { _enable_instance_dict(); }
|
||||||
_enable_instance_dict();
|
|
||||||
}
|
|
||||||
void _obj_gc_mark() override {}
|
void _obj_gc_mark() override {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct Py_<Type> final: PyObject {
|
struct Py_<Type> final: PyObject {
|
||||||
Type _value;
|
Type _value;
|
||||||
Py_(Type type, Type val): PyObject(type), _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 {}
|
void _obj_gc_mark() override {}
|
||||||
@ -323,7 +307,7 @@ struct Py_<Type> final: PyObject {
|
|||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct Py_<DummyModule> final: PyObject {
|
struct Py_<DummyModule> final: PyObject {
|
||||||
Py_(Type type): PyObject(type) {
|
Py_(): PyObject() {
|
||||||
_enable_instance_dict(PK_TYPE_ATTR_LOAD_FACTOR);
|
_enable_instance_dict(PK_TYPE_ATTR_LOAD_FACTOR);
|
||||||
}
|
}
|
||||||
void _obj_gc_mark() override {}
|
void _obj_gc_mark() override {}
|
||||||
|
@ -11,7 +11,7 @@ using List = pod_vector<PyVar, 4>;
|
|||||||
|
|
||||||
struct Tuple {
|
struct Tuple {
|
||||||
PyVar* _args;
|
PyVar* _args;
|
||||||
PyVar _inlined[3];
|
PyVar _inlined[4];
|
||||||
int _size;
|
int _size;
|
||||||
|
|
||||||
Tuple(int n);
|
Tuple(int n);
|
||||||
|
@ -8,9 +8,9 @@ namespace pkpy{
|
|||||||
template<typename T, int Growth=2>
|
template<typename T, int Growth=2>
|
||||||
struct pod_vector{
|
struct pod_vector{
|
||||||
static constexpr int SizeT = sizeof(T);
|
static constexpr int SizeT = sizeof(T);
|
||||||
static constexpr int N = 64 / SizeT;
|
static constexpr int N = 128 / SizeT;
|
||||||
|
|
||||||
// static_assert(64 % SizeT == 0);
|
// static_assert(128 % SizeT == 0);
|
||||||
static_assert(is_pod_v<T>);
|
static_assert(is_pod_v<T>);
|
||||||
static_assert(N >= 4);
|
static_assert(N >= 4);
|
||||||
|
|
||||||
@ -21,21 +21,21 @@ struct pod_vector{
|
|||||||
using size_type = int;
|
using size_type = int;
|
||||||
|
|
||||||
pod_vector(): _size(0), _capacity(N) {
|
pod_vector(): _size(0), _capacity(N) {
|
||||||
_data = (T*)pool64_alloc(_capacity * SizeT);
|
_data = (T*)pool128_alloc(_capacity * SizeT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// support initializer list
|
// support initializer list
|
||||||
pod_vector(std::initializer_list<T> il): _size(il.size()), _capacity(std::max(N, _size)) {
|
pod_vector(std::initializer_list<T> il): _size(il.size()), _capacity(std::max(N, _size)) {
|
||||||
_data = (T*)pool64_alloc(_capacity * SizeT);
|
_data = (T*)pool128_alloc(_capacity * SizeT);
|
||||||
for(int i=0; i<_size; i++) _data[i] = *(il.begin() + i);
|
for(int i=0; i<_size; i++) _data[i] = *(il.begin() + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
pod_vector(int size): _size(size), _capacity(std::max(N, size)) {
|
pod_vector(int size): _size(size), _capacity(std::max(N, size)) {
|
||||||
_data = (T*)pool64_alloc(_capacity * SizeT);
|
_data = (T*)pool128_alloc(_capacity * SizeT);
|
||||||
}
|
}
|
||||||
|
|
||||||
pod_vector(const pod_vector& other): _size(other._size), _capacity(other._capacity) {
|
pod_vector(const pod_vector& other): _size(other._size), _capacity(other._capacity) {
|
||||||
_data = (T*)pool64_alloc(_capacity * SizeT);
|
_data = (T*)pool128_alloc(_capacity * SizeT);
|
||||||
memcpy(_data, other._data, SizeT * _size);
|
memcpy(_data, other._data, SizeT * _size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ struct pod_vector{
|
|||||||
}
|
}
|
||||||
|
|
||||||
pod_vector& operator=(pod_vector&& other) noexcept {
|
pod_vector& operator=(pod_vector&& other) noexcept {
|
||||||
if(_data!=nullptr) pool64_dealloc(_data);
|
if(_data!=nullptr) pool128_dealloc(_data);
|
||||||
_size = other._size;
|
_size = other._size;
|
||||||
_capacity = other._capacity;
|
_capacity = other._capacity;
|
||||||
_data = other._data;
|
_data = other._data;
|
||||||
@ -74,10 +74,10 @@ struct pod_vector{
|
|||||||
if(cap <= _capacity) return;
|
if(cap <= _capacity) return;
|
||||||
_capacity = cap;
|
_capacity = cap;
|
||||||
T* old_data = _data;
|
T* old_data = _data;
|
||||||
_data = (T*)pool64_alloc(_capacity * SizeT);
|
_data = (T*)pool128_alloc(_capacity * SizeT);
|
||||||
if(old_data != nullptr){
|
if(old_data != nullptr){
|
||||||
memcpy(_data, old_data, SizeT * _size);
|
memcpy(_data, old_data, SizeT * _size);
|
||||||
pool64_dealloc(old_data);
|
pool128_dealloc(old_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +139,7 @@ struct pod_vector{
|
|||||||
}
|
}
|
||||||
|
|
||||||
~pod_vector() {
|
~pod_vector() {
|
||||||
if(_data != nullptr) pool64_dealloc(_data);
|
if(_data != nullptr) pool128_dealloc(_data);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -365,7 +365,7 @@ public:
|
|||||||
void check_type(PyVar obj, Type type){ if(!is_type(obj, type)) TypeError(type, _tp(obj)); }
|
void check_type(PyVar obj, Type type){ if(!is_type(obj, type)) TypeError(type, _tp(obj)); }
|
||||||
void check_compatible_type(PyVar obj, Type type){ if(!isinstance(obj, type)) TypeError(type, _tp(obj)); }
|
void check_compatible_type(PyVar obj, Type type){ if(!isinstance(obj, type)) TypeError(type, _tp(obj)); }
|
||||||
|
|
||||||
Type _tp(PyVar obj){ return is_small_int(obj) ? tp_int : obj->type; }
|
Type _tp(PyVar obj){ return obj.type; }
|
||||||
const PyTypeInfo* _tp_info(PyVar obj) { return &_all_types[_tp(obj)]; }
|
const PyTypeInfo* _tp_info(PyVar obj) { return &_all_types[_tp(obj)]; }
|
||||||
const PyTypeInfo* _tp_info(Type type) { return &_all_types[type]; }
|
const PyTypeInfo* _tp_info(Type type) { return &_all_types[type]; }
|
||||||
PyVar _t(PyVar obj){ return _all_types[_tp(obj)].obj; }
|
PyVar _t(PyVar obj){ return _all_types[_tp(obj)].obj; }
|
||||||
@ -480,17 +480,14 @@ PyVar py_var(VM* vm, __T&& value){
|
|||||||
return value ? vm->True : vm->False;
|
return value ? vm->True : vm->False;
|
||||||
}else if constexpr(is_integral_v<T>){
|
}else if constexpr(is_integral_v<T>){
|
||||||
// int
|
// int
|
||||||
i64 val = static_cast<i64>(std::forward<__T>(value));
|
PyVar retval(VM::tp_int, true);
|
||||||
if(val >= Number::kMinSmallInt && val <= Number::kMaxSmallInt){
|
retval.as<i64>() = static_cast<i64>(value);
|
||||||
val = (val << 2) | 0b10;
|
return retval;
|
||||||
return reinterpret_cast<PyVar>(val);
|
|
||||||
}else{
|
|
||||||
return vm->heap.gcnew<i64>(vm->tp_int, val);
|
|
||||||
}
|
|
||||||
}else if constexpr(is_floating_point_v<T>){
|
}else if constexpr(is_floating_point_v<T>){
|
||||||
// float
|
// float
|
||||||
f64 val = static_cast<f64>(std::forward<__T>(value));
|
PyVar retval(VM::tp_float, true);
|
||||||
return vm->heap.gcnew<f64>(vm->tp_float, val);
|
retval.as<f64>() = static_cast<f64>(value);
|
||||||
|
return retval;
|
||||||
}else if constexpr(std::is_pointer_v<T>){
|
}else if constexpr(std::is_pointer_v<T>){
|
||||||
return from_void_p(vm, (void*)value);
|
return from_void_p(vm, (void*)value);
|
||||||
}else{
|
}else{
|
||||||
@ -529,19 +526,17 @@ __T _py_cast__internal(VM* vm, PyVar obj) {
|
|||||||
static_assert(!std::is_reference_v<__T>);
|
static_assert(!std::is_reference_v<__T>);
|
||||||
// int
|
// int
|
||||||
if constexpr(with_check){
|
if constexpr(with_check){
|
||||||
if(is_small_int(obj)) return (T)(PK_BITS(obj) >> 2);
|
if(is_int(obj)) return (T)obj.as<i64>();
|
||||||
if(is_heap_int(obj)) return (T)PK_OBJ_GET(i64, obj);
|
|
||||||
vm->TypeError("expected 'int', got " + _type_name(vm, vm->_tp(obj)).escape());
|
vm->TypeError("expected 'int', got " + _type_name(vm, vm->_tp(obj)).escape());
|
||||||
}else{
|
}else{
|
||||||
if(is_small_int(obj)) return (T)(PK_BITS(obj) >> 2);
|
return (T)obj.as<i64>();
|
||||||
return (T)PK_OBJ_GET(i64, obj);
|
|
||||||
}
|
}
|
||||||
}else if constexpr(is_floating_point_v<T>){
|
}else if constexpr(is_floating_point_v<T>){
|
||||||
static_assert(!std::is_reference_v<__T>);
|
static_assert(!std::is_reference_v<__T>);
|
||||||
// float
|
// float
|
||||||
if(is_float(obj)) return PK_OBJ_GET(f64, obj);
|
if(is_float(obj)) return (T)obj.as<f64>();
|
||||||
i64 bits;
|
i64 bits;
|
||||||
if(try_cast_int(obj, &bits)) return (float)bits;
|
if(try_cast_int(obj, &bits)) return (T)bits;
|
||||||
vm->TypeError("expected 'int' or 'float', got " + _type_name(vm, vm->_tp(obj)).escape());
|
vm->TypeError("expected 'int' or 'float', got " + _type_name(vm, vm->_tp(obj)).escape());
|
||||||
}else if constexpr(std::is_enum_v<T>){
|
}else if constexpr(std::is_enum_v<T>){
|
||||||
static_assert(!std::is_reference_v<__T>);
|
static_assert(!std::is_reference_v<__T>);
|
||||||
|
@ -2,33 +2,34 @@
|
|||||||
|
|
||||||
namespace pkpy{
|
namespace pkpy{
|
||||||
|
|
||||||
#define PREDICT_INT_OP(op) \
|
#define PREDICT_INT_OP(op) \
|
||||||
if(is_small_int(_0) && is_small_int(_1)){ \
|
if(is_int(_0) && is_int(_1)){ \
|
||||||
TOP() = VAR((PK_BITS(_0)>>2) op (PK_BITS(_1)>>2)); \
|
TOP() = VAR(_0.as<i64>() op _1.as<i64>()); \
|
||||||
DISPATCH() \
|
DISPATCH() \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PREDICT_INT_DIV_OP(op) \
|
#define PREDICT_INT_DIV_OP(op) \
|
||||||
if(is_small_int(_0) && is_small_int(_1)){ \
|
if(is_int(_0) && is_int(_1)){ \
|
||||||
if(_1 == (PyVar)0b10) ZeroDivisionError(); \
|
i64 divisor = _1.as<i64>(); \
|
||||||
TOP() = VAR((PK_BITS(_0)>>2) op (PK_BITS(_1)>>2)); \
|
if(_1.as<i64>() == 0) ZeroDivisionError(); \
|
||||||
DISPATCH() \
|
TOP() = VAR(_0.as<i64>() op divisor); \
|
||||||
|
DISPATCH() \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define BINARY_F_COMPARE(func, op, rfunc) \
|
#define BINARY_F_COMPARE(func, op, rfunc) \
|
||||||
PyVar ret; \
|
PyVar ret; \
|
||||||
const PyTypeInfo* _ti = _tp_info(_0); \
|
const PyTypeInfo* _ti = _tp_info(_0); \
|
||||||
if(_ti->m##func){ \
|
if(_ti->m##func){ \
|
||||||
ret = _ti->m##func(this, _0, _1); \
|
ret = _ti->m##func(this, _0, _1); \
|
||||||
}else{ \
|
}else{ \
|
||||||
PyVar self; \
|
PyVar self; \
|
||||||
PyVar _2 = get_unbound_method(_0, func, &self, false); \
|
PyVar _2 = get_unbound_method(_0, func, &self, false); \
|
||||||
if(_2 != nullptr) ret = call_method(self, _2, _1); \
|
if(_2 != nullptr) ret = call_method(self, _2, _1); \
|
||||||
else ret = NotImplemented; \
|
else ret = NotImplemented; \
|
||||||
} \
|
} \
|
||||||
if(ret == NotImplemented){ \
|
if(ret == NotImplemented){ \
|
||||||
PyVar self; \
|
PyVar self; \
|
||||||
PyVar _2 = get_unbound_method(_1, rfunc, &self, false); \
|
PyVar _2 = get_unbound_method(_1, rfunc, &self, false); \
|
||||||
if(_2 != nullptr) ret = call_method(self, _2, _0); \
|
if(_2 != nullptr) ret = call_method(self, _2, _0); \
|
||||||
else BinaryOptError(op, _0, _1); \
|
else BinaryOptError(op, _0, _1); \
|
||||||
if(ret == NotImplemented) BinaryOptError(op, _0, _1); \
|
if(ret == NotImplemented) BinaryOptError(op, _0, _1); \
|
||||||
@ -145,7 +146,7 @@ __NEXT_STEP:;
|
|||||||
case OP_LOAD_TRUE: PUSH(True); DISPATCH()
|
case OP_LOAD_TRUE: PUSH(True); DISPATCH()
|
||||||
case OP_LOAD_FALSE: PUSH(False); DISPATCH()
|
case OP_LOAD_FALSE: PUSH(False); DISPATCH()
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
case OP_LOAD_SMALL_INT: PUSH((PyVar)(uintptr_t)byte.arg); DISPATCH()
|
case OP_LOAD_SMALL_INT: PUSH(VAR((int16_t)byte.arg)); DISPATCH()
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
case OP_LOAD_ELLIPSIS: PUSH(Ellipsis); DISPATCH()
|
case OP_LOAD_ELLIPSIS: PUSH(Ellipsis); DISPATCH()
|
||||||
case OP_LOAD_FUNCTION: {
|
case OP_LOAD_FUNCTION: {
|
||||||
@ -243,7 +244,7 @@ __NEXT_STEP:;
|
|||||||
}
|
}
|
||||||
} DISPATCH()
|
} DISPATCH()
|
||||||
case OP_LOAD_SUBSCR_SMALL_INT:{
|
case OP_LOAD_SUBSCR_SMALL_INT:{
|
||||||
PyVar _1 = (PyVar)(uintptr_t)byte.arg;
|
PyVar _1 = VAR((int16_t)byte.arg);
|
||||||
PyVar _0 = TOP(); // a
|
PyVar _0 = TOP(); // a
|
||||||
auto _ti = _tp_info(_0);
|
auto _ti = _tp_info(_0);
|
||||||
if(_ti->m__getitem__){
|
if(_ti->m__getitem__){
|
||||||
@ -604,7 +605,7 @@ __NEXT_STEP:;
|
|||||||
case OP_IS_OP:{
|
case OP_IS_OP:{
|
||||||
PyVar _1 = POPX(); // rhs
|
PyVar _1 = POPX(); // rhs
|
||||||
PyVar _0 = TOP(); // lhs
|
PyVar _0 = TOP(); // lhs
|
||||||
TOP() = VAR(static_cast<bool>((_0==_1) ^ byte.arg));
|
TOP() = VAR(static_cast<bool>((uint16_t)(_0==_1) ^ byte.arg));
|
||||||
} DISPATCH()
|
} DISPATCH()
|
||||||
case OP_CONTAINS_OP:{
|
case OP_CONTAINS_OP:{
|
||||||
// a in b -> b __contains__ a
|
// a in b -> b __contains__ a
|
||||||
|
@ -184,7 +184,7 @@ void add_module_c(VM* vm){
|
|||||||
vm->bind(mod, "pp_deref(ptr: Tp) -> Tp", [](VM* vm, ArgsView args){
|
vm->bind(mod, "pp_deref(ptr: Tp) -> Tp", [](VM* vm, ArgsView args){
|
||||||
VoidP& ptr = CAST(VoidP&, args[0]);
|
VoidP& ptr = CAST(VoidP&, args[0]);
|
||||||
void* value = *reinterpret_cast<void**>(ptr.ptr);
|
void* value = *reinterpret_cast<void**>(ptr.ptr);
|
||||||
return vm->heap.gcnew<VoidP>(args[0]->type, value);
|
return vm->heap.gcnew<VoidP>(args[0].type, value);
|
||||||
});
|
});
|
||||||
|
|
||||||
PyVar type;
|
PyVar type;
|
||||||
@ -226,13 +226,13 @@ void add_module_c(VM* vm){
|
|||||||
VoidP& voidp = PK_OBJ_GET(VoidP, lhs); \
|
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->heap.gcnew<VoidP>(lhs->type, target + offset); \
|
return vm->heap.gcnew<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){ \
|
||||||
VoidP& voidp = PK_OBJ_GET(VoidP, lhs); \
|
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->heap.gcnew<VoidP>(lhs->type, target - offset); \
|
return vm->heap.gcnew<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); \
|
||||||
|
@ -13,11 +13,11 @@ namespace pkpy{
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct PySignalObject: PyObject {
|
struct PySignalObject: PyObject {
|
||||||
PySignalObject() : PyObject(Type(0)) { gc_enabled = false; }
|
PySignalObject() : PyObject() { gc_enabled = false; }
|
||||||
void _obj_gc_mark() override {}
|
void _obj_gc_mark() override {}
|
||||||
};
|
};
|
||||||
|
|
||||||
PyVar const PY_NULL = new PySignalObject();
|
PyVar const PY_NULL(Type(), new PySignalObject());
|
||||||
PyVar const PY_OP_CALL = new PySignalObject();
|
PyVar const PY_OP_CALL(Type(), new PySignalObject());
|
||||||
PyVar const PY_OP_YIELD = new PySignalObject();
|
PyVar const PY_OP_YIELD(Type(), new PySignalObject());
|
||||||
} // namespace pkpy
|
} // namespace pkpy
|
@ -10,7 +10,7 @@ namespace pkpy{
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool is_small_int(i64 value){
|
inline bool is_small_int(i64 value){
|
||||||
return value >= 0 && value < 1024;
|
return value >= INT16_MIN && value <= INT16_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CodeEmitContext::get_loop() const {
|
int CodeEmitContext::get_loop() const {
|
||||||
@ -91,7 +91,6 @@ namespace pkpy{
|
|||||||
|
|
||||||
int CodeEmitContext::emit_int(i64 value, int line){
|
int CodeEmitContext::emit_int(i64 value, int line){
|
||||||
if(is_small_int(value)){
|
if(is_small_int(value)){
|
||||||
value = (value << 2) | 0b10;
|
|
||||||
return emit_(OP_LOAD_SMALL_INT, (uint16_t)value, line);
|
return emit_(OP_LOAD_SMALL_INT, (uint16_t)value, line);
|
||||||
}else{
|
}else{
|
||||||
return emit_(OP_LOAD_CONST, add_const(VAR(value)), line);
|
return emit_(OP_LOAD_CONST, add_const(VAR(value)), line);
|
||||||
|
@ -10,11 +10,11 @@ namespace pkpy{
|
|||||||
alive.push_back(obj);
|
alive.push_back(obj);
|
||||||
}else{
|
}else{
|
||||||
#if PK_DEBUG_GC_STATS
|
#if PK_DEBUG_GC_STATS
|
||||||
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();
|
obj->~PyObject();
|
||||||
pool64_dealloc(obj);
|
pool64_dealloc(obj.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,8 +55,8 @@ namespace pkpy{
|
|||||||
}
|
}
|
||||||
|
|
||||||
ManagedHeap::~ManagedHeap(){
|
ManagedHeap::~ManagedHeap(){
|
||||||
for(PyVar obj: _no_gc) { obj->~PyObject(); pool64_dealloc(obj); }
|
for(PyVar obj: _no_gc) { obj->~PyObject(); pool64_dealloc(obj.get()); }
|
||||||
for(PyVar obj: gen) { obj->~PyObject(); pool64_dealloc(obj); }
|
for(PyVar obj: gen) { obj->~PyObject(); pool64_dealloc(obj.get()); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ struct DoubleLinkedList{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<int __BlockSize=128>
|
template<int __BlockSize>
|
||||||
struct MemoryPool{
|
struct MemoryPool{
|
||||||
static const int __MaxBlocks = 256*1024 / __BlockSize;
|
static const int __MaxBlocks = 256*1024 / __BlockSize;
|
||||||
static const int __MinArenaCount = PK_GC_MIN_THRESHOLD*100 / (256*1024);
|
static const int __MinArenaCount = PK_GC_MIN_THRESHOLD*100 / (256*1024);
|
||||||
@ -269,6 +269,7 @@ struct MemoryPool{
|
|||||||
|
|
||||||
static MemoryPool<64> pool64;
|
static MemoryPool<64> pool64;
|
||||||
static MemoryPool<128> pool128;
|
static MemoryPool<128> pool128;
|
||||||
|
static MemoryPool<256> pool256;
|
||||||
|
|
||||||
void* pool64_alloc(size_t size) noexcept { return pool64.alloc(size); }
|
void* pool64_alloc(size_t size) noexcept { return pool64.alloc(size); }
|
||||||
void pool64_dealloc(void* p) noexcept { pool64.dealloc(p); }
|
void pool64_dealloc(void* p) noexcept { pool64.dealloc(p); }
|
||||||
@ -276,12 +277,17 @@ void pool64_dealloc(void* p) noexcept { pool64.dealloc(p); }
|
|||||||
void* pool128_alloc(size_t size) noexcept { return pool128.alloc(size); }
|
void* pool128_alloc(size_t size) noexcept { return pool128.alloc(size); }
|
||||||
void pool128_dealloc(void* p) noexcept { pool128.dealloc(p); }
|
void pool128_dealloc(void* p) noexcept { pool128.dealloc(p); }
|
||||||
|
|
||||||
|
void* pool256_alloc(size_t size) noexcept { return pool256.alloc(size); }
|
||||||
|
void pool256_dealloc(void* p) noexcept { pool256.dealloc(p); }
|
||||||
|
|
||||||
void pools_shrink_to_fit() noexcept {
|
void pools_shrink_to_fit() noexcept {
|
||||||
pool64.shrink_to_fit();
|
pool64.shrink_to_fit();
|
||||||
pool128.shrink_to_fit();
|
pool128.shrink_to_fit();
|
||||||
|
pool256.shrink_to_fit();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string pool64_info() noexcept { return pool64.info(); }
|
std::string pool64_info() noexcept { return pool64.info(); }
|
||||||
std::string pool128_info() noexcept { return pool128.info(); }
|
std::string pool128_info() noexcept { return pool128.info(); }
|
||||||
|
std::string pool256_info() noexcept { return pool256.info(); }
|
||||||
|
|
||||||
}
|
}
|
@ -173,7 +173,7 @@ void __init_builtins(VM* _vm) {
|
|||||||
_vm->bind_func(_vm->builtins, "id", 1, [](VM* vm, ArgsView args) {
|
_vm->bind_func(_vm->builtins, "id", 1, [](VM* vm, ArgsView args) {
|
||||||
PyVar obj = args[0];
|
PyVar obj = args[0];
|
||||||
if(is_tagged(obj)) return vm->None;
|
if(is_tagged(obj)) return vm->None;
|
||||||
return VAR(PK_BITS(obj));
|
return VAR(reinterpret_cast<i64>(obj.get()));
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind_func(_vm->builtins, "callable", 1, [](VM* vm, ArgsView args) {
|
_vm->bind_func(_vm->builtins, "callable", 1, [](VM* vm, ArgsView args) {
|
||||||
@ -331,7 +331,7 @@ void __init_builtins(VM* _vm) {
|
|||||||
if(is_tagged(obj)) PK_FATAL_ERROR();
|
if(is_tagged(obj)) PK_FATAL_ERROR();
|
||||||
SStream ss;
|
SStream ss;
|
||||||
ss << "<" << _type_name(vm, vm->_tp(obj)) << " object at ";
|
ss << "<" << _type_name(vm, vm->_tp(obj)) << " object at ";
|
||||||
ss.write_hex(obj);
|
ss.write_hex(obj.get());
|
||||||
ss << ">";
|
ss << ">";
|
||||||
return ss.str();
|
return ss.str();
|
||||||
});
|
});
|
||||||
@ -1482,7 +1482,7 @@ void __init_builtins(VM* _vm) {
|
|||||||
|
|
||||||
_vm->bind__repr__(VM::tp_exception, [](VM* vm, PyVar _0) -> Str {
|
_vm->bind__repr__(VM::tp_exception, [](VM* vm, PyVar _0) -> Str {
|
||||||
Exception& self = _CAST(Exception&, _0);
|
Exception& self = _CAST(Exception&, _0);
|
||||||
return _S(_type_name(vm, _0->type), '(', self.msg.escape(), ')');
|
return _S(_type_name(vm, _0.type), '(', self.msg.escape(), ')');
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind__str__(VM::tp_exception, [](VM* vm, PyVar _0) -> Str{
|
_vm->bind__str__(VM::tp_exception, [](VM* vm, PyVar _0) -> Str{
|
||||||
|
@ -6,7 +6,7 @@ Tuple::Tuple(int n){
|
|||||||
if(n <= 3){
|
if(n <= 3){
|
||||||
this->_args = _inlined;
|
this->_args = _inlined;
|
||||||
}else{
|
}else{
|
||||||
this->_args = (PyVar*)pool64_alloc(n * sizeof(void*));
|
this->_args = (PyVar*)pool128_alloc(n * sizeof(void*));
|
||||||
}
|
}
|
||||||
this->_size = n;
|
this->_size = n;
|
||||||
}
|
}
|
||||||
@ -51,7 +51,7 @@ Tuple::Tuple(PyVar _0, PyVar _1, PyVar _2, PyVar _3): Tuple(4){
|
|||||||
_args[3] = _3;
|
_args[3] = _3;
|
||||||
}
|
}
|
||||||
|
|
||||||
Tuple::~Tuple(){ if(!is_inlined()) pool64_dealloc(_args); }
|
Tuple::~Tuple(){ if(!is_inlined()) pool128_dealloc(_args); }
|
||||||
|
|
||||||
List ArgsView::to_list() const{
|
List ArgsView::to_list() const{
|
||||||
List ret(size());
|
List ret(size());
|
||||||
|
22
src/vm.cpp
22
src/vm.cpp
@ -501,7 +501,7 @@ i64 VM::py_hash(PyVar obj){
|
|||||||
return CAST(i64, ret);
|
return CAST(i64, ret);
|
||||||
}
|
}
|
||||||
// if it is trivial `object`, return PK_BITS
|
// if it is trivial `object`, return PK_BITS
|
||||||
if(ti == &_all_types[tp_object]) return PK_BITS(obj);
|
if(ti == &_all_types[tp_object]) return obj.hash();
|
||||||
// otherwise, we check if it has a custom __eq__ other than object.__eq__
|
// otherwise, we check if it has a custom __eq__ other than object.__eq__
|
||||||
bool has_custom_eq = false;
|
bool has_custom_eq = false;
|
||||||
if(ti->m__eq__) has_custom_eq = true;
|
if(ti->m__eq__) has_custom_eq = true;
|
||||||
@ -513,7 +513,7 @@ i64 VM::py_hash(PyVar obj){
|
|||||||
TypeError(_S("unhashable type: ", ti->name.escape()));
|
TypeError(_S("unhashable type: ", ti->name.escape()));
|
||||||
PK_UNREACHABLE()
|
PK_UNREACHABLE()
|
||||||
}else{
|
}else{
|
||||||
return PK_BITS(obj);
|
return obj.hash();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -715,8 +715,6 @@ static std::string _opcode_argstr(VM* vm, Bytecode byte, const CodeObject* co){
|
|||||||
case OP_LOAD_FUNCTION:
|
case OP_LOAD_FUNCTION:
|
||||||
argStr += _S(" (", co->func_decls[byte.arg]->code->name, ")").sv();
|
argStr += _S(" (", co->func_decls[byte.arg]->code->name, ")").sv();
|
||||||
break;
|
break;
|
||||||
case OP_LOAD_SMALL_INT: case OP_LOAD_SUBSCR_SMALL_INT:
|
|
||||||
argStr += _S(" (", (int)(byte.arg >> 2), ")").sv();
|
|
||||||
}
|
}
|
||||||
return argStr;
|
return argStr;
|
||||||
}
|
}
|
||||||
@ -1168,12 +1166,12 @@ PyVar VM::getattr(PyVar obj, StrName name, bool throw_err){
|
|||||||
// handle instance __dict__
|
// handle instance __dict__
|
||||||
if(!is_tagged(obj) && obj->is_attr_valid()){
|
if(!is_tagged(obj) && obj->is_attr_valid()){
|
||||||
PyVar val;
|
PyVar val;
|
||||||
if(obj->type == tp_type){
|
if(obj.type == tp_type){
|
||||||
val = find_name_in_mro(PK_OBJ_GET(Type, obj), name);
|
val = find_name_in_mro(PK_OBJ_GET(Type, obj), name);
|
||||||
if(val != nullptr){
|
if(val != nullptr){
|
||||||
if(is_tagged(val)) return val;
|
if(is_tagged(val)) return val;
|
||||||
if(val->type == tp_staticmethod) return PK_OBJ_GET(StaticMethod, val).func;
|
if(val.type == tp_staticmethod) return PK_OBJ_GET(StaticMethod, val).func;
|
||||||
if(val->type == tp_classmethod) return VAR(BoundMethod(obj, PK_OBJ_GET(ClassMethod, val).func));
|
if(val.type == tp_classmethod) return VAR(BoundMethod(obj, PK_OBJ_GET(ClassMethod, val).func));
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
@ -1184,7 +1182,7 @@ PyVar VM::getattr(PyVar obj, StrName name, bool throw_err){
|
|||||||
if(cls_var != nullptr){
|
if(cls_var != nullptr){
|
||||||
// bound method is non-data descriptor
|
// bound method is non-data descriptor
|
||||||
if(!is_tagged(cls_var)){
|
if(!is_tagged(cls_var)){
|
||||||
switch(cls_var->type){
|
switch(cls_var.type){
|
||||||
case tp_function.index:
|
case tp_function.index:
|
||||||
return VAR(BoundMethod(obj, cls_var));
|
return VAR(BoundMethod(obj, cls_var));
|
||||||
case tp_native_func.index:
|
case tp_native_func.index:
|
||||||
@ -1234,12 +1232,12 @@ PyVar VM::get_unbound_method(PyVar obj, StrName name, PyVar* self, bool throw_er
|
|||||||
// handle instance __dict__
|
// handle instance __dict__
|
||||||
if(!is_tagged(obj) && obj->is_attr_valid()){
|
if(!is_tagged(obj) && obj->is_attr_valid()){
|
||||||
PyVar val;
|
PyVar val;
|
||||||
if(obj->type == tp_type){
|
if(obj.type == tp_type){
|
||||||
val = find_name_in_mro(PK_OBJ_GET(Type, obj), name);
|
val = find_name_in_mro(PK_OBJ_GET(Type, obj), name);
|
||||||
if(val != nullptr){
|
if(val != nullptr){
|
||||||
if(is_tagged(val)) return val;
|
if(is_tagged(val)) return val;
|
||||||
if(val->type == tp_staticmethod) return PK_OBJ_GET(StaticMethod, val).func;
|
if(val.type == tp_staticmethod) return PK_OBJ_GET(StaticMethod, val).func;
|
||||||
if(val->type == tp_classmethod) return VAR(BoundMethod(obj, PK_OBJ_GET(ClassMethod, val).func));
|
if(val.type == tp_classmethod) return VAR(BoundMethod(obj, PK_OBJ_GET(ClassMethod, val).func));
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
@ -1251,7 +1249,7 @@ PyVar VM::get_unbound_method(PyVar obj, StrName name, PyVar* self, bool throw_er
|
|||||||
|
|
||||||
if(cls_var != nullptr){
|
if(cls_var != nullptr){
|
||||||
if(!is_tagged(cls_var)){
|
if(!is_tagged(cls_var)){
|
||||||
switch(cls_var->type){
|
switch(cls_var.type){
|
||||||
case tp_function.index:
|
case tp_function.index:
|
||||||
*self = obj;
|
*self = obj;
|
||||||
break;
|
break;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user