gc.cpp 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. #include "pocketpy/gc.h"
  2. namespace pkpy{
  3. int ManagedHeap::sweep(){
  4. std::vector<PyObject*> alive;
  5. for(PyObject* obj: gen){
  6. if(obj->gc_marked){
  7. obj->gc_marked = false;
  8. alive.push_back(obj);
  9. }else{
  10. #if PK_DEBUG_GC_STATS
  11. deleted[obj->type] += 1;
  12. #endif
  13. if(_gc_on_delete) _gc_on_delete(vm, obj);
  14. obj->~PyObject();
  15. pool64_dealloc(obj);
  16. }
  17. }
  18. // clear _no_gc marked flag
  19. for(PyObject* obj: _no_gc) obj->gc_marked = false;
  20. int freed = gen.size() - alive.size();
  21. #if PK_DEBUG_GC_STATS
  22. for(auto& [type, count]: deleted){
  23. std::cout << "GC: " << _type_name(vm, type).sv() << "=" << count << std::endl;
  24. }
  25. std::cout << "GC: " << alive.size() << "/" << gen.size() << " (" << freed << " freed)" << std::endl;
  26. deleted.clear();
  27. #endif
  28. gen.clear();
  29. gen.swap(alive);
  30. // clean up pools
  31. pools_shrink_to_fit();
  32. return freed;
  33. }
  34. void ManagedHeap::_auto_collect(){
  35. #if !PK_DEBUG_NO_AUTO_GC
  36. if(_gc_lock_counter > 0) return;
  37. gc_counter = 0;
  38. collect();
  39. gc_threshold = gen.size() * 2;
  40. if(gc_threshold < PK_GC_MIN_THRESHOLD) gc_threshold = PK_GC_MIN_THRESHOLD;
  41. #endif
  42. }
  43. int ManagedHeap::collect(){
  44. PK_ASSERT(_gc_lock_counter == 0)
  45. mark();
  46. int freed = sweep();
  47. return freed;
  48. }
  49. ManagedHeap::~ManagedHeap(){
  50. for(PyObject* obj: _no_gc) { obj->~PyObject(); pool64_dealloc(obj); }
  51. for(PyObject* obj: gen) { obj->~PyObject(); pool64_dealloc(obj); }
  52. }
  53. void FuncDecl::_gc_mark() const{
  54. code->_gc_mark();
  55. for(int i=0; i<kwargs.size(); i++) PK_OBJ_MARK(kwargs[i].value);
  56. }
  57. } // namespace pkpy