This commit is contained in:
blueloveTH 2024-05-12 23:43:06 +08:00
parent 4ab7c10ed1
commit f5a4c37968
22 changed files with 167 additions and 136 deletions

View File

@ -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>

View File

@ -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 {

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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;
} }

View File

@ -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;

View File

@ -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

View File

@ -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>

View File

@ -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 {}

View File

@ -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);

View File

@ -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);
} }
}; };

View File

@ -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>);

View File

@ -3,15 +3,16 @@
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(); \
TOP() = VAR(_0.as<i64>() op divisor); \
DISPATCH() \ DISPATCH() \
} }
@ -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

View File

@ -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); \

View File

@ -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

View File

@ -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);

View File

@ -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()); }
} }

View File

@ -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(); }
} }

View File

@ -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{

View File

@ -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());

View File

@ -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;