From f5a4c379688e9450c143d6cd726c2042d9951dd6 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 12 May 2024 23:43:06 +0800 Subject: [PATCH] init --- include/pocketpy/cffi.h | 2 +- include/pocketpy/codeobject.h | 4 +-- include/pocketpy/common.h | 45 +++++++++++++++++++++--- include/pocketpy/dict.h | 2 +- include/pocketpy/expr.h | 2 +- include/pocketpy/frame.h | 6 ++-- include/pocketpy/gc.h | 6 ++-- include/pocketpy/memory.h | 9 +++++ include/pocketpy/namedict.h | 4 +-- include/pocketpy/obj.h | 66 +++++++++++++---------------------- include/pocketpy/tuplelist.h | 2 +- include/pocketpy/vector.h | 20 +++++------ include/pocketpy/vm.h | 27 ++++++-------- src/ceval.cpp | 43 ++++++++++++----------- src/cffi.cpp | 6 ++-- src/codeobject.cpp | 8 ++--- src/expr.cpp | 3 +- src/gc.cpp | 8 ++--- src/memory.cpp | 8 ++++- src/pocketpy.cpp | 6 ++-- src/tuplelist.cpp | 4 +-- src/vm.cpp | 22 ++++++------ 22 files changed, 167 insertions(+), 136 deletions(-) diff --git a/include/pocketpy/cffi.h b/include/pocketpy/cffi.h index 8f08eb0a..a0da20be 100644 --- a/include/pocketpy/cffi.h +++ b/include/pocketpy/cffi.h @@ -88,7 +88,7 @@ struct Struct{ }; static_assert(sizeof(Py_) <= 64); -static_assert(sizeof(Py_) <= 64); +static_assert(sizeof(Py_) <= 128); /***********************************************/ template diff --git a/include/pocketpy/codeobject.h b/include/pocketpy/codeobject.h index a0a686b0..07c22c98 100644 --- a/include/pocketpy/codeobject.h +++ b/include/pocketpy/codeobject.h @@ -148,7 +148,7 @@ template<> struct Py_ final: PyObject { Function _value; template - Py_(Type type, Args&&... args): PyObject(type), _value(std::forward(args)...) { + Py_(Args&&... args): PyObject(), _value(std::forward(args)...) { // _enable_instance_dict(); } void _obj_gc_mark() override { @@ -161,7 +161,7 @@ template<> struct Py_ final: PyObject { NativeFunc _value; template - Py_(Type type, Args&&... args): PyObject(type), _value(std::forward(args)...) { + Py_(Args&&... args): PyObject(), _value(std::forward(args)...) { // _enable_instance_dict(); } void _obj_gc_mark() override { diff --git a/include/pocketpy/common.h b/include/pocketpy/common.h index a1125c04..fc8798e8 100644 --- a/include/pocketpy/common.h +++ b/include/pocketpy/common.h @@ -125,10 +125,6 @@ struct Type { #define PK_DEBUG_ASSERT(x) #endif -struct PyObject; -using PyVar = PyObject *; -#define PK_BITS(p) (reinterpret_cast(p)) - // is_pod_v<> for c++17 and c++20 template inline constexpr bool is_pod_v = std::is_trivially_copyable_v && std::is_standard_layout_v; @@ -172,4 +168,45 @@ inline constexpr bool is_floating_point_v = std::is_same_v || std::is_ 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() = p; } + + template + T& as() const { + static_assert(!std::is_reference_v); + 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(); } + i64 hash() const { return as(); } + PyObject* operator->() const { return as(); } +}; + +static_assert(sizeof(PyVar) == 16 && is_pod_v); + } // namespace pkpy diff --git a/include/pocketpy/dict.h b/include/pocketpy/dict.h index db0f13d3..120e4cd3 100644 --- a/include/pocketpy/dict.h +++ b/include/pocketpy/dict.h @@ -18,7 +18,7 @@ struct Dict{ int next; }; - static constexpr int __Capacity = 8; + static constexpr int __Capacity = 4; static constexpr float __LoadFactor = 0.67f; static_assert(sizeof(Item) * __Capacity <= 128); static_assert(sizeof(ItemNode) * __Capacity <= 64); diff --git a/include/pocketpy/expr.h b/include/pocketpy/expr.h index 9980771c..082fec37 100644 --- a/include/pocketpy/expr.h +++ b/include/pocketpy/expr.h @@ -97,7 +97,7 @@ struct CodeEmitContext{ bool is_compiling_class = false; int base_stack_size = 0; - std::map _co_consts_nonstring_dedup_map; + std::map _co_consts_nonstring_dedup_map; std::map> _co_consts_string_dedup_map; int get_loop() const; diff --git a/include/pocketpy/frame.h b/include/pocketpy/frame.h index 8c73d3c0..77b01bb2 100644 --- a/include/pocketpy/frame.h +++ b/include/pocketpy/frame.h @@ -132,7 +132,7 @@ struct LinkedFrame{ }; struct CallStack{ - static_assert(sizeof(LinkedFrame) <= 64 && std::is_trivially_destructible_v); + static_assert(sizeof(LinkedFrame) <= 128 && std::is_trivially_destructible_v); LinkedFrame* _tail; int _size; @@ -144,7 +144,7 @@ struct CallStack{ template void emplace(Args&&... args){ - _tail = new(pool64_alloc()) LinkedFrame(_tail, std::forward(args)...); + _tail = new(pool128_alloc()) LinkedFrame(_tail, std::forward(args)...); ++_size; } @@ -152,7 +152,7 @@ struct CallStack{ PK_DEBUG_ASSERT(!empty()) LinkedFrame* p = _tail; _tail = p->f_back; - pool64_dealloc(p); + pool128_dealloc(p); --_size; } diff --git a/include/pocketpy/gc.h b/include/pocketpy/gc.h index 3e1a423d..503d1953 100644 --- a/include/pocketpy/gc.h +++ b/include/pocketpy/gc.h @@ -42,7 +42,8 @@ struct ManagedHeap{ PyVar gcnew(Type type, Args&&... args){ using __T = Py_>; // https://github.com/pocketpy/pocketpy/issues/94#issuecomment-1594784476 - PyVar obj = new(pool64_alloc<__T>()) Py_>(type, std::forward(args)...); + PyObject* p = new(pool64_alloc<__T>()) Py_>(std::forward(args)...); + PyVar obj(type, p); gen.push_back(obj); gc_counter++; return obj; @@ -52,7 +53,8 @@ struct ManagedHeap{ PyVar _new(Type type, Args&&... args){ using __T = Py_>; // https://github.com/pocketpy/pocketpy/issues/94#issuecomment-1594784476 - PyVar obj = new(pool64_alloc<__T>()) Py_>(type, std::forward(args)...); + PyObject* p = new(pool64_alloc<__T>()) Py_>(std::forward(args)...); + PyVar obj(type, p); obj->gc_enabled = false; _no_gc.push_back(obj); return obj; diff --git a/include/pocketpy/memory.h b/include/pocketpy/memory.h index 14327ae4..324da3b3 100644 --- a/include/pocketpy/memory.h +++ b/include/pocketpy/memory.h @@ -10,6 +10,9 @@ void pool64_dealloc(void*) noexcept; void* pool128_alloc(size_t) noexcept; void pool128_dealloc(void*) noexcept; +void* pool256_alloc(size_t) noexcept; +void pool256_dealloc(void*) noexcept; + template void* pool64_alloc() noexcept{ return pool64_alloc(sizeof(T)); @@ -20,9 +23,15 @@ void* pool128_alloc() noexcept{ return pool128_alloc(sizeof(T)); } +template +void* pool256_alloc() noexcept{ + return pool256_alloc(sizeof(T)); +} + void pools_shrink_to_fit() noexcept; std::string pool64_info() noexcept; std::string pool128_info() noexcept; +std::string pool256_info() noexcept; }; // namespace pkpy diff --git a/include/pocketpy/namedict.h b/include/pocketpy/namedict.h index 08286b58..8515ec8a 100644 --- a/include/pocketpy/namedict.h +++ b/include/pocketpy/namedict.h @@ -8,12 +8,12 @@ namespace pkpy{ template constexpr T default_invalid_value(){ - if constexpr(std::is_pointer_v) return nullptr; + if constexpr(std::is_same_v) return nullptr; else if constexpr(std::is_same_v) return -1; 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 diff --git a/include/pocketpy/obj.h b/include/pocketpy/obj.h index 48bc7be5..7bc897fc 100644 --- a/include/pocketpy/obj.h +++ b/include/pocketpy/obj.h @@ -96,7 +96,6 @@ struct Slice { struct PyObject{ bool gc_enabled; // whether this object is managed by GC bool gc_marked; // whether this object is marked - Type type; NameDict* _attr; bool is_attr_valid() const noexcept { return _attr != nullptr; } @@ -114,7 +113,7 @@ struct PyObject{ virtual void _obj_gc_mark() = 0; 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() { _attr = new(pool128_alloc()) NameDict(); @@ -128,15 +127,13 @@ struct PyObject{ const int kTpIntIndex = 2; const int kTpFloatIndex = 3; -inline bool is_tagged(PyVar p) noexcept { return (PK_BITS(p) & 0b11) != 0b00; } -inline bool is_small_int(PyVar p) noexcept { return (PK_BITS(p) & 0b11) == 0b10; } -inline bool is_heap_int(PyVar p) noexcept { return !is_tagged(p) && 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_tagged(PyVar p) noexcept { return p.is_sso; } +inline bool is_float(PyVar p) noexcept { return p.type.index == kTpFloatIndex; } +inline bool is_int(PyVar p) noexcept { return p.type.index == kTpIntIndex; } inline bool is_type(PyVar obj, Type type) { PK_DEBUG_ASSERT(obj != nullptr) - return is_small_int(obj) ? type.index == kTpIntIndex : obj->type == type; + return obj.type == type; } template struct has_gc_marker : std::false_type {}; @@ -154,7 +151,7 @@ struct Py_ final: PyObject { } template - Py_(Type type, Args&&... args) : PyObject(type), _value(std::forward(args)...) { } + Py_(Args&&... args) : PyObject(), _value(std::forward(args)...) { } }; struct MappingProxy{ @@ -169,7 +166,7 @@ template T to_void_p(VM*, PyVar); PyVar from_void_p(VM*, void*); -#define PK_OBJ_GET(T, obj) (((Py_*)(obj))->_value) +#define PK_OBJ_GET(T, obj) (obj.is_sso ? obj.as() : (((Py_*)(obj.get()))->_value)) #define PK_OBJ_MARK(obj) \ 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(vm, x) : (default_value) /*****************************************************************/ -template<> -struct Py_ 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 { - if(is_small_int(obj)){ - *val = PK_BITS(obj) >> 2; + if(is_int(obj)){ + *val = obj.as(); return true; - }else if(is_heap_int(obj)){ - *val = PK_OBJ_GET(i64, obj); - return true; - }else{ - return false; } + return false; } template<> struct Py_ final: PyObject { List _value; - Py_(Type type, List&& val): PyObject(type), _value(std::move(val)) {} - Py_(Type type, const List& val): PyObject(type), _value(val) {} + 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); @@ -219,8 +205,8 @@ struct Py_ final: PyObject { template<> struct Py_ final: PyObject { Tuple _value; - Py_(Type type, Tuple&& val): PyObject(type), _value(std::move(val)) {} - Py_(Type type, const Tuple& val): PyObject(type), _value(val) {} + 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); @@ -230,7 +216,7 @@ struct Py_ final: PyObject { template<> struct Py_ final: PyObject { MappingProxy _value; - Py_(Type type, MappingProxy val): PyObject(type), _value(val) {} + Py_(MappingProxy val): PyObject(), _value(val) {} void _obj_gc_mark() override { PK_OBJ_MARK(_value.obj); } @@ -239,7 +225,7 @@ struct Py_ final: PyObject { template<> struct Py_ final: PyObject { BoundMethod _value; - Py_(Type type, BoundMethod val): PyObject(type), _value(val) {} + Py_(BoundMethod val): PyObject(), _value(val) {} void _obj_gc_mark() override { PK_OBJ_MARK(_value.self); PK_OBJ_MARK(_value.func); @@ -249,7 +235,7 @@ struct Py_ final: PyObject { template<> struct Py_ final: PyObject { StarWrapper _value; - Py_(Type type, StarWrapper val): PyObject(type), _value(val) {} + Py_(StarWrapper val): PyObject(), _value(val) {} void _obj_gc_mark() override { PK_OBJ_MARK(_value.obj); } @@ -258,7 +244,7 @@ struct Py_ final: PyObject { template<> struct Py_ final: PyObject { StaticMethod _value; - Py_(Type type, StaticMethod val): PyObject(type), _value(val) {} + Py_(StaticMethod val): PyObject(), _value(val) {} void _obj_gc_mark() override { PK_OBJ_MARK(_value.func); } @@ -267,7 +253,7 @@ struct Py_ final: PyObject { template<> struct Py_ final: PyObject { ClassMethod _value; - Py_(Type type, ClassMethod val): PyObject(type), _value(val) {} + Py_(ClassMethod val): PyObject(), _value(val) {} void _obj_gc_mark() override { PK_OBJ_MARK(_value.func); } @@ -276,7 +262,7 @@ struct Py_ final: PyObject { template<> struct Py_ final: PyObject { Property _value; - Py_(Type type, Property val): PyObject(type), _value(val) {} + Py_(Property val): PyObject(), _value(val) {} void _obj_gc_mark() override { PK_OBJ_MARK(_value.getter); PK_OBJ_MARK(_value.setter); @@ -286,7 +272,7 @@ struct Py_ final: PyObject { template<> struct Py_ final: PyObject { Slice _value; - Py_(Type type, Slice val): PyObject(type), _value(val) {} + Py_(Slice val): PyObject(), _value(val) {} void _obj_gc_mark() override { PK_OBJ_MARK(_value.start); PK_OBJ_MARK(_value.stop); @@ -298,7 +284,7 @@ template<> struct Py_ final: PyObject { Super _value; template - Py_(Type type, Args&&... args): PyObject(type), _value(std::forward(args)...) {} + Py_(Args&&... args): PyObject(), _value(std::forward(args)...) {} void _obj_gc_mark() override { PK_OBJ_MARK(_value.first); } @@ -306,16 +292,14 @@ struct Py_ final: PyObject { template<> struct Py_ final: PyObject { - Py_(Type type): PyObject(type) { - _enable_instance_dict(); - } + Py_(): PyObject() { _enable_instance_dict(); } void _obj_gc_mark() override {} }; template<> struct Py_ final: PyObject { 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); } void _obj_gc_mark() override {} @@ -323,7 +307,7 @@ struct Py_ final: PyObject { template<> struct Py_ final: PyObject { - Py_(Type type): PyObject(type) { + Py_(): PyObject() { _enable_instance_dict(PK_TYPE_ATTR_LOAD_FACTOR); } void _obj_gc_mark() override {} diff --git a/include/pocketpy/tuplelist.h b/include/pocketpy/tuplelist.h index 0fb6f4c8..d4e3c974 100644 --- a/include/pocketpy/tuplelist.h +++ b/include/pocketpy/tuplelist.h @@ -11,7 +11,7 @@ using List = pod_vector; struct Tuple { PyVar* _args; - PyVar _inlined[3]; + PyVar _inlined[4]; int _size; Tuple(int n); diff --git a/include/pocketpy/vector.h b/include/pocketpy/vector.h index 25b507fd..9e972f97 100644 --- a/include/pocketpy/vector.h +++ b/include/pocketpy/vector.h @@ -8,9 +8,9 @@ namespace pkpy{ template struct pod_vector{ 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); static_assert(N >= 4); @@ -21,21 +21,21 @@ struct pod_vector{ using size_type = int; pod_vector(): _size(0), _capacity(N) { - _data = (T*)pool64_alloc(_capacity * SizeT); + _data = (T*)pool128_alloc(_capacity * SizeT); } // support initializer list pod_vector(std::initializer_list 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); } 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) { - _data = (T*)pool64_alloc(_capacity * SizeT); + _data = (T*)pool128_alloc(_capacity * SizeT); memcpy(_data, other._data, SizeT * _size); } @@ -47,7 +47,7 @@ struct pod_vector{ } pod_vector& operator=(pod_vector&& other) noexcept { - if(_data!=nullptr) pool64_dealloc(_data); + if(_data!=nullptr) pool128_dealloc(_data); _size = other._size; _capacity = other._capacity; _data = other._data; @@ -74,10 +74,10 @@ struct pod_vector{ if(cap <= _capacity) return; _capacity = cap; T* old_data = _data; - _data = (T*)pool64_alloc(_capacity * SizeT); + _data = (T*)pool128_alloc(_capacity * SizeT); if(old_data != nullptr){ memcpy(_data, old_data, SizeT * _size); - pool64_dealloc(old_data); + pool128_dealloc(old_data); } } @@ -139,7 +139,7 @@ struct pod_vector{ } ~pod_vector() { - if(_data != nullptr) pool64_dealloc(_data); + if(_data != nullptr) pool128_dealloc(_data); } }; diff --git a/include/pocketpy/vm.h b/include/pocketpy/vm.h index 8d867f0b..7880e413 100644 --- a/include/pocketpy/vm.h +++ b/include/pocketpy/vm.h @@ -365,7 +365,7 @@ public: 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)); } - 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(Type type) { return &_all_types[type]; } 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; }else if constexpr(is_integral_v){ // int - i64 val = static_cast(std::forward<__T>(value)); - if(val >= Number::kMinSmallInt && val <= Number::kMaxSmallInt){ - val = (val << 2) | 0b10; - return reinterpret_cast(val); - }else{ - return vm->heap.gcnew(vm->tp_int, val); - } + PyVar retval(VM::tp_int, true); + retval.as() = static_cast(value); + return retval; }else if constexpr(is_floating_point_v){ // float - f64 val = static_cast(std::forward<__T>(value)); - return vm->heap.gcnew(vm->tp_float, val); + PyVar retval(VM::tp_float, true); + retval.as() = static_cast(value); + return retval; }else if constexpr(std::is_pointer_v){ return from_void_p(vm, (void*)value); }else{ @@ -529,19 +526,17 @@ __T _py_cast__internal(VM* vm, PyVar obj) { static_assert(!std::is_reference_v<__T>); // int if constexpr(with_check){ - if(is_small_int(obj)) return (T)(PK_BITS(obj) >> 2); - if(is_heap_int(obj)) return (T)PK_OBJ_GET(i64, obj); + if(is_int(obj)) return (T)obj.as(); vm->TypeError("expected 'int', got " + _type_name(vm, vm->_tp(obj)).escape()); }else{ - if(is_small_int(obj)) return (T)(PK_BITS(obj) >> 2); - return (T)PK_OBJ_GET(i64, obj); + return (T)obj.as(); } }else if constexpr(is_floating_point_v){ static_assert(!std::is_reference_v<__T>); // float - if(is_float(obj)) return PK_OBJ_GET(f64, obj); + if(is_float(obj)) return (T)obj.as(); 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()); }else if constexpr(std::is_enum_v){ static_assert(!std::is_reference_v<__T>); diff --git a/src/ceval.cpp b/src/ceval.cpp index 58a8b408..683ee46e 100644 --- a/src/ceval.cpp +++ b/src/ceval.cpp @@ -2,33 +2,34 @@ namespace pkpy{ -#define PREDICT_INT_OP(op) \ - if(is_small_int(_0) && is_small_int(_1)){ \ - TOP() = VAR((PK_BITS(_0)>>2) op (PK_BITS(_1)>>2)); \ - DISPATCH() \ +#define PREDICT_INT_OP(op) \ + if(is_int(_0) && is_int(_1)){ \ + TOP() = VAR(_0.as() op _1.as()); \ + DISPATCH() \ } -#define PREDICT_INT_DIV_OP(op) \ - if(is_small_int(_0) && is_small_int(_1)){ \ - if(_1 == (PyVar)0b10) ZeroDivisionError(); \ - TOP() = VAR((PK_BITS(_0)>>2) op (PK_BITS(_1)>>2)); \ - DISPATCH() \ +#define PREDICT_INT_DIV_OP(op) \ + if(is_int(_0) && is_int(_1)){ \ + i64 divisor = _1.as(); \ + if(_1.as() == 0) ZeroDivisionError(); \ + TOP() = VAR(_0.as() op divisor); \ + DISPATCH() \ } #define BINARY_F_COMPARE(func, op, rfunc) \ - PyVar ret; \ - const PyTypeInfo* _ti = _tp_info(_0); \ - if(_ti->m##func){ \ - ret = _ti->m##func(this, _0, _1); \ - }else{ \ - PyVar self; \ - PyVar _2 = get_unbound_method(_0, func, &self, false); \ + PyVar ret; \ + const PyTypeInfo* _ti = _tp_info(_0); \ + if(_ti->m##func){ \ + ret = _ti->m##func(this, _0, _1); \ + }else{ \ + PyVar self; \ + PyVar _2 = get_unbound_method(_0, func, &self, false); \ if(_2 != nullptr) ret = call_method(self, _2, _1); \ else ret = NotImplemented; \ } \ if(ret == NotImplemented){ \ - PyVar self; \ - PyVar _2 = get_unbound_method(_1, rfunc, &self, false); \ + PyVar self; \ + PyVar _2 = get_unbound_method(_1, rfunc, &self, false); \ if(_2 != nullptr) ret = call_method(self, _2, _0); \ else 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_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_FUNCTION: { @@ -243,7 +244,7 @@ __NEXT_STEP:; } } DISPATCH() case OP_LOAD_SUBSCR_SMALL_INT:{ - PyVar _1 = (PyVar)(uintptr_t)byte.arg; + PyVar _1 = VAR((int16_t)byte.arg); PyVar _0 = TOP(); // a auto _ti = _tp_info(_0); if(_ti->m__getitem__){ @@ -604,7 +605,7 @@ __NEXT_STEP:; case OP_IS_OP:{ PyVar _1 = POPX(); // rhs PyVar _0 = TOP(); // lhs - TOP() = VAR(static_cast((_0==_1) ^ byte.arg)); + TOP() = VAR(static_cast((uint16_t)(_0==_1) ^ byte.arg)); } DISPATCH() case OP_CONTAINS_OP:{ // a in b -> b __contains__ a diff --git a/src/cffi.cpp b/src/cffi.cpp index 6abc4cbc..17f2bae7 100644 --- a/src/cffi.cpp +++ b/src/cffi.cpp @@ -184,7 +184,7 @@ void add_module_c(VM* vm){ vm->bind(mod, "pp_deref(ptr: Tp) -> Tp", [](VM* vm, ArgsView args){ VoidP& ptr = CAST(VoidP&, args[0]); void* value = *reinterpret_cast(ptr.ptr); - return vm->heap.gcnew(args[0]->type, value); + return vm->heap.gcnew(args[0].type, value); }); PyVar type; @@ -226,13 +226,13 @@ void add_module_c(VM* vm){ VoidP& voidp = PK_OBJ_GET(VoidP, lhs); \ i64 offset = CAST(i64, rhs); \ T* target = (T*)voidp.ptr; \ - return vm->heap.gcnew(lhs->type, target + offset); \ + return vm->heap.gcnew(lhs.type, target + offset); \ }); \ vm->bind__sub__(type_t, [](VM* vm, PyVar lhs, PyVar rhs){ \ VoidP& voidp = PK_OBJ_GET(VoidP, lhs); \ i64 offset = CAST(i64, rhs); \ T* target = (T*)voidp.ptr; \ - return vm->heap.gcnew(lhs->type, target - offset); \ + return vm->heap.gcnew(lhs.type, target - offset); \ }); \ vm->bind__repr__(type_t, [](VM* vm, PyVar obj) -> Str{ \ VoidP& self = _CAST(VoidP&, obj); \ diff --git a/src/codeobject.cpp b/src/codeobject.cpp index a1ec7e76..a807ff7f 100644 --- a/src/codeobject.cpp +++ b/src/codeobject.cpp @@ -13,11 +13,11 @@ namespace pkpy{ } struct PySignalObject: PyObject { - PySignalObject() : PyObject(Type(0)) { gc_enabled = false; } + PySignalObject() : PyObject() { gc_enabled = false; } void _obj_gc_mark() override {} }; - PyVar const PY_NULL = new PySignalObject(); - PyVar const PY_OP_CALL = new PySignalObject(); - PyVar const PY_OP_YIELD = new PySignalObject(); + PyVar const PY_NULL(Type(), new PySignalObject()); + PyVar const PY_OP_CALL(Type(), new PySignalObject()); + PyVar const PY_OP_YIELD(Type(), new PySignalObject()); } // namespace pkpy \ No newline at end of file diff --git a/src/expr.cpp b/src/expr.cpp index da78831d..43d80c6e 100644 --- a/src/expr.cpp +++ b/src/expr.cpp @@ -10,7 +10,7 @@ namespace pkpy{ } inline bool is_small_int(i64 value){ - return value >= 0 && value < 1024; + return value >= INT16_MIN && value <= INT16_MAX; } int CodeEmitContext::get_loop() const { @@ -91,7 +91,6 @@ namespace pkpy{ int CodeEmitContext::emit_int(i64 value, int line){ if(is_small_int(value)){ - value = (value << 2) | 0b10; return emit_(OP_LOAD_SMALL_INT, (uint16_t)value, line); }else{ return emit_(OP_LOAD_CONST, add_const(VAR(value)), line); diff --git a/src/gc.cpp b/src/gc.cpp index 9ba74cd0..24f0ca6d 100644 --- a/src/gc.cpp +++ b/src/gc.cpp @@ -10,11 +10,11 @@ namespace pkpy{ alive.push_back(obj); }else{ #if PK_DEBUG_GC_STATS - deleted[obj->type] += 1; + deleted[obj.type] += 1; #endif if(_gc_on_delete) _gc_on_delete(vm, obj); obj->~PyObject(); - pool64_dealloc(obj); + pool64_dealloc(obj.get()); } } @@ -55,8 +55,8 @@ namespace pkpy{ } ManagedHeap::~ManagedHeap(){ - for(PyVar obj: _no_gc) { obj->~PyObject(); pool64_dealloc(obj); } - for(PyVar obj: gen) { 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.get()); } } diff --git a/src/memory.cpp b/src/memory.cpp index 2926b944..a30cc47d 100644 --- a/src/memory.cpp +++ b/src/memory.cpp @@ -121,7 +121,7 @@ struct DoubleLinkedList{ } }; -template +template struct MemoryPool{ static const int __MaxBlocks = 256*1024 / __BlockSize; static const int __MinArenaCount = PK_GC_MIN_THRESHOLD*100 / (256*1024); @@ -269,6 +269,7 @@ struct MemoryPool{ static MemoryPool<64> pool64; static MemoryPool<128> pool128; +static MemoryPool<256> pool256; void* pool64_alloc(size_t size) noexcept { return pool64.alloc(size); } 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_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 { pool64.shrink_to_fit(); pool128.shrink_to_fit(); + pool256.shrink_to_fit(); } std::string pool64_info() noexcept { return pool64.info(); } std::string pool128_info() noexcept { return pool128.info(); } +std::string pool256_info() noexcept { return pool256.info(); } } \ No newline at end of file diff --git a/src/pocketpy.cpp b/src/pocketpy.cpp index b42bf1e8..d29303cb 100644 --- a/src/pocketpy.cpp +++ b/src/pocketpy.cpp @@ -173,7 +173,7 @@ void __init_builtins(VM* _vm) { _vm->bind_func(_vm->builtins, "id", 1, [](VM* vm, ArgsView args) { PyVar obj = args[0]; if(is_tagged(obj)) return vm->None; - return VAR(PK_BITS(obj)); + return VAR(reinterpret_cast(obj.get())); }); _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(); SStream ss; ss << "<" << _type_name(vm, vm->_tp(obj)) << " object at "; - ss.write_hex(obj); + ss.write_hex(obj.get()); ss << ">"; return ss.str(); }); @@ -1482,7 +1482,7 @@ void __init_builtins(VM* _vm) { _vm->bind__repr__(VM::tp_exception, [](VM* vm, PyVar _0) -> Str { 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{ diff --git a/src/tuplelist.cpp b/src/tuplelist.cpp index ab11fb38..2d28e0b0 100644 --- a/src/tuplelist.cpp +++ b/src/tuplelist.cpp @@ -6,7 +6,7 @@ Tuple::Tuple(int n){ if(n <= 3){ this->_args = _inlined; }else{ - this->_args = (PyVar*)pool64_alloc(n * sizeof(void*)); + this->_args = (PyVar*)pool128_alloc(n * sizeof(void*)); } this->_size = n; } @@ -51,7 +51,7 @@ Tuple::Tuple(PyVar _0, PyVar _1, PyVar _2, PyVar _3): Tuple(4){ _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 ret(size()); diff --git a/src/vm.cpp b/src/vm.cpp index a4eb0f3b..952208ac 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -501,7 +501,7 @@ i64 VM::py_hash(PyVar obj){ return CAST(i64, ret); } // 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__ bool has_custom_eq = false; 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())); PK_UNREACHABLE() }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: argStr += _S(" (", co->func_decls[byte.arg]->code->name, ")").sv(); break; - case OP_LOAD_SMALL_INT: case OP_LOAD_SUBSCR_SMALL_INT: - argStr += _S(" (", (int)(byte.arg >> 2), ")").sv(); } return argStr; } @@ -1168,12 +1166,12 @@ PyVar VM::getattr(PyVar obj, StrName name, bool throw_err){ // handle instance __dict__ if(!is_tagged(obj) && obj->is_attr_valid()){ PyVar val; - if(obj->type == tp_type){ + if(obj.type == tp_type){ val = find_name_in_mro(PK_OBJ_GET(Type, obj), name); if(val != nullptr){ if(is_tagged(val)) return val; - 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_staticmethod) return PK_OBJ_GET(StaticMethod, val).func; + if(val.type == tp_classmethod) return VAR(BoundMethod(obj, PK_OBJ_GET(ClassMethod, val).func)); return val; } }else{ @@ -1184,7 +1182,7 @@ PyVar VM::getattr(PyVar obj, StrName name, bool throw_err){ if(cls_var != nullptr){ // bound method is non-data descriptor if(!is_tagged(cls_var)){ - switch(cls_var->type){ + switch(cls_var.type){ case tp_function.index: return VAR(BoundMethod(obj, cls_var)); 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__ if(!is_tagged(obj) && obj->is_attr_valid()){ PyVar val; - if(obj->type == tp_type){ + if(obj.type == tp_type){ val = find_name_in_mro(PK_OBJ_GET(Type, obj), name); if(val != nullptr){ if(is_tagged(val)) return val; - 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_staticmethod) return PK_OBJ_GET(StaticMethod, val).func; + if(val.type == tp_classmethod) return VAR(BoundMethod(obj, PK_OBJ_GET(ClassMethod, val).func)); return val; } }else{ @@ -1251,7 +1249,7 @@ PyVar VM::get_unbound_method(PyVar obj, StrName name, PyVar* self, bool throw_er if(cls_var != nullptr){ if(!is_tagged(cls_var)){ - switch(cls_var->type){ + switch(cls_var.type){ case tp_function.index: *self = obj; break;