From c05bf766626504d07a5b48e4bed815e56e27f202 Mon Sep 17 00:00:00 2001 From: Victor Olin Date: Wed, 15 Feb 2023 16:57:11 +0100 Subject: [PATCH] Started testing the GC Co-authored-by: ValterMiari --- src/GC/Makefile | 22 +++++++++ src/GC/include/chunk.hpp | 2 +- src/GC/include/heap.hpp | 48 ++++++++++-------- src/GC/{ => lib}/heap.cpp | 99 +++++++++++++++++++++++-------------- src/GC/tests/alloc_free.cpp | 29 +++++++++++ src/GC/tests/h_test.cpp | 23 ++++++--- src/GC/tests/linker.cpp | 30 +++++++++++ 7 files changed, 188 insertions(+), 65 deletions(-) create mode 100644 src/GC/Makefile rename src/GC/{ => lib}/heap.cpp (54%) create mode 100644 src/GC/tests/alloc_free.cpp create mode 100644 src/GC/tests/linker.cpp diff --git a/src/GC/Makefile b/src/GC/Makefile new file mode 100644 index 0000000..64d90d6 --- /dev/null +++ b/src/GC/Makefile @@ -0,0 +1,22 @@ +CC = clang++ +PWD = /home/virre/dev/systemF/org/language/src/GC/include +CFLAGS = -Wall -Wextra -v -std=gnu++20 -stdlib=libc++ -I + +heap: + $(CC) $(CFLAGS)$(PWD) lib/heap.cpp + +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: + rm -f tests/h_test.out + $(CC) $(CFLAGS)$(PWD) -g tests/h_test.cpp lib/heap.cpp -o tests/h_test.out + +linker: + rm -f tests/linker.out + $(CC) $(CFLAGS)$(PWD) tests/linker.cpp lib/heap.cpp -o tests/linker.out + +linker_vg: + rm -f tests/linker.out + $(CC) $(CFLAGS)$(PWD) -g tests/linker.cpp lib/heap.cpp -o tests/linker.out \ No newline at end of file diff --git a/src/GC/include/chunk.hpp b/src/GC/include/chunk.hpp index b0cd33d..7aa4fb7 100644 --- a/src/GC/include/chunk.hpp +++ b/src/GC/include/chunk.hpp @@ -8,7 +8,7 @@ namespace GC { struct Chunk { bool marked; - void *start; + uintptr_t *start; size_t size; }; diff --git a/src/GC/include/heap.hpp b/src/GC/include/heap.hpp index 14737ad..8a9f828 100644 --- a/src/GC/include/heap.hpp +++ b/src/GC/include/heap.hpp @@ -5,7 +5,6 @@ #include #include #include -using namespace std; #include "chunk.hpp" @@ -14,22 +13,6 @@ using namespace std; namespace GC { class Heap { - public: - - // Singleton - static Heap &the() { - if (m_instance) - return *m_instance; - m_instance = new Heap(); - return *m_instance; - } - - ~Heap() { - free((char *)m_heap); - } - - void *alloc(size_t size); - void print_contents(); private: @@ -40,11 +23,11 @@ namespace GC { } void collect(); - void compact(); + void sweep(); + // void compact(); void mark(uintptr_t *start, const uintptr_t *end, std::vector worklist); + void print_line(Chunk *chunk); - bool compareChunks(Chunk *c1, Chunk *c2); - inline static Heap *m_instance = nullptr; const char *m_heap; size_t m_size; @@ -53,5 +36,30 @@ namespace GC { std::vector m_allocated_chunks; std::vector m_freed_chunks; + public: + + // Singleton + static Heap &the() { + if (m_instance) + return *m_instance; + m_instance = new Heap(); + return *m_instance; + } + + static Heap *the2() { + if (m_instance) + return m_instance; + m_instance = new Heap(); + return m_instance; + } + + // BEWARE only for testing, this should be adressed +/* ~Heap() { + free((char *)m_heap); + } */ + + void *alloc(size_t size); + void print_contents(); + void force_collect(); }; } \ No newline at end of file diff --git a/src/GC/heap.cpp b/src/GC/lib/heap.cpp similarity index 54% rename from src/GC/heap.cpp rename to src/GC/lib/heap.cpp index 8fca1b1..8c296b5 100644 --- a/src/GC/heap.cpp +++ b/src/GC/lib/heap.cpp @@ -1,5 +1,3 @@ -#pragma once - #include #include #include @@ -9,7 +7,7 @@ #include #include -#include "include/heap.hpp" +#include "heap.hpp" namespace GC { @@ -53,7 +51,7 @@ namespace GC { // Om inga free chunks finns, skapa ny chunk auto new_chunk = new Chunk; new_chunk->size = size; - new_chunk->start = (void *)m_heap + m_size; + new_chunk->start = (uintptr_t *)m_heap + m_size; m_size += size; @@ -62,47 +60,68 @@ namespace GC { return new_chunk->start; } - bool compareChunks(Chunk *c1, Chunk *c2) { - return c1->start < c2->start; - } - void Heap::collect() { // get the frame adress, whwere local variables and saved registers are located auto stack_start = reinterpret_cast(__builtin_frame_address(0)); // looking at 10 stack frames back - auto stack_end = reinterpret_cast(__builtin_frame_address(10)); + const uintptr_t *stack_end = (uintptr_t *)0; //reinterpret_cast(__builtin_frame_address(10)); auto work_list = m_allocated_chunks; mark(stack_start, stack_end, work_list); - compact(); + sweep(); + // compact(); + + // 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; + delete chunk_pointer; // deletes chunk object, doesn't free 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) { + m_allocated_chunks.erase(m_allocated_chunks.begin() + i); + m_freed_chunks.push_back(chunk); + } } } + + void Heap::force_collect() { + Heap::collect(); + } - void Heap::compact() { + // dead code + // void Heap::compact() { - // sort alloced_chunks by their start-addresses - std::sort(m_allocated_chunks.begin(), m_allocated_chunks.end(), compareChunks); + // // 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 = (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; - } - } - } + // // 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 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 @@ -120,18 +139,26 @@ namespace GC { } // For testing purposes - void print_line(bool marked, void *start, size_t size) { - std::cout << "Marked: " << marked << "\nStart adr: " << start << "\nSize" << size << std::endl; + void Heap::print_line(Chunk *chunk) { + std::cout << "Marked: " << chunk->marked << "\nStart adr: " << chunk->start << "\nSize: " << chunk->size << " B" << std::endl; } void Heap::print_contents() { - std::cout << "ALLOCATED CHUNKS" << std::endl; - for (auto chunk : m_allocated_chunks) { - print_line(chunk->marked, chunk->start, chunk->size); - } - std::cout << "FREED CHUNKS" << std::endl; - for (auto fchunk : m_freed_chunks) { - print_line(fchunk->marked, fchunk->start, fchunk->size); + if (m_allocated_chunks.size()) { + std::cout << "ALLOCATED CHUNKS" << std::endl; + for (auto chunk : m_allocated_chunks) { + print_line(chunk); + } + } else { + std::cout << "NO ALLOCATIONS" << std::endl; } + if (m_freed_chunks.size()) { + std::cout << "FREED CHUNKS" << std::endl; + for (auto fchunk : m_freed_chunks) { + print_line(fchunk); + } + } else { + std::cout << "NO FREED CHUNKS" << std::endl; + } } } \ No newline at end of file diff --git a/src/GC/tests/alloc_free.cpp b/src/GC/tests/alloc_free.cpp new file mode 100644 index 0000000..0e277dc --- /dev/null +++ b/src/GC/tests/alloc_free.cpp @@ -0,0 +1,29 @@ +#include + +#include "heap.hpp" + +struct Obj { + int a; + int b; + int c; +}; + +int main() { + GC::Heap *heap = GC::Heap::the2(); + Obj *obj; + + for (int i = 0; i < 4; i++) { + obj = static_cast(heap->alloc(sizeof(Obj))); + obj->a = i * i + 1; + obj->b = i * i + 2; + obj->c = i * i + 3; + } + + // heap->force_collect(); + + std::cout << obj->a << ", " << obj->b << ", " << obj->c << std::endl; + + //delete heap; + + return 0; +} \ No newline at end of file diff --git a/src/GC/tests/h_test.cpp b/src/GC/tests/h_test.cpp index 914e65c..c88f0fa 100644 --- a/src/GC/tests/h_test.cpp +++ b/src/GC/tests/h_test.cpp @@ -1,16 +1,23 @@ -#include "../include/heap.hpp" +#include "heap.hpp" -GC::Heap gc; +GC::Heap *gc = GC::Heap::the2(); void init() { - gc = GC::Heap::the(); // pointer to the heap - std::vector live_int_vec(100); - std::vector dead_int_vec(100); - gc.alloc(sizeof(live_int_vec)); - gc.alloc(sizeof(dead_int_vec)); + std::vector live_int_vec{1, 2, 3, 4, 5}; + std::vector dead_int_vec(10, 1); + int *a_ptr; + int a = 10; + a_ptr = &a; + auto temp1 = gc->alloc(sizeof(a_ptr)); + auto temp2 = gc->alloc(sizeof(live_int_vec)); + auto temp3 = gc->alloc(sizeof(dead_int_vec)); + a_ptr = nullptr; } int main() { - gc.print_contents(); + init(); + gc->force_collect(); + gc->print_contents(); + //delete gc; return 0; } \ No newline at end of file diff --git a/src/GC/tests/linker.cpp b/src/GC/tests/linker.cpp new file mode 100644 index 0000000..f3b12f0 --- /dev/null +++ b/src/GC/tests/linker.cpp @@ -0,0 +1,30 @@ +#include + +#include "heap.hpp" + +struct Obj { + int a; + int b; + int c; +}; + +int main() { + auto heap = GC::Heap::the2(); + + std::cout << "heap:\t" << heap << std::endl; + + auto obj = static_cast(heap->alloc(sizeof(Obj))); + + std::cout << "obj: \t" << obj << std::endl; + + obj->a = 3; + obj->b = 4; + obj->c = 5; + + std::cout << obj->a << ", " << obj->b << ", " << obj->c << std::endl; + + heap->print_contents(); + //delete heap; + + return 0; +} \ No newline at end of file