From 42c22bc1ebbdf6544c66b6beda85abd996461f6d Mon Sep 17 00:00:00 2001 From: Victor Olin Date: Thu, 16 Feb 2023 16:23:35 +0100 Subject: [PATCH] Continued debugging Co-authored-by: ValterMiari --- src/GC/Makefile | 13 ++++++- src/GC/include/heap.hpp | 7 +++- src/GC/lib/heap.cpp | 83 +++++++++++++++++++++++++++-------------- src/GC/tests/h_test.cpp | 5 ++- src/GC/tests/stack2.cpp | 17 ++++++--- src/GC/todo.md | 27 ++++---------- 6 files changed, 95 insertions(+), 57 deletions(-) diff --git a/src/GC/Makefile b/src/GC/Makefile index 7c0c38f..3d57536 100644 --- a/src/GC/Makefile +++ b/src/GC/Makefile @@ -1,6 +1,9 @@ +mkfile_path = $(abspath $(lastword $(MAKEFILE_LIST))) +current_dir = $(notdir $(patsubst %/,%,$(dir $(mkfile_path)))) CC = clang++ PWD = /home/virre/dev/systemF/org/language/src/GC/include CFLAGS = -Wall -Wextra -v -g -std=gnu++20 -stdlib=libc++ -I +VGFLAGS = --leak-check=full --show-leak-kinds=all heap: $(CC) $(CFLAGS)$(PWD) lib/heap.cpp @@ -9,6 +12,14 @@ h_test: rm -f tests/h_test.out $(CC) $(CFLAGS)$(PWD) tests/h_test.cpp lib/heap.cpp -o tests/h_test.out +h_test_vg: + make h_test + valgrind $(VGFLAGS) tests/h_test.out + linker: rm -f tests/linker.out - $(CC) $(CFLAGS)$(PWD) tests/linker.cpp lib/heap.cpp -o tests/linker.out \ No newline at end of file + $(CC) $(CFLAGS)$(PWD) tests/linker.cpp lib/heap.cpp -o tests/linker.out + +linker_vg: + make linker + valgrind $(VGFLAGS) tests/linker.out \ No newline at end of file diff --git a/src/GC/include/heap.hpp b/src/GC/include/heap.hpp index 8a9f828..e659598 100644 --- a/src/GC/include/heap.hpp +++ b/src/GC/include/heap.hpp @@ -10,6 +10,11 @@ #define HEAP_SIZE 65536 +#define MARK (uint) 0x1 +#define SWEEP (uint) 0x2 +#define FREE (uint) 0x4 +#define COLLECT_ALL (uint) 0x7 + namespace GC { class Heap { @@ -60,6 +65,6 @@ namespace GC { void *alloc(size_t size); void print_contents(); - void force_collect(); + void collect(uint flags); // DEBUG ONLY }; } \ No newline at end of file diff --git a/src/GC/lib/heap.cpp b/src/GC/lib/heap.cpp index 59f4e7d..c41c924 100644 --- a/src/GC/lib/heap.cpp +++ b/src/GC/lib/heap.cpp @@ -79,17 +79,47 @@ namespace GC { // BELOW SHOULD BE INCLUDED (commented only for tests, to see which objects freed) //release free chunks - /* while (m_freed_chunks.size()) { + while (m_freed_chunks.size()) { auto chunk_pointer = m_freed_chunks.back(); m_freed_chunks.pop_back(); delete chunk_pointer; // deletes chunk object, doesn't free memory to the OS - } */ + } + } + + void Heap::collect(uint flags) { + + std::cout << "DEBUG COLLECT\nFLAGS: " << flags << std::endl; + // get the frame adress, whwere local variables and saved registers are located + auto stack_start = reinterpret_cast(__builtin_frame_address(0)); + + const uintptr_t *stack_end = (uintptr_t *)0; // dummy value + + // denna segfaultar om arg för __b_f_a är > 2 + // reinterpret_cast(__builtin_frame_address(10)); + + auto work_list = m_allocated_chunks; + + if (flags & MARK) { + mark(stack_start, stack_end, work_list); + } + + if (flags & SWEEP) { + sweep(); + } + + //release free chunks + if (flags & FREE) { + while (m_freed_chunks.size()) { + auto chunk_pointer = m_freed_chunks.back(); + m_freed_chunks.pop_back(); + delete chunk_pointer; // deletes chunk object, doesn't free heap memory to the OS + } + } } // Not optimal for now, it doesn't have to loop over all objects // but mark needs some refinements before this can be optimised void Heap::sweep() { - // assert(false && "NOT IMPLEMENTED"); for (size_t i = 0; i < m_allocated_chunks.size(); i++) { auto chunk = m_allocated_chunks.at(i); if (chunk->marked == false) { @@ -99,32 +129,7 @@ namespace GC { } } - void Heap::force_collect() { - Heap::collect(); - } - - // dead code - // void Heap::compact() { - - // // sort alloced_chunks by their start-addresses - // std::sort(m_allocated_chunks.begin(), m_allocated_chunks.end(), [](Chunk *c1, Chunk *c2){ - // return c1->start < c2->start; - // }); - - // // move all chunks to the start of the heap - // auto heap_curr = (uintptr_t *)m_heap; // (char *)m_heap - // for (auto space : m_allocated_chunks) { - // if (space->start != heap_curr) { - // memmove(heap_curr, space->start, space->size); - // space->start = heap_curr; - // heap_curr += space->size; - // } else { - // heap_curr += space->size; - // } - // } - // } - - // return the worklist filtered on mark = true + // TODO: return the worklist filtered on mark = true void Heap::mark(uintptr_t *start, const uintptr_t *end, std::vector work_list) { for (; start < end; start++) { // to find adresses thats in the worklist for (size_t i = 0; i < work_list.size(); i++) { // fix this @@ -140,7 +145,27 @@ namespace GC { } } } + + /* Alternative marking, pseudocode + mark_from_roots(): + worklist <- empty + for fld in Roots + ref <- *fld + if ref ≠ null && !marked(ref) + set_marked(ref) + worklist.add(ref) + mark() + + mark(): + while size(worklist) > 0 + ref <- remove_first(worklist) + for fld in Pointers(ref) + child <- *fld + if child ≠ null && !marked(child) + set_marked(child) + worklist.add(child) + */ // For testing purposes void Heap::print_line(Chunk *chunk) { std::cout << "Marked: " << chunk->marked << "\nStart adr: " << chunk->start << "\nSize: " << chunk->size << " B" << std::endl; diff --git a/src/GC/tests/h_test.cpp b/src/GC/tests/h_test.cpp index c88f0fa..f785077 100644 --- a/src/GC/tests/h_test.cpp +++ b/src/GC/tests/h_test.cpp @@ -4,7 +4,8 @@ GC::Heap *gc = GC::Heap::the2(); void init() { std::vector live_int_vec{1, 2, 3, 4, 5}; - std::vector dead_int_vec(10, 1); + std::vector dead_int_vec(1000000, 1); + int *arr = static_cast(gc->alloc(sizeof(int) * 300)); int *a_ptr; int a = 10; a_ptr = &a; @@ -16,7 +17,7 @@ void init() { int main() { init(); - gc->force_collect(); + gc->collect(MARK | SWEEP); gc->print_contents(); //delete gc; return 0; diff --git a/src/GC/tests/stack2.cpp b/src/GC/tests/stack2.cpp index 0444e10..f1a78bc 100644 --- a/src/GC/tests/stack2.cpp +++ b/src/GC/tests/stack2.cpp @@ -14,12 +14,18 @@ int main() { std::cout << "Start:\t\t" << prev1 << std::endl; #pragma clang diagnostic ignored "-Wframe-address" uintptr_t *tmp = reinterpret_cast(__builtin_frame_address(1)); - std::cout << "Frame 1:\t" << tmp << "\t\tDiff:\t" << std::hex << "0x"<< prev1 - tmp << std::endl; + std::cout << "Frame 1:\t" << tmp << "\t\tDiff:\t" << std::hex << "0x"<< tmp - prev1 << std::endl; prev1 = tmp; #pragma clang diagnostic ignored "-Wframe-address" tmp = reinterpret_cast(__builtin_frame_address(2)); - std::cout << "Frame 2:\t" << tmp << "\tDiff:\t" << std::hex << "0x" << prev1 - tmp << std::endl; + std::cout << "Frame 2:\t" << tmp << "\tDiff:\t" << std::hex << "0x" << tmp - prev1 << std::endl; + prev1 = tmp; + +// arg > 2 for __builtin_frame_address() results in segfault +// #pragma clang diagnostic ignored "-Wframe-address" +// tmp = reinterpret_cast(__builtin_frame_address(3)); +// std::cout << "Frame 3:\t" << tmp << "\tDiff:\t" << std::hex << "0x" << prev1 - tmp << std::endl; dummy1(); @@ -27,11 +33,11 @@ int main() { } void dummy1() { - std::cout << "Frame:\t\t" << __builtin_frame_address(0); + std::cout << "D1 SFrame:\t" << __builtin_frame_address(0); #pragma clang diagnostic ignored "-Wframe-address" std::cout << "\t\tPrev:\t" << __builtin_frame_address(1) << std::endl; - dummy2(); std::cout << "D1 RA:\t\t" << std::hex << __builtin_return_address(0) << std::endl; + dummy2(); } void dummy2() { @@ -40,5 +46,6 @@ void dummy2() { std::cout << "\t\tPrev:\t" << __builtin_frame_address(1) << std::endl; void *ra = __builtin_return_address(0); std::cout << "D2 RA:\t\t" << std::hex << ra << std::endl; - std::cout << "D2 ERA:\t\t" << std::hex << __builtin_extract_return_addr(ra) << std::endl; + // gives same value as pure 'ra' + // std::cout << "D2 ERA:\t\t" << std::hex << __builtin_extract_return_addr(ra) << std::endl; } \ No newline at end of file diff --git a/src/GC/todo.md b/src/GC/todo.md index 5e5f0b9..939c6a0 100644 --- a/src/GC/todo.md +++ b/src/GC/todo.md @@ -13,25 +13,14 @@ TODO: Potential algorithms: - mark & sweep - - easy to implement - - slow -- mark & compact - - no memory fragmentation - - slow -- stop-copy algorithms (?) - - no memory fragmentation - - slow - - maybe good for FP langs? -## Type hierarchy +## Tests TODO +### Library linking +Compile the GC lib and a test separately, link them together +and evalutate the following: -- Heap class - - Holds all memory - - Resizeable array? - - Singleton instance - - exposes alloc + __builtin_frame_address(0) + __builtin_frame_address(1) + __builtin_return_address(0) + __builtin_return_address(1) -- Heap chunks - - size - - addr - - marked bit \ No newline at end of file