diff --git a/mycpp/gc_dict.h b/mycpp/gc_dict.h index 4b04c6a67a..a62dc68b88 100644 --- a/mycpp/gc_dict.h +++ b/mycpp/gc_dict.h @@ -48,7 +48,7 @@ class _DummyDict { void* values_; }; -// A list has one Slab pointer which we need to follow. +// A dict has 3 pointers the GC needs to follow. constexpr uint16_t maskof_Dict() { return maskbit(offsetof(_DummyDict, entry_)) | maskbit(offsetof(_DummyDict, keys_)) | diff --git a/mycpp/marksweep_gc_test.cc b/mycpp/marksweep_gc_test.cc index 2bb6157abd..267bbcf908 100644 --- a/mycpp/marksweep_gc_test.cc +++ b/mycpp/marksweep_gc_test.cc @@ -82,6 +82,40 @@ TEST list_collection_test() { PASS(); } +class Node : Obj { + public: + Node(); + Node* next_; +}; + +constexpr uint16_t maskof_Node() { + return maskbit(offsetof(Node, next_)); +} + +Node::Node() : + Obj(Tag::FixedSize, maskof_Node(), sizeof(Node)), + next_(nullptr) { +} + +TEST cycle_collection_test() { + // Dict* d = NewDict(); + + Node* n1 = nullptr; + Node* n2 = nullptr; + StackRoots _roots({&n1, &n2}); + n1 = Alloc(); + n2 = Alloc(); + + gHeap.Collect(); + + n1->next_ = n2; + n2->next_ = n1; + + gHeap.Collect(); + + PASS(); +} + GREATEST_MAIN_DEFS(); int main(int argc, char **argv) { @@ -93,6 +127,9 @@ int main(int argc, char **argv) { RUN_TEST(string_collection_test); RUN_TEST(list_collection_test); + RUN_TEST(cycle_collection_test); + + gHeap.Collect(); GREATEST_MAIN_END(); /* display results */ return 0; diff --git a/mycpp/marksweep_heap.cc b/mycpp/marksweep_heap.cc index 316e5a835f..d28b89d113 100644 --- a/mycpp/marksweep_heap.cc +++ b/mycpp/marksweep_heap.cc @@ -53,6 +53,13 @@ void* MarkSweepHeap::Allocate(int byte_count) { void MarkSweepHeap::MarkAllReferences(Obj* obj) { auto header = ObjHeader(obj); + auto marked_alloc = marked_allocations_.find((Obj*)obj); + bool alloc_is_marked = marked_alloc != marked_allocations_.end(); + if (alloc_is_marked) + { + return; + } + this->marked_allocations_.insert(static_cast(obj)); switch (header->heap_tag_) {