diff --git a/src/GC/docs/heap.md b/src/GC/docs/heap.md deleted file mode 100644 index 5db98e6..0000000 --- a/src/GC/docs/heap.md +++ /dev/null @@ -1,47 +0,0 @@ -## Heap Documentation - -### Algorithm notes - - void mark_test(vector worklist) { - while (worklist.size() > 0) { - Chunk *ref = worklist.pop_back(); - Chunk *child = (Chunk*) *ref; - if (child != NULL && !child->marked) { - child->marked = true; - worklist.push_back(child); - mark_test(worklist); - } - } - } - - void mark_from_roots(uintptr_t *start, const uintptr_t *end) { - vector worklist; - for (;start > end; start--) { - Chunk *ref = *start; - if (ref != NULL && !ref->marked) { - ref->marked = true; - worklist.push_back(ref); - mark_test(worklist); - } - } - } - -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) \ No newline at end of file diff --git a/src/GC/docs/ref-guide.md b/src/GC/docs/ref-guide.md new file mode 100644 index 0000000..7ee627e --- /dev/null +++ b/src/GC/docs/ref-guide.md @@ -0,0 +1,83 @@ +# GC library - reference guide + +The Heap class is the core of the library and contains all necessary +functions for using the library. This class exposes four public functions +which are `init`, `dispose`, `alloc`, and `set_profiler`. + +To use the library, simply include it as `#include "heap.hpp"` and link +it during compilation. Or you can compile it to a static library using +the target `make static_lib` which compiles everything to an .a file. +It can also be compiled to a shared library if necessary with the target +`make shared_lib` which produces an .so file. + +## Quick guide +1. If you want a profiler, call `Heap::set_profiler(true)`. Otherwise this can be skipped. +2. Call `Heap::init()` to initialize the heap before using `alloc` (**crucial**). +3. Use `Heap::alloc()` as you want. +4. At program exit, call `Heap::dispose()` to free up all the memory used. + +## Functions + +### Heap::init() +When using the library, the user has to, at the start of the program, +call the `void init()` function, which initiates the Heap singleton +and the class member `m_stack_top`. **It is crucial** that this +functions is called from the `main` function of the end program, +as `init` uses the intrinsic function `__builtin_frame_address` +to find the address of the **first** stack frame of the end program. +If the function **is not** called from the `main` function +of the end program, it is not guaranteed that the garbage collector +will collect all objects. + +The intrinsic function used is technically unsafe for this use, +but during testing it has only shown to segfault for values greater +than the one used in `init`. If you run into a segfault, please +contact the developers. + + +### Heap::set_profiler(bool mode) +This function is used to enable or disable the profiler connected +to the Heap. The profiler is primarily used for testing, but can +also be used in general to keep track of the programs history. + +This function takes a single boolean as an argument to represent +the state of the profiler. `true` means that the profiler is enabled +and `false` means that the profiler is disabled. This function +can theoretically be called at any time during program execution, +but it's probably a bad idea. It is recommended to call this function +before the call to `init` or at least at before the first call to +`alloc`. + +### Heap::alloc(size_t size) +The probably most important function in this library. This function +is called to request memory from the "heap". `alloc` takes a single +argument which is a `size_t` (unsigned long) to represent the amount +of bytes to allocate on the heap. The allocation is C-style, meaning +that alloc returns a `void` pointer similar to `malloc`, which +is then supposed to be cast by the user to a proper pointer. When +`alloc` is called and there is already not enough memory left on +the heap to accommodate the request, a collection is triggered +to free up memory for the allocation. Hence the user does not +need to make their own calls to `free` or manually free up memory. + +`alloc` can also return a null pointer, if the user requests to +allocate 0 bytes. This is not recommended. + +`alloc` can also throw runtime errors in two cases. The first one +is of there is not enough memory on the heap available after +a collection, which in case the allocation cannot complete. +The second case is during a collection, where the function +`collect` throws a runtime error if the heap is not already +initialized by a call to `init`. Calls to `alloc` can technically +take place without properly initializing the heap, but this is +not recommended. + +### Heap::dispose() +This function is used to dispose the heap at the program exit. +If the profiler is enabled, it is also disposed from a call +to `dispose`. When the profiler is disposed, a log file is +dumped containing the events on the heap. If the profiler +is disabled, nothing happens to the profiler during `dispose`. +After the profiler is disposed, the heap is deleted which +frees up all the memory used and deletes (hopefully) all +the remaining objects in memory. \ No newline at end of file diff --git a/src/GC/include/heap.hpp b/src/GC/include/heap.hpp index 08b3e78..0cc7f73 100644 --- a/src/GC/include/heap.hpp +++ b/src/GC/include/heap.hpp @@ -123,6 +123,7 @@ namespace GC static void init(); static void dispose(); static void *alloc(size_t size); + void set_profiler(bool mode); #ifdef DEBUG static Heap *debug_the() @@ -136,7 +137,6 @@ namespace GC void check_init(); // print dummy things void print_contents(); // print dummy things void print_allocated_chunks(Heap *heap); // print the contents in m_allocated_chunks - void set_profiler(bool mode); #endif }; } \ No newline at end of file diff --git a/src/GC/lib/heap.cpp b/src/GC/lib/heap.cpp index 8c511a7..917a8d6 100644 --- a/src/GC/lib/heap.cpp +++ b/src/GC/lib/heap.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -70,7 +71,7 @@ namespace GC { heap->collect(); // If memory is not enough after collect, crash with OOM error - assert(heap->m_size + size <= HEAP_SIZE && "Heap: Out Of Memory"); + throw std::runtime_error(std::string("Error: Heap out of memory")); } // If a chunk was recycled, return the old chunk address @@ -164,7 +165,7 @@ namespace GC auto stack_bottom = reinterpret_cast(__builtin_frame_address(0)); if (heap->m_stack_top == nullptr) - assert(false && "Heap is not initialized, read the docs!"); + throw std::runtime_error(std::string("Error: Heap is not initialized, read the docs!")); uintptr_t *stack_top = heap->m_stack_top; diff --git a/src/GC/todo.md b/src/GC/todo.md index 34c63e9..dae634a 100644 --- a/src/GC/todo.md +++ b/src/GC/todo.md @@ -4,11 +4,11 @@ Deliver to samuel ## GC TODO: -- Code cleanup - Dokumentera - Dokumentera alla filer och funktioner - Skriva reference guide för Samuel - PR till master ## Tests TODO -- Write complex datastructures for tests with larger programs \ No newline at end of file +- Write complex datastructures for tests with larger programs +- Testa `__builtin_frame_address` mer specifikt för att se om första stack framen skannas \ No newline at end of file