gc.h 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. #pragma once
  2. #include "common.h"
  3. #include "memory.h"
  4. #include "obj.h"
  5. #include "codeobject.h"
  6. #include "namedict.h"
  7. namespace pkpy {
  8. struct ManagedHeap{
  9. std::vector<PyObject*> _no_gc;
  10. std::vector<PyObject*> gen;
  11. VM* vm;
  12. void (*_gc_on_delete)(VM*, PyObject*) = nullptr;
  13. void (*_gc_marker_ex)(VM*) = nullptr;
  14. ManagedHeap(VM* vm): vm(vm) {}
  15. int gc_threshold = PK_GC_MIN_THRESHOLD;
  16. int gc_counter = 0;
  17. /********************/
  18. int _gc_lock_counter = 0;
  19. struct ScopeLock{
  20. PK_ALWAYS_PASS_BY_POINTER(ScopeLock)
  21. ManagedHeap* heap;
  22. ScopeLock(ManagedHeap* heap): heap(heap){
  23. heap->_gc_lock_counter++;
  24. }
  25. ~ScopeLock(){
  26. heap->_gc_lock_counter--;
  27. }
  28. };
  29. ScopeLock gc_scope_lock(){
  30. return ScopeLock(this);
  31. }
  32. /********************/
  33. template<typename T, typename... Args>
  34. PyVar gcnew(Type type, Args&&... args){
  35. using __T = std::decay_t<T>;
  36. static_assert(!is_sso_v<__T>, "gcnew cannot be used with SSO types");
  37. // https://github.com/pocketpy/pocketpy/issues/94#issuecomment-1594784476
  38. PyObject* p = new(pool128_alloc(py_sizeof<__T>)) PyObject(type);
  39. p->placement_new<__T>(std::forward<Args>(args)...);
  40. gen.push_back(p);
  41. gc_counter++;
  42. return PyVar(type, p);
  43. }
  44. template<typename T, typename... Args>
  45. PyVar _new(Type type, Args&&... args){
  46. using __T = std::decay_t<T>;
  47. static_assert(!is_sso_v<__T>);
  48. PyObject* p = new(pool128_alloc(py_sizeof<__T>)) PyObject(type);
  49. p->placement_new<__T>(std::forward<Args>(args)...);
  50. _no_gc.push_back(p);
  51. return PyVar(type, p);
  52. }
  53. void _delete(PyObject*);
  54. #if PK_DEBUG_GC_STATS
  55. inline static std::map<Type, int> deleted;
  56. #endif
  57. int sweep();
  58. void _auto_collect();
  59. bool _should_auto_collect() const { return gc_counter >= gc_threshold; }
  60. int collect();
  61. void mark();
  62. };
  63. } // namespace pkpy