From 4b687d36ff9b0241e0d0349db90338426792faa6 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 9 Jun 2024 21:26:54 +0800 Subject: [PATCH] some fix --- include/pocketpy/common/memorypool.hpp | 3 ++- include/pocketpy/interpreter/gc.hpp | 14 +++++++++-- include/pocketpy/objects/object.hpp | 5 ++-- src/common/memorypool.cpp | 33 ++++++++++---------------- src/interpreter/vm.cpp | 6 ++++- src/objects/builtins.cpp | 4 ++-- 6 files changed, 36 insertions(+), 29 deletions(-) diff --git a/include/pocketpy/common/memorypool.hpp b/include/pocketpy/common/memorypool.hpp index cbe5c0ee..72961d59 100644 --- a/include/pocketpy/common/memorypool.hpp +++ b/include/pocketpy/common/memorypool.hpp @@ -10,13 +10,14 @@ namespace pkpy { const inline int kPoolExprBlockSize = 128; const inline int kPoolFrameBlockSize = 80; +const inline int kPoolObjectBlockSize = 80; void* PoolExpr_alloc() noexcept; void PoolExpr_dealloc(void*) noexcept; void* PoolFrame_alloc() noexcept; void PoolFrame_dealloc(void*) noexcept; -void* PoolObject_alloc(size_t size) noexcept; +void* PoolObject_alloc() noexcept; void PoolObject_dealloc(void* p) noexcept; void PoolObject_shrink_to_fit() noexcept; diff --git a/include/pocketpy/interpreter/gc.hpp b/include/pocketpy/interpreter/gc.hpp index 82cc7eb6..cf6abcad 100644 --- a/include/pocketpy/interpreter/gc.hpp +++ b/include/pocketpy/interpreter/gc.hpp @@ -40,7 +40,12 @@ struct ManagedHeap { using __T = std::decay_t; static_assert(!is_sso_v<__T>, "gcnew cannot be used with SSO types"); // https://github.com/pocketpy/pocketpy/issues/94#issuecomment-1594784476 - PyObject* p = new (PoolObject_alloc(py_sizeof<__T>)) PyObject(type); + PyObject* p; + if constexpr(py_sizeof<__T> <= kPoolObjectBlockSize){ + p = new (PoolObject_alloc()) PyObject(type, false); + }else{ + p = new (std::malloc(py_sizeof<__T>)) PyObject(type, true); + } p->placement_new<__T>(std::forward(args)...); gen.push_back(p); gc_counter++; @@ -51,7 +56,12 @@ struct ManagedHeap { PyObject* _new(Type type, Args&&... args) { using __T = std::decay_t; static_assert(!is_sso_v<__T>); - PyObject* p = new (PoolObject_alloc(py_sizeof<__T>)) PyObject(type); + PyObject* p; + if constexpr(py_sizeof<__T> <= kPoolObjectBlockSize){ + p = new (PoolObject_alloc()) PyObject(type, false); + }else{ + p = new (std::malloc(py_sizeof<__T>)) PyObject(type, true); + } p->placement_new<__T>(std::forward(args)...); _no_gc.push_back(p); return p; diff --git a/include/pocketpy/objects/object.hpp b/include/pocketpy/objects/object.hpp index 1e641182..52641b19 100644 --- a/include/pocketpy/objects/object.hpp +++ b/include/pocketpy/objects/object.hpp @@ -9,8 +9,9 @@ namespace pkpy { struct NameDict; struct PyObject final { - bool gc_marked; // whether this object is marked Type type; // we have a duplicated type here for convenience + bool gc_is_large; + bool gc_marked; NameDict* _attr; // gc will delete this on destruction bool is_attr_valid() const noexcept { return _attr != nullptr; } @@ -28,7 +29,7 @@ struct PyObject final { return *_attr; } - PyObject(Type type) : gc_marked(false), type(type), _attr(nullptr) {} + PyObject(Type type, bool gc_is_large) : type(type), gc_is_large(gc_is_large), gc_marked(false), _attr(nullptr) {} PyVar attr(StrName name) const; static NameDict* __init_namedict(float lf); diff --git a/src/common/memorypool.cpp b/src/common/memorypool.cpp index 0c82b0ad..edb72adc 100644 --- a/src/common/memorypool.cpp +++ b/src/common/memorypool.cpp @@ -87,8 +87,8 @@ struct DoubleLinkedList { } }; -template struct MemoryPool { + const static int __BlockSize = kPoolObjectBlockSize; const static int __MaxBlocks = 256 * 1024 / __BlockSize; const static int __MinArenaCount = PK_GC_MIN_THRESHOLD * 100 / (256 * 1024); @@ -138,14 +138,8 @@ struct MemoryPool { DoubleLinkedList _arenas; DoubleLinkedList _empty_arenas; - void* alloc(size_t size) { + void* alloc() { PK_GLOBAL_SCOPE_LOCK(); - if(size > __BlockSize) { - void* p = std::malloc(sizeof(void*) + size); - std::memset(p, 0, sizeof(void*)); - return (char*)p + sizeof(void*); - } - if(_arenas.empty()) { _arenas.push_back(new Arena()); } Arena* arena = _arenas.back(); void* p = arena->alloc()->data; @@ -160,17 +154,14 @@ struct MemoryPool { PK_GLOBAL_SCOPE_LOCK(); assert(p != nullptr); Block* block = (Block*)((char*)p - sizeof(void*)); - if(block->arena == nullptr) { - std::free(block); + assert(block->arena != nullptr); + Arena* arena = (Arena*)block->arena; + if(arena->empty()) { + _empty_arenas.erase(arena); + _arenas.push_front(arena); + arena->dealloc(block); } else { - Arena* arena = (Arena*)block->arena; - if(arena->empty()) { - _empty_arenas.erase(arena); - _arenas.push_front(arena); - arena->dealloc(block); - } else { - arena->dealloc(block); - } + arena->dealloc(block); } } @@ -248,7 +239,7 @@ struct FixedMemoryPool { static FixedMemoryPool PoolExpr; static FixedMemoryPool PoolFrame; -static MemoryPool<80> PoolObject; +static MemoryPool PoolObject; void* PoolExpr_alloc() noexcept { return PoolExpr.alloc(); } @@ -258,7 +249,7 @@ void* PoolFrame_alloc() noexcept { return PoolFrame.alloc(); } void PoolFrame_dealloc(void* p) noexcept { PoolFrame.dealloc(p); } -void* PoolObject_alloc(size_t size) noexcept { return PoolObject.alloc(size); } +void* PoolObject_alloc() noexcept { return PoolObject.alloc(); } void PoolObject_dealloc(void* p) noexcept { PoolObject.dealloc(p); } @@ -292,7 +283,7 @@ void Pools_debug_info(char* buffer, int size) noexcept { ); buffer += n; size -= n; // log each non-empty arena - PoolObject._arenas.apply([&](MemoryPool<80>::Arena* arena) { + PoolObject._arenas.apply([&](MemoryPool::Arena* arena) { n = snprintf( buffer, size, " - %p: %.2f MB (used) / %.2f MB (total)\n", (void*)arena, diff --git a/src/interpreter/vm.cpp b/src/interpreter/vm.cpp index 3508385e..3ea17293 100644 --- a/src/interpreter/vm.cpp +++ b/src/interpreter/vm.cpp @@ -1902,7 +1902,11 @@ void ManagedHeap::_delete(PyObject* obj) { const PyTypeInfo* ti = vm->_tp_info(obj->type); if(ti->vt._dtor) ti->vt._dtor(obj->_value_ptr()); delete obj->_attr; // delete __dict__ if exists - PoolObject_dealloc(obj); + if(obj->gc_is_large){ + std::free(obj); + }else{ + PoolObject_dealloc(obj); + } } void Dict::_gc_mark(VM* vm) const { diff --git a/src/objects/builtins.cpp b/src/objects/builtins.cpp index 1e70a44c..fb944eaa 100644 --- a/src/objects/builtins.cpp +++ b/src/objects/builtins.cpp @@ -1,6 +1,6 @@ #include "pocketpy/objects/builtins.hpp" namespace pkpy { -const PyVar PY_OP_CALL(Type(), new PyObject(Type())); -const PyVar PY_OP_YIELD(Type(), new PyObject(Type())); +const PyVar PY_OP_CALL(Type(), new PyObject(Type(), true)); +const PyVar PY_OP_YIELD(Type(), new PyObject(Type(), true)); } // namespace pkpy