Debugged mark()

Co-authored-by: ValterMiari <ValterMiari@users.noreply.github.com>
This commit is contained in:
Victor Olin 2023-02-17 12:14:11 +01:00
parent fb5f283dfd
commit b79a83c32a
5 changed files with 66 additions and 33 deletions

View file

@ -7,19 +7,23 @@ CFLAGS = -Wall -Wextra -v -g -std=gnu++20 -stdlib=libc++ -I
VGFLAGS = --leak-check=full --show-leak-kinds=all VGFLAGS = --leak-check=full --show-leak-kinds=all
heap: heap:
$(CC) $(CFLAGS)$(PWD_V) lib/heap.cpp $(CC) $(CFLAGS)$(PWD) lib/heap.cpp
h_test: h_test:
rm -f tests/h_test.out rm -f tests/h_test.out
$(CC) $(CFLAGS)$(PWD_V) tests/h_test.cpp lib/heap.cpp -o tests/h_test.out $(CC) $(CFLAGS)$(PWD) tests/h_test.cpp lib/heap.cpp -o tests/h_test.out
h_test_vg: h_test_vg:
make h_test make h_test
valgrind $(VGFLAGS) tests/h_test.out valgrind $(VGFLAGS) tests/h_test.out
h_test_dbg:
make h_test
lldb tests/h_test.out launch
linker: linker:
rm -f tests/linker.out rm -f tests/linker.out
$(CC) $(CFLAGS)$(PWD_V) tests/linker.cpp lib/heap.cpp -o tests/linker.out $(CC) $(CFLAGS)$(PWD) tests/linker.cpp lib/heap.cpp -o tests/linker.out
linker_vg: linker_vg:
make linker make linker

View file

@ -32,6 +32,7 @@ namespace GC {
// void compact(); // void compact();
void mark(uintptr_t *start, const uintptr_t *end, std::vector<Chunk *> worklist); void mark(uintptr_t *start, const uintptr_t *end, std::vector<Chunk *> worklist);
void print_line(Chunk *chunk); void print_line(Chunk *chunk);
void print_worklist(std::vector<Chunk *> list);
inline static Heap *m_instance = nullptr; inline static Heap *m_instance = nullptr;
const char *m_heap; const char *m_heap;

View file

@ -23,6 +23,7 @@ namespace GC {
} }
// kolla freed chunks innan // kolla freed chunks innan
// denna är helt onödig just nu, freed chunks kommer alltid va tom
for (size_t i = 0; i < m_freed_chunks.size(); i++) { for (size_t i = 0; i < m_freed_chunks.size(); i++) {
auto cp = m_freed_chunks.at(i); auto cp = m_freed_chunks.at(i);
if (cp->size > size) if (cp->size > size)
@ -90,7 +91,14 @@ namespace GC {
void Heap::collect(uint flags) { void Heap::collect(uint flags) {
cout << "DEBUG COLLECT\nFLAGS: " << flags << endl; cout << "DEBUG COLLECT\nFLAGS: ";
if (flags & MARK)
cout << "\n - MARK";
if (flags & SWEEP)
cout << "\n - SWEEP";
if (flags & FREE)
cout << "\n - FREE";
cout << endl;
// get the frame adress, whwere local variables and saved registers are located // get the frame adress, whwere local variables and saved registers are located
auto stack_start = reinterpret_cast<uintptr_t *>(__builtin_frame_address(0)); auto stack_start = reinterpret_cast<uintptr_t *>(__builtin_frame_address(0));
cout << "Stack start:\t" << stack_start << endl; cout << "Stack start:\t" << stack_start << endl;
@ -101,6 +109,7 @@ namespace GC {
// reinterpret_cast<const uintptr_t *>(__builtin_frame_address(10)); // reinterpret_cast<const uintptr_t *>(__builtin_frame_address(10));
auto work_list = m_allocated_chunks; auto work_list = m_allocated_chunks;
// print_worklist(work_list);
if (flags & MARK) { if (flags & MARK) {
mark(stack_start, stack_end, work_list); mark(stack_start, stack_end, work_list);
@ -136,24 +145,28 @@ namespace GC {
} }
// TODO: 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, vector<Chunk*> work_list) { // This assumes that there are no chains of pointers, will be fixed later on
void Heap::mark(uintptr_t *start, const uintptr_t *end, vector<Chunk*> worklist) {
for (; start > end; start--) { // to find adresses thats in the worklist for (; start > end; start--) { // to find adresses thats in the worklist
cout << "Value of start pointer:\t" << start << endl; if (*start % 8 == 0) { // all pointers must be aligned as double words
for (size_t i = 0; i < work_list.size(); i++) { // fix this for (size_t i = 0; i < worklist.size(); i++) { // fix this
auto chunk = work_list.at(i); auto chunk = worklist.at(i);
cout << "Chunk value:\t" << chunk->start << endl; uintptr_t c_start = reinterpret_cast<uintptr_t>(chunk->start);
cout << "Chunk pointer value:\t" << &chunk << endl; uintptr_t c_end = reinterpret_cast<uintptr_t>(chunk->start + chunk->size);
if (chunk->start <= start && start < chunk->start + chunk->size) { if (c_start <= *start && *start < c_end) {
uintptr_t c_start = reinterpret_cast<uintptr_t>(chunk->start);
if (!chunk->marked) { if (!chunk->marked) {
chunk->marked = true; chunk->marked = true;
work_list.erase(work_list.begin() + i); worklist.erase(worklist.begin() + i);
mark(reinterpret_cast<uintptr_t *>(chunk->start + chunk->size), end, work_list); // auto new_stack_start = reinterpret_cast<uintptr_t *>(start);
mark(new_stack_start, end, worklist); //
return; return;
} }
} }
} }
} }
} }
}
/* void mark_test(vector<Chunk *> worklist) { /* void mark_test(vector<Chunk *> worklist) {
while (worklist.size() > 0) { while (worklist.size() > 0) {
@ -204,6 +217,12 @@ namespace GC {
cout << "Marked: " << chunk->marked << "\nStart adr: " << chunk->start << "\nSize: " << chunk->size << " B\n" << endl; cout << "Marked: " << chunk->marked << "\nStart adr: " << chunk->start << "\nSize: " << chunk->size << " B\n" << endl;
} }
void Heap::print_worklist(std::vector<Chunk *> list) {
for (auto cp : list) {
cout << "Chunk at:\t" << cp->start << "\nSize:\t\t" << cp->size << endl;
}
}
void Heap::print_contents() { void Heap::print_contents() {
if (m_allocated_chunks.size()) { if (m_allocated_chunks.size()) {
cout << "\nALLOCATED CHUNKS #" << m_allocated_chunks.size() << endl; cout << "\nALLOCATED CHUNKS #" << m_allocated_chunks.size() << endl;

View file

@ -5,28 +5,26 @@ GC::Heap *gc = GC::Heap::the2();
void init() { void init() {
auto stack_start = reinterpret_cast<uintptr_t *>(__builtin_frame_address(0)); auto stack_start = reinterpret_cast<uintptr_t *>(__builtin_frame_address(0));
auto stack_end = stack_start - 160; auto stack_end = stack_start - 40;
std::cout << "Stack start from init:\t" << stack_start << std::endl; std::cout << "Stack start from init:\t" << stack_start << std::endl;
std::cout << "Imaginary stack end:\t" << stack_end << std::endl; std::cout << "Imaginary stack end:\t" << stack_end << std::endl;
int *arr = static_cast<int *>(gc->alloc(sizeof(int) * 300)); int *arr = static_cast<int *>(gc->alloc(sizeof(int) * 100));
for (int i = 0; i < (sizeof(int) * 300); i++) { std::cout << "Arr_ptr" << std::hex << arr << "\n\n\n" << std::endl;
for (int i = 0; i < (sizeof(int) * 100); i++) {
arr[i] = i; arr[i] = i;
} }
std::cout << "First stack pointer:\t" << &arr << std::endl; std::cout << "First stack pointer:\t" << &arr << std::endl;
long a = 20;
long *l = static_cast<long *>(gc->alloc(sizeof(long))); long *l = static_cast<long *>(gc->alloc(sizeof(long)));
*l = 20; l = &a;
// This doesn't get allocated on our heap, but how is it viewed on valgr? //*l = 20;
int *arr2 = new int[1000];
for (int i = 0; i < 1000; i++) {
arr2[i] = i;
}
} }
int main() { int main() {
auto stack_start = reinterpret_cast<uintptr_t *>(__builtin_frame_address(0)); auto stack_start = reinterpret_cast<uintptr_t *>(__builtin_frame_address(0));
std::cout << "Stack start from main:\t" << stack_start << std::endl; std::cout << "Stack start from main:\t" << stack_start << std::endl;
init(); init();
gc->collect(MARK | SWEEP); gc->collect(MARK | SWEEP | FREE);
gc->print_contents(); gc->print_contents();
//delete gc; //delete gc;
return 0; return 0;

View file

@ -6,16 +6,13 @@ Goal for next week (17/2):
- Functioning garbage collector - Functioning garbage collector
- Test it with valgrind - Test it with valgrind
TODO: ## GC TODO:
- Merge to main branch - Merge to main branch
- Don't empty m_free_chunks, reuse in a better way **Victor fixes this**
## Algorithm
Potential algorithms:
- mark & sweep
## Tests TODO ## Tests TODO
### Library linking ### Library linking
**Victor fixes this**
Compile the GC lib and a test separately, link them together Compile the GC lib and a test separately, link them together
and evalutate the following: and evalutate the following:
@ -24,3 +21,17 @@ and evalutate the following:
__builtin_return_address(0) __builtin_return_address(0)
__builtin_return_address(1) __builtin_return_address(1)
### GC Init and __b_f_a
1. Save the first stack fram globally as the stack start
2. For each call to collect, save the prev stack frame as the stack end
3. Scan through the span
gc_init()
global stack_end = __builtin_frame_address(1)
collect()
global stack_start = __builtin_frame_address(1)
sweep()
for all addr in range(stack_end, stack_start)
mark if chunk