2024-05-13 17:50:51 +08:00

77 lines
2.0 KiB
C++

#pragma once
#include "common.h"
#include "memory.h"
#include "obj.h"
#include "codeobject.h"
#include "namedict.h"
namespace pkpy {
struct ManagedHeap{
std::vector<PyVar> _no_gc;
std::vector<PyVar> gen;
VM* vm;
void (*_gc_on_delete)(VM*, PyVar) = nullptr;
void (*_gc_marker_ex)(VM*) = nullptr;
ManagedHeap(VM* vm): vm(vm) {}
int gc_threshold = PK_GC_MIN_THRESHOLD;
int gc_counter = 0;
/********************/
int _gc_lock_counter = 0;
struct ScopeLock{
PK_ALWAYS_PASS_BY_POINTER(ScopeLock)
ManagedHeap* heap;
ScopeLock(ManagedHeap* heap): heap(heap){
heap->_gc_lock_counter++;
}
~ScopeLock(){
heap->_gc_lock_counter--;
}
};
ScopeLock gc_scope_lock(){
return ScopeLock(this);
}
/********************/
template<typename T, typename... Args>
PyVar gcnew(Type type, Args&&... args){
using __T = Py_<std::decay_t<T>>;
static_assert(!is_sso_v<std::decay_t<T>>, "gcnew cannot be used with SSO types");
// https://github.com/pocketpy/pocketpy/issues/94#issuecomment-1594784476
PyObject* p = new(pool128_alloc<__T>()) Py_<std::decay_t<T>>(std::forward<Args>(args)...);
PyVar obj(type, p);
gen.push_back(obj);
gc_counter++;
return obj;
}
template<typename T, typename... Args>
PyVar _new(Type type, Args&&... args){
using __T = Py_<std::decay_t<T>>;
static_assert(!is_sso_v<std::decay_t<T>>);
PyObject* p = new(pool128_alloc<__T>()) Py_<std::decay_t<T>>(std::forward<Args>(args)...);
PyVar obj(type, p);
obj->gc_enabled = false;
_no_gc.push_back(obj);
return obj;
}
#if PK_DEBUG_GC_STATS
inline static std::map<Type, int> deleted;
#endif
int sweep();
void _auto_collect();
bool _should_auto_collect() const { return gc_counter >= gc_threshold; }
int collect();
void mark();
~ManagedHeap();
};
} // namespace pkpy