blueloveTH 1 năm trước cách đây
mục cha
commit
4b687d36ff

+ 2 - 1
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;
 

+ 12 - 2
include/pocketpy/interpreter/gc.hpp

@@ -40,7 +40,12 @@ struct ManagedHeap {
         using __T = std::decay_t<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>(args)...);
         gen.push_back(p);
         gc_counter++;
@@ -51,7 +56,12 @@ struct ManagedHeap {
     PyObject* _new(Type type, Args&&... args) {
         using __T = std::decay_t<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>(args)...);
         _no_gc.push_back(p);
         return p;

+ 3 - 2
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);

+ 12 - 21
src/common/memorypool.cpp

@@ -87,8 +87,8 @@ struct DoubleLinkedList {
     }
 };
 
-template <int __BlockSize>
 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<Arena> _arenas;
     DoubleLinkedList<Arena> _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<kPoolExprBlockSize, 64> PoolExpr;
 static FixedMemoryPool<kPoolFrameBlockSize, 128> 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,

+ 5 - 1
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 {

+ 2 - 2
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