diff --git a/src/GC/Makefile b/src/GC/Makefile index 6ca9320..b99d2a4 100644 --- a/src/GC/Makefile +++ b/src/GC/Makefile @@ -1,17 +1,23 @@ mkfile_path = $(abspath $(lastword $(MAKEFILE_LIST))) current_dir = $(notdir $(patsubst %/,%,$(dir $(mkfile_path)))) -PWD_V = /Users/valtermiari/Desktop/DV/Bachelors/code/language/src/GC/include -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 +CC = clang++ + +PWD_V = /Users/valtermiari/Desktop/DV/Bachelors/code/language/src/GC/include +LIB_INCL = -I/home/virre/dev/systemF/org/language/src/GC/include +LIB_SO = -L/home/virre/dev/systemF/org/language/src/GC/lib/libheap.so + +CFLAGS = -Wall -Wextra -v -g -std=gnu++20 -stdlib=libc++ -I +VGFLAGS = --leak-check=full --show-leak-kinds=all +STDFLAGS = -std=gnu++20 -stdlib=libc++ +WFLAGS = -Wall -Wextra +DBGFLAGS = -g heap: - $(CC) $(CFLAGS)$(PWD) lib/heap.cpp + $(CC) $(WFLAGS) $(STDFLAGS) $(LIB_INCL) 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 + $(CC) $(WFLAGS) $(STDFLAGS) $(LIB_INCL) tests/h_test.cpp lib/heap.cpp -o tests/h_test.out h_test_vg: make h_test @@ -23,8 +29,15 @@ h_test_dbg: linker: rm -f tests/linker.out - $(CC) $(CFLAGS)$(PWD) tests/linker.cpp lib/heap.cpp -o tests/linker.out + $(CC) $(WFLAGS) $(STDFLAGS) $(LIB_INCL) 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 + valgrind $(VGFLAGS) tests/linker.out + +extern_lib: + rm -f lib/heap.o + rm -f lib/libheap.so + $(CC) $(STDFLAGS) -c -fPIC -o lib/heap.o lib/heap.cpp + $(CC) $(STDFLAGS) -shared -o lib/libheap.so lib/heap.o + $(CC) $(LIB_INCL) $(LIB_SO) -v -Wall -o tests/extern_lib.out tests/extern_lib.cpp \ No newline at end of file diff --git a/src/GC/include/heap.hpp b/src/GC/include/heap.hpp index 0962c9f..d0f805d 100644 --- a/src/GC/include/heap.hpp +++ b/src/GC/include/heap.hpp @@ -29,11 +29,11 @@ namespace GC { m_allocated_size = 0; } - void collect(); - void sweep(); - uintptr_t *try_recycle_chunks(size_t size); - void free(); - void free_overlap(); + void collect(Heap *heap); + void sweep(Heap *heap); + uintptr_t *try_recycle_chunks(Heap *heap, size_t size); + void free(Heap *heap); + void free_overlap(Heap *heap); void mark(uintptr_t *start, const uintptr_t *end, std::vector worklist); void print_line(Chunk *chunk); void print_worklist(std::vector list); @@ -61,9 +61,12 @@ namespace GC { std::free((char *)m_heap); } - void init(); void *alloc(size_t size); + void init(); + + // DEBUG ONLY + void check_init(); + void collect(uint flags); void print_contents(); - 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 d6ac52d..a222833 100644 --- a/src/GC/lib/heap.cpp +++ b/src/GC/lib/heap.cpp @@ -7,7 +7,7 @@ #include #include -#include "heap.hpp" +#include "../include/heap.hpp" using namespace std; namespace GC { @@ -18,6 +18,13 @@ namespace GC { * this address points to the stack frame of the compiled * LLVM executable after linking. (NOT CONFIRMED) */ + void Heap::check_init() { + auto heap = Heap::the(); + cout << "GC m_stack_end:\t" << heap->m_stack_end << endl; + auto stack_start = reinterpret_cast(__builtin_frame_address(0)); + cout << "GC stack_start:\t" << stack_start << endl; + } + void Heap::init() { Heap *heap = Heap::the(); heap->m_stack_end = reinterpret_cast(__builtin_frame_address(1)); @@ -43,13 +50,13 @@ namespace GC { } if (heap->m_size + size > HEAP_SIZE) { - collect(); + collect(heap); // If collect failed, crash with OOM error assert(heap->m_size + size <= HEAP_SIZE && "Heap: Out Of Memory"); } // If a chunk was recycled, return the old chunk address - uintptr_t *reused_chunk = try_recycle_chunks(size); + uintptr_t *reused_chunk = try_recycle_chunks(heap, size); if (reused_chunk != nullptr) { return (void *)reused_chunk; } @@ -58,18 +65,17 @@ namespace GC { // then create a new chunk auto new_chunk = new Chunk; new_chunk->size = size; - new_chunk->start = (uintptr_t *)m_heap + m_size; + new_chunk->start = (uintptr_t *)(heap->m_heap + m_size); - m_size += size; + heap->m_size += size; - m_allocated_chunks.push_back(new_chunk); + heap->m_allocated_chunks.push_back(new_chunk); // new_chunk should probably be a unique pointer, if that isn't implicit already return new_chunk->start; } - uintptr_t *Heap::try_recycle_chunks(size_t size) { - auto heap = Heap::the(); + uintptr_t *Heap::try_recycle_chunks(Heap *heap, size_t size) { // Check if there are any freed chunks large enough for current request for (size_t i = 0; i < heap->m_freed_chunks.size(); i++) { auto cp = heap->m_freed_chunks.at(i); @@ -92,16 +98,16 @@ namespace GC { else if (cp->size == size) { // Reuse the whole chunk - m_freed_chunks.erase(m_freed_chunks.begin() + i); - m_allocated_chunks.push_back(cp); + heap->m_freed_chunks.erase(m_freed_chunks.begin() + i); + heap->m_allocated_chunks.push_back(cp); return cp->start; } } + return nullptr; } - void Heap::collect() { + void Heap::collect(Heap *heap) { // Get the adress of the current stack frame - auto heap = Heap::the(); uintptr_t *stack_end; @@ -111,38 +117,38 @@ namespace GC { else stack_end = (uintptr_t *)0; // temporary - auto work_list = m_allocated_chunks; + auto work_list = heap->m_allocated_chunks; mark(stack_start, stack_end, work_list); - sweep(); + sweep(heap); - free(); + free(heap); } - void Heap::free() { - if (m_freed_chunks.size() > FREE_THRESH) { - while (m_freed_chunks.size()) { - auto chunk = m_freed_chunks.back(); - m_freed_chunks.pop_back(); + void Heap::free(Heap *heap) { + if (heap->m_freed_chunks.size() > FREE_THRESH) { + while (heap->m_freed_chunks.size()) { + auto chunk = heap->m_freed_chunks.back(); + heap->m_freed_chunks.pop_back(); delete chunk; } } else { - free_overlap(); + free_overlap(heap); } } - void Heap::free_overlap() { + void Heap::free_overlap(Heap *heap) { std::vector filtered; size_t i = 0; - filtered.push_back(m_freed_chunks.at(i++)); - for (; i < m_freed_chunks.size(); i++) { + filtered.push_back(heap->m_freed_chunks.at(i++)); + for (; i < heap->m_freed_chunks.size(); i++) { auto prev = filtered.back(); - auto next = m_freed_chunks.at(i); + auto next = heap->m_freed_chunks.at(i); if (next->start > (prev->start + prev->size)) { filtered.push_back(next); } } - m_freed_chunks.swap(filtered); + heap->m_freed_chunks.swap(filtered); } void Heap::collect(uint flags) { @@ -155,16 +161,20 @@ namespace GC { if (flags & FREE) cout << "\n - FREE"; cout << endl; + + auto heap = Heap::the(); + // get the frame adress, whwere local variables and saved registers are located auto stack_start = reinterpret_cast(__builtin_frame_address(0)); cout << "Stack start:\t" << stack_start << endl; + uintptr_t *stack_end; - const uintptr_t *stack_end = (uintptr_t *) stack_start - 40; // dummy value - - // denna segfaultar om arg för __b_f_a är > 2 - // reinterpret_cast(__builtin_frame_address(10)); + if (heap->m_stack_end != nullptr) + stack_end = heap->m_stack_end; + else + stack_end = (uintptr_t *) stack_start - 40; // dummy value - auto work_list = m_allocated_chunks; + auto work_list = heap->m_allocated_chunks; // print_worklist(work_list); if (flags & MARK) { @@ -172,31 +182,22 @@ namespace GC { } if (flags & SWEEP) { - sweep(); + sweep(heap); } if (flags & FREE) { - free(); + free(heap); } - - //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() { - for (auto it = m_allocated_chunks.begin(); it != m_allocated_chunks.end();) { + void Heap::sweep(Heap *heap) { + for (auto it = heap->m_allocated_chunks.begin(); it != heap->m_allocated_chunks.end();) { auto chunk = *it; if (!chunk->marked) { - m_freed_chunks.push_back(chunk); - it = m_allocated_chunks.erase(it); + heap->m_freed_chunks.push_back(chunk); + it = heap->m_allocated_chunks.erase(it); } else { ++it; @@ -240,17 +241,18 @@ namespace GC { } void Heap::print_contents() { - if (m_allocated_chunks.size()) { - cout << "\nALLOCATED CHUNKS #" << m_allocated_chunks.size() << endl; - for (auto chunk : m_allocated_chunks) { + auto heap = Heap::the(); + if (heap->m_allocated_chunks.size()) { + cout << "\nALLOCATED CHUNKS #" << heap->m_allocated_chunks.size() << endl; + for (auto chunk : heap->m_allocated_chunks) { print_line(chunk); } } else { cout << "NO ALLOCATIONS\n" << endl; } - if (m_freed_chunks.size()) { - cout << "\nFREED CHUNKS #" << m_freed_chunks.size() << endl; - for (auto fchunk : m_freed_chunks) { + if (heap->m_freed_chunks.size()) { + cout << "\nFREED CHUNKS #" << heap->m_freed_chunks.size() << endl; + for (auto fchunk : heap->m_freed_chunks) { print_line(fchunk); } } else { diff --git a/src/GC/lib/heap.o b/src/GC/lib/heap.o new file mode 100644 index 0000000..2f2a154 Binary files /dev/null and b/src/GC/lib/heap.o differ diff --git a/src/GC/lib/libheap.so b/src/GC/lib/libheap.so new file mode 100755 index 0000000..83a12f5 Binary files /dev/null and b/src/GC/lib/libheap.so differ diff --git a/src/GC/tests/extern_lib.cpp b/src/GC/tests/extern_lib.cpp new file mode 100644 index 0000000..5f3e0c7 --- /dev/null +++ b/src/GC/tests/extern_lib.cpp @@ -0,0 +1,52 @@ +#include +#include + +#include "heap.hpp" + +// using namespace std; + +// GC::Heap *singleton_test(); +// void init_gc(GC::Heap *heap); +// void frame_test(GC::Heap *heap); + +GC::Heap *singleton_test() { + std::cout << "TESTING SINGLETON INSTANCES" << std::endl; + std::cout << "===========================" << std::endl; + std::cout << "Call 1:\t" << GC::Heap::the() << std::endl; + GC::Heap *heap = GC::Heap::the(); + std::cout << "Call 2:\t" << heap << std::endl; + std::cout << "===========================" << std::endl; + return heap; +} + +void init_gc(GC::Heap *heap){ + std::cout << "\n\n INITIALIZING THE HEAP" << std::endl; + std::cout << "===========================" << std::endl; + heap->init(); + std::cout << "===========================" << std::endl; +} + +void frame_test(GC::Heap *heap) { + std::cout << "\n\n TESTING FRAME ADDRESSES" << std::endl; + std::cout << "===========================" << std::endl; + +#pragma clang diagnostic ignored "-Wframe-address" + auto curr_frame = reinterpret_cast(__builtin_frame_address(0)); + std::cout << "Current stack frame:\t" << curr_frame << std::endl; +#pragma clang diagnostic ignored "-Wframe-address" + auto prev_frame = reinterpret_cast(__builtin_frame_address(1)); + std::cout << "Previous stack frame:\t" << prev_frame << std::endl; + + heap->check_init(); + + std::cout << "===========================" << std::endl; +} + +int main() { + auto heap = singleton_test(); + + init_gc(heap); + frame_test(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 76e2434..774f091 100644 --- a/src/GC/tests/h_test.cpp +++ b/src/GC/tests/h_test.cpp @@ -1,6 +1,6 @@ #include "../include/heap.hpp" -GC::Heap *gc = GC::Heap::the2(); +GC::Heap *gc = GC::Heap::the(); void init() {