Merge branch 'g-collection' of https://github.com/bachelor-group-66-systemf/language into g-collection
This commit is contained in:
commit
f9932ce527
5 changed files with 89 additions and 52 deletions
|
|
@ -1,47 +0,0 @@
|
|||
## Heap Documentation
|
||||
|
||||
### Algorithm notes
|
||||
|
||||
void mark_test(vector<Chunk *> 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<Chunk *> 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)
|
||||
83
src/GC/docs/ref-guide.md
Normal file
83
src/GC/docs/ref-guide.md
Normal file
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
};
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
#include <execinfo.h>
|
||||
#include <iostream>
|
||||
#include <setjmp.h>
|
||||
#include <stdexcept>
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -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<uintptr_t *>(__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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
- Write complex datastructures for tests with larger programs
|
||||
- Testa `__builtin_frame_address` mer specifikt för att se om första stack framen skannas
|
||||
Loading…
Add table
Add a link
Reference in a new issue