From 3e188553d6d69e3397ed3a23f0c7d46a1f916f87 Mon Sep 17 00:00:00 2001 From: Victor Olin Date: Thu, 4 May 2023 18:18:25 +0200 Subject: [PATCH] rip gc Co-authored-by: ValterMiari --- src/GC/Makefile | 15 ++++-- src/GC/include/heap.hpp | 16 ++++-- src/GC/include/profiler.hpp | 2 +- src/GC/lib/heap.cpp | 102 ++++++++++++++++++++++++++++++++++-- src/GC/tests/linkedlist.cpp | 54 ++++++++++++++++--- src/GC/tests/pointers.cpp | 39 ++++++++++++++ src/GC/tests/revrange.cpp | 43 +++++++++++++++ 7 files changed, 252 insertions(+), 19 deletions(-) create mode 100644 src/GC/tests/pointers.cpp create mode 100644 src/GC/tests/revrange.cpp diff --git a/src/GC/Makefile b/src/GC/Makefile index 87a3a83..e92237f 100644 --- a/src/GC/Makefile +++ b/src/GC/Makefile @@ -66,9 +66,9 @@ static_lib: # remove old files rm -f lib/event.o lib/profiler.o lib/heap.o lib/gcoll.a tests/extern_lib.out # compile object files - $(CC) $(STDFLAGS) $(WFLAGS) $(LIB_INCL) -O3 -c -o lib/event.o lib/event.cpp -fPIC - $(CC) $(STDFLAGS) $(WFLAGS) $(LIB_INCL) -O3 -c -o lib/profiler.o lib/profiler.cpp -fPIC - $(CC) $(STDFLAGS) $(WFLAGS) $(LIB_INCL) -O3 -c -o lib/heap.o lib/heap.cpp -fPIC + $(CC) $(STDFLAGS) $(WFLAGS) $(LIB_INCL) -c -o lib/event.o lib/event.cpp -fPIC + $(CC) $(STDFLAGS) $(WFLAGS) $(LIB_INCL) -c -o lib/profiler.o lib/profiler.cpp -fPIC + $(CC) $(STDFLAGS) $(WFLAGS) $(LIB_INCL) -c -o lib/heap.o lib/heap.cpp -fPIC # create static library ar r lib/gcoll.a lib/event.o lib/profiler.o lib/heap.o @@ -103,7 +103,16 @@ alloc_free_list: static_lib linked_list_test: static_lib $(CC) $(STDFLAGS) $(WFLAGS) $(LIB_INCL) -o tests/linkedlist.out tests/linkedlist.cpp lib/gcoll.a +<<<<<<< HEAD >>>>>>> d7ea27e (testing testing...) +======= +revrange: static_lib + $(CC) $(STDFLAGS) $(WFLAGS) $(LIB_INCL) -o tests/revrange.out tests/revrange.cpp lib/gcoll.a + +pointers: static_lib + $(CC) $(STDFLAGS) $(WFLAGS) $(LIB_INCL) -o tests/pointers.out tests/pointers.cpp lib/gcoll.a + +>>>>>>> a910d54 (rip gc) wrapper: # remove old files rm -f lib/event.o lib/profiler.o lib/heap.o lib/coll.a tests/wrapper.out diff --git a/src/GC/include/heap.hpp b/src/GC/include/heap.hpp index eb161c0..2d116bb 100644 --- a/src/GC/include/heap.hpp +++ b/src/GC/include/heap.hpp @@ -7,9 +7,9 @@ #include "chunk.hpp" #include "profiler.hpp" -#define HEAP_SIZE 65536 -#define FREE_THRESH (uint) 100 -#define HEAP_DEBUG +#define HEAP_SIZE 320//65536 +#define FREE_THRESH (uint) 0 +// #define HEAP_DEBUG namespace GC { @@ -23,7 +23,14 @@ namespace GC MARK_SWEEP = 1 << 2, FREE = 1 << 3, COLLECT_ALL = 0b1111 // all flags above - }; + }; + + struct AddrRange + { + const uintptr_t *start, *end; + + AddrRange(uintptr_t *_start, uintptr_t *_end) : start(_start), end(_end) {} + }; /** * The heap class to represent the heap for the @@ -65,6 +72,7 @@ namespace GC void print_line(Chunk *chunk); void print_worklist(std::vector &list); void mark_step(uintptr_t start, uintptr_t end, std::vector &worklist); + void mark_range(std::vector &ranges, std::vector &worklist); // Temporary Chunk *try_recycle_chunks_new(size_t size); diff --git a/src/GC/include/profiler.hpp b/src/GC/include/profiler.hpp index f70ca3b..1c44ef6 100644 --- a/src/GC/include/profiler.hpp +++ b/src/GC/include/profiler.hpp @@ -14,7 +14,7 @@ namespace GC { enum RecordOption { - FunctionCalls = (GC::AllocStart | GC::CollectStart | GC::MarkStart | GC::SweepStart), + FunctionCalls = (GC::AllocStart | GC::CollectStart | GC::MarkStart | GC::SweepStart | GC::FreeStart), ChunkOps = (GC::ChunkMarked | GC::ChunkSwept | GC::ChunkFreed | GC::NewChunk | GC::ReusedChunk), AllOps = 0xFFFFFF }; diff --git a/src/GC/lib/heap.cpp b/src/GC/lib/heap.cpp index fade27a..ff1743d 100644 --- a/src/GC/lib/heap.cpp +++ b/src/GC/lib/heap.cpp @@ -207,7 +207,7 @@ namespace GC Profiler::record(CollectStart); // get current stack frame - auto stack_bottom = reinterpret_cast(__builtin_frame_address(0)); + auto stack_bottom = reinterpret_cast(__builtin_frame_address(2)); if (heap.m_stack_top == nullptr) throw std::runtime_error(std::string("Error: Heap is not initialized, read the docs!")); @@ -244,11 +244,14 @@ namespace GC */ void Heap::mark(uintptr_t *start, const uintptr_t* const end, vector &worklist) { + // cout << "\nWorklist size: " << worklist.size() << "\n"; Heap &heap = Heap::the(); bool profiler_enabled = heap.m_profiler_enable; if (profiler_enabled) Profiler::record(MarkStart); + vector rangeWL; + // To find adresses thats in the worklist for (; start <= end; start++) { @@ -258,8 +261,8 @@ namespace GC { Chunk *chunk = *it; auto c_start = reinterpret_cast(chunk->m_start); - auto c_size = reinterpret_cast(chunk->m_size); - auto c_end = reinterpret_cast(c_start + c_size); + auto c_size = reinterpret_cast(chunk->m_size); + auto c_end = reinterpret_cast(c_start + c_size); // Check if the stack pointer points to something within the chunk if (c_start <= *start && *start < c_end) @@ -271,8 +274,22 @@ namespace GC chunk->m_marked = true; it = worklist.erase(it); + Chunk *next = find_pointer((uintptr_t *) c_start, (uintptr_t *) c_end, worklist); + while (next != NULL) { + if (!next->m_marked) + { + next->m_marked = true; + auto c_start = reinterpret_cast(next->m_start); + auto c_size = reinterpret_cast(next->m_size); + auto c_end = reinterpret_cast(c_start + c_size); + next = find_pointer((uintptr_t *) c_start, (uintptr_t *) c_end, worklist); + } + } + // Recursively call mark, to see if the reachable chunk further points to another chunk - mark((uintptr_t *)c_start, (uintptr_t *)c_end, worklist); + // mark((uintptr_t *)c_start, (uintptr_t *)c_end, worklist); + // AddrRange *range = new AddrRange((uintptr_t *)c_start, (uintptr_t *)c_end); + rangeWL.push_back(new AddrRange((uintptr_t *)c_start, (uintptr_t *)c_end)); } else { @@ -285,8 +302,60 @@ namespace GC } } } + mark_range(rangeWL, worklist); + rangeWL.clear(); } + void Heap::mark_range(vector &ranges, vector &worklist) + { + Heap &heap = Heap::the(); + bool profiler_enabled = heap.m_profiler_enable; + if (profiler_enabled) + Profiler::record(MarkStart); + + auto iter = ranges.begin(); + auto stop = ranges.end(); + + while (iter != stop) + { + auto range = *iter++; + uintptr_t *start = (uintptr_t *)range->start; + const uintptr_t *end = range->end; + if (start == nullptr) + cout << "\nstart is null\n"; + for (; start <= end; start++) + { + auto wliter = worklist.begin(); + auto wlstop = worklist.end(); + while (wliter != wlstop) + { + Chunk *chunk = *wliter; + auto c_start = reinterpret_cast(chunk->m_start); + auto c_size = reinterpret_cast(chunk->m_size); + auto c_end = reinterpret_cast(c_start + c_size); + + if (c_start <= *start && *start < c_end) + { + if (!chunk->m_marked) + { + chunk->m_marked = true; + wliter = worklist.erase(wliter); + ranges.push_back(new AddrRange((uintptr_t *)c_start, (uintptr_t *)c_end)); + stop = ranges.end(); + } + else + { + wliter++; + } + } + else + { + wliter++; + } + } + } + } + } /** * Sweeps the heap, unmarks the marked chunks for the next cycle, @@ -304,6 +373,7 @@ namespace GC if (profiler_enabled) Profiler::record(SweepStart); auto iter = heap.m_allocated_chunks.begin(); + std::cout << "Chunks alloced: " << heap.m_allocated_chunks.size() << std::endl; // This cannot "iter != stop", results in seg fault, since the end gets updated, I think. while (iter != heap.m_allocated_chunks.end()) { @@ -326,6 +396,7 @@ namespace GC heap.m_size -= chunk->m_size; } } + std::cout << "Chunks left: " << heap.m_allocated_chunks.size() << std::endl; } /** @@ -390,7 +461,7 @@ namespace GC auto prev = heap.m_freed_chunks[i++]; prev->m_marked = true; filtered.push_back(prev); - cout << filtered.back()->m_start << endl; + // cout << filtered.back()->m_start << endl; for (; i < heap.m_freed_chunks.size(); i++) { prev = filtered.back(); @@ -432,6 +503,27 @@ namespace GC heap.m_profiler_enable = mode; } + Chunk* find_pointer(uintptr_t *start, const uintptr_t* const end, vector &worklist) { + for (; start <= end; start++) { + auto it = worklist.begin(); + auto stop = worklist.end(); + while (it != stop) + { + Chunk *chunk = *it; + auto c_start = reinterpret_cast(chunk->m_start); + auto c_size = reinterpret_cast(chunk->m_size); + auto c_end = reinterpret_cast(c_start + c_size); + + // Check if the stack pointer points to something within the chunk + if (c_start <= *start && *start < c_end) + { + return chunk; + } + return NULL; + } + } + } + #ifdef HEAP_DEBUG /** * Prints the result of Heap::init() and a dummy value diff --git a/src/GC/tests/linkedlist.cpp b/src/GC/tests/linkedlist.cpp index 61ab3c4..ccb07d9 100644 --- a/src/GC/tests/linkedlist.cpp +++ b/src/GC/tests/linkedlist.cpp @@ -19,10 +19,11 @@ Node *create_list(size_t length) head->value = 0; Node *prev = head; + Node *next; for (size_t i = 1; i < length; i++) { - Node *next = allocNode; + next = allocNode; next->value = i; prev->next = next; prev = next; @@ -52,10 +53,51 @@ void clear_list(Node *head) } } -void run_list_test() +#define LIST_SIZE 10 + +void list_test1() { - Node *list = create_list(10); - print_list(list); + Node *list_1 = create_list(LIST_SIZE); + // print_list(list_1); +} + +void list_test2() +{ + Node *list_2 = create_list(LIST_SIZE); + // print_list(list_2); +} + +void list_test3() +{ + Node *list_3 = create_list(LIST_SIZE); + // print_list(list_3); +} + +void list_test4() +{ + Node *list_4 = create_list(LIST_SIZE); + // print_list(list_4); +} + +void list_test5() +{ + Node *list_5 = create_list(LIST_SIZE); + // print_list(list_5); +} + +void list_test6() +{ + Node *list_6 = create_list(LIST_SIZE); + // print_list(list_6); +} + +void make_test() { + list_test1(); + list_test2(); + list_test3(); + list_test4(); + list_test5(); + list_test6(); } int main() @@ -64,9 +106,9 @@ int main() GC::Heap &heap = GC::Heap::the(); heap.set_profiler(true); GC::Profiler::set_log_options(GC::FunctionCalls); + // GC::Profiler::set_log_options(GC::AllOps); - for (int i = 0; i < 10; i++) - run_list_test(); + make_test(); GC::Heap::dispose(); diff --git a/src/GC/tests/pointers.cpp b/src/GC/tests/pointers.cpp new file mode 100644 index 0000000..265ca30 --- /dev/null +++ b/src/GC/tests/pointers.cpp @@ -0,0 +1,39 @@ +#include +#include +#include + +#include "heap.hpp" + +using std::cout, std::endl, std::hex; + +struct Node { + int value; + Node *next {nullptr}; +}; + +void test(Node *n) { + size_t n_size = 16; + + auto c_start = reinterpret_cast(n); + auto c_size = reinterpret_cast(n_size); + auto c_end = reinterpret_cast(c_start + c_size); + + cout << "Node *n:\t" << n << "\n"; + cout << "n_size: \t0x" << std::hex << n_size << "\n"; + cout << "c_start:\t0x" << std::hex << c_start << "\n"; + cout << "c_size: \t0x" << std::hex << c_size << "\n"; + cout << "c_end: \t0x" << std::hex << c_end << endl; +} + +int main() { + GC::Heap::init(); + GC::Heap &heap = GC::Heap::the(); + heap.set_profiler(true); + heap.set_profiler_log_options(GC::FunctionCalls); + + Node *n = static_cast(GC::Heap::alloc(sizeof(Node))); + test(n); + + GC::Heap::dispose(); + return 0; +} \ No newline at end of file diff --git a/src/GC/tests/revrange.cpp b/src/GC/tests/revrange.cpp new file mode 100644 index 0000000..6a11c57 --- /dev/null +++ b/src/GC/tests/revrange.cpp @@ -0,0 +1,43 @@ +#include +#include +#include + +#include "heap.hpp" + +#define allocNode static_cast(GC::Heap::alloc(sizeof(Node))) + +using std::cout, std::endl; + +struct Node { + int value; + Node *next {nullptr}; +}; + +void revRange(int n) { + Node *next = nullptr; + Node *prev = allocNode; + while (n > 0) { + next = allocNode; + prev->next = next; + prev->value = n--; + prev = next; + } +} + +void make_test() { + int n = 10; + while (n > 0) + revRange(1000); +} + +int main() { + GC::Heap::init(); + GC::Heap &heap = GC::Heap::the(); + heap.set_profiler(true); + GC::Profiler::set_log_options(GC::FunctionCalls); + + make_test(); + + GC::Heap::dispose(); + return 0; +} \ No newline at end of file