This commit is contained in:
blueloveTH 2024-06-09 21:26:54 +08:00
parent 0946c67fe0
commit 4b687d36ff
6 changed files with 36 additions and 29 deletions

View File

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

View File

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

View File

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

View File

@ -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,9 +154,7 @@ struct MemoryPool {
PK_GLOBAL_SCOPE_LOCK();
assert(p != nullptr);
Block* block = (Block*)((char*)p - sizeof(void*));
if(block->arena == nullptr) {
std::free(block);
} else {
assert(block->arena != nullptr);
Arena* arena = (Arena*)block->arena;
if(arena->empty()) {
_empty_arenas.erase(arena);
@ -172,7 +164,6 @@ struct MemoryPool {
arena->dealloc(block);
}
}
}
void shrink_to_fit() {
PK_GLOBAL_SCOPE_LOCK();
@ -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,

View File

@ -1902,8 +1902,12 @@ 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
if(obj->gc_is_large){
std::free(obj);
}else{
PoolObject_dealloc(obj);
}
}
void Dict::_gc_mark(VM* vm) const {
apply([vm](PyVar k, PyVar v) {

View File

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