Continued debugging

Co-authored-by: ValterMiari <ValterMiari@users.noreply.github.com>
This commit is contained in:
Victor Olin 2023-02-16 16:23:35 +01:00
parent fb1e177130
commit 5157e6b41d
6 changed files with 95 additions and 57 deletions

View file

@ -1,6 +1,9 @@
mkfile_path = $(abspath $(lastword $(MAKEFILE_LIST)))
current_dir = $(notdir $(patsubst %/,%,$(dir $(mkfile_path))))
CC = clang++ CC = clang++
PWD = /home/virre/dev/systemF/org/language/src/GC/include PWD = /home/virre/dev/systemF/org/language/src/GC/include
CFLAGS = -Wall -Wextra -v -g -std=gnu++20 -stdlib=libc++ -I CFLAGS = -Wall -Wextra -v -g -std=gnu++20 -stdlib=libc++ -I
VGFLAGS = --leak-check=full --show-leak-kinds=all
heap: heap:
$(CC) $(CFLAGS)$(PWD) lib/heap.cpp $(CC) $(CFLAGS)$(PWD) lib/heap.cpp
@ -9,6 +12,14 @@ h_test:
rm -f tests/h_test.out rm -f tests/h_test.out
$(CC) $(CFLAGS)$(PWD) 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:
make h_test
valgrind $(VGFLAGS) tests/h_test.out
linker: linker:
rm -f tests/linker.out rm -f tests/linker.out
$(CC) $(CFLAGS)$(PWD) 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:
make linker
valgrind $(VGFLAGS) tests/linker.out

View file

@ -10,6 +10,11 @@
#define HEAP_SIZE 65536 #define HEAP_SIZE 65536
#define MARK (uint) 0x1
#define SWEEP (uint) 0x2
#define FREE (uint) 0x4
#define COLLECT_ALL (uint) 0x7
namespace GC { namespace GC {
class Heap { class Heap {
@ -60,6 +65,6 @@ namespace GC {
void *alloc(size_t size); void *alloc(size_t size);
void print_contents(); void print_contents();
void force_collect(); void collect(uint flags); // DEBUG ONLY
}; };
} }

View file

@ -79,17 +79,47 @@ namespace GC {
// BELOW SHOULD BE INCLUDED (commented only for tests, to see which objects freed) // BELOW SHOULD BE INCLUDED (commented only for tests, to see which objects freed)
//release free chunks //release free chunks
/* while (m_freed_chunks.size()) { while (m_freed_chunks.size()) {
auto chunk_pointer = m_freed_chunks.back(); auto chunk_pointer = m_freed_chunks.back();
m_freed_chunks.pop_back(); m_freed_chunks.pop_back();
delete chunk_pointer; // deletes chunk object, doesn't free memory to the OS delete chunk_pointer; // deletes chunk object, doesn't free memory to the OS
} */ }
}
void Heap::collect(uint flags) {
std::cout << "DEBUG COLLECT\nFLAGS: " << flags << std::endl;
// get the frame adress, whwere local variables and saved registers are located
auto stack_start = reinterpret_cast<uintptr_t *>(__builtin_frame_address(0));
const uintptr_t *stack_end = (uintptr_t *)0; // dummy value
// denna segfaultar om arg för __b_f_a är > 2
// reinterpret_cast<const uintptr_t *>(__builtin_frame_address(10));
auto work_list = m_allocated_chunks;
if (flags & MARK) {
mark(stack_start, stack_end, work_list);
}
if (flags & SWEEP) {
sweep();
}
//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 // Not optimal for now, it doesn't have to loop over all objects
// but mark needs some refinements before this can be optimised // but mark needs some refinements before this can be optimised
void Heap::sweep() { void Heap::sweep() {
// assert(false && "NOT IMPLEMENTED");
for (size_t i = 0; i < m_allocated_chunks.size(); i++) { for (size_t i = 0; i < m_allocated_chunks.size(); i++) {
auto chunk = m_allocated_chunks.at(i); auto chunk = m_allocated_chunks.at(i);
if (chunk->marked == false) { if (chunk->marked == false) {
@ -99,32 +129,7 @@ namespace GC {
} }
} }
void Heap::force_collect() { // TODO: return the worklist filtered on mark = true
Heap::collect();
}
// dead code
// void Heap::compact() {
// // 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 = (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<Chunk*> work_list) { void Heap::mark(uintptr_t *start, const uintptr_t *end, std::vector<Chunk*> work_list) {
for (; start < end; start++) { // to find adresses thats in the worklist for (; start < end; start++) { // to find adresses thats in the worklist
for (size_t i = 0; i < work_list.size(); i++) { // fix this for (size_t i = 0; i < work_list.size(); i++) { // fix this
@ -140,7 +145,27 @@ namespace GC {
} }
} }
} }
/* 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)
*/
// For testing purposes // For testing purposes
void Heap::print_line(Chunk *chunk) { void Heap::print_line(Chunk *chunk) {
std::cout << "Marked: " << chunk->marked << "\nStart adr: " << chunk->start << "\nSize: " << chunk->size << " B" << std::endl; std::cout << "Marked: " << chunk->marked << "\nStart adr: " << chunk->start << "\nSize: " << chunk->size << " B" << std::endl;

View file

@ -4,7 +4,8 @@ GC::Heap *gc = GC::Heap::the2();
void init() { void init() {
std::vector<int> live_int_vec{1, 2, 3, 4, 5}; std::vector<int> live_int_vec{1, 2, 3, 4, 5};
std::vector<int> dead_int_vec(10, 1); std::vector<int> dead_int_vec(1000000, 1);
int *arr = static_cast<int *>(gc->alloc(sizeof(int) * 300));
int *a_ptr; int *a_ptr;
int a = 10; int a = 10;
a_ptr = &a; a_ptr = &a;
@ -16,7 +17,7 @@ void init() {
int main() { int main() {
init(); init();
gc->force_collect(); gc->collect(MARK | SWEEP);
gc->print_contents(); gc->print_contents();
//delete gc; //delete gc;
return 0; return 0;

View file

@ -14,12 +14,18 @@ int main() {
std::cout << "Start:\t\t" << prev1 << std::endl; std::cout << "Start:\t\t" << prev1 << std::endl;
#pragma clang diagnostic ignored "-Wframe-address" #pragma clang diagnostic ignored "-Wframe-address"
uintptr_t *tmp = reinterpret_cast<uintptr_t *>(__builtin_frame_address(1)); uintptr_t *tmp = reinterpret_cast<uintptr_t *>(__builtin_frame_address(1));
std::cout << "Frame 1:\t" << tmp << "\t\tDiff:\t" << std::hex << "0x"<< prev1 - tmp << std::endl; std::cout << "Frame 1:\t" << tmp << "\t\tDiff:\t" << std::hex << "0x"<< tmp - prev1 << std::endl;
prev1 = tmp; prev1 = tmp;
#pragma clang diagnostic ignored "-Wframe-address" #pragma clang diagnostic ignored "-Wframe-address"
tmp = reinterpret_cast<uintptr_t *>(__builtin_frame_address(2)); tmp = reinterpret_cast<uintptr_t *>(__builtin_frame_address(2));
std::cout << "Frame 2:\t" << tmp << "\tDiff:\t" << std::hex << "0x" << prev1 - tmp << std::endl; std::cout << "Frame 2:\t" << tmp << "\tDiff:\t" << std::hex << "0x" << tmp - prev1 << std::endl;
prev1 = tmp;
// arg > 2 for __builtin_frame_address() results in segfault
// #pragma clang diagnostic ignored "-Wframe-address"
// tmp = reinterpret_cast<uintptr_t *>(__builtin_frame_address(3));
// std::cout << "Frame 3:\t" << tmp << "\tDiff:\t" << std::hex << "0x" << prev1 - tmp << std::endl;
dummy1(); dummy1();
@ -27,11 +33,11 @@ int main() {
} }
void dummy1() { void dummy1() {
std::cout << "Frame:\t\t" << __builtin_frame_address(0); std::cout << "D1 SFrame:\t" << __builtin_frame_address(0);
#pragma clang diagnostic ignored "-Wframe-address" #pragma clang diagnostic ignored "-Wframe-address"
std::cout << "\t\tPrev:\t" << __builtin_frame_address(1) << std::endl; std::cout << "\t\tPrev:\t" << __builtin_frame_address(1) << std::endl;
dummy2();
std::cout << "D1 RA:\t\t" << std::hex << __builtin_return_address(0) << std::endl; std::cout << "D1 RA:\t\t" << std::hex << __builtin_return_address(0) << std::endl;
dummy2();
} }
void dummy2() { void dummy2() {
@ -40,5 +46,6 @@ void dummy2() {
std::cout << "\t\tPrev:\t" << __builtin_frame_address(1) << std::endl; std::cout << "\t\tPrev:\t" << __builtin_frame_address(1) << std::endl;
void *ra = __builtin_return_address(0); void *ra = __builtin_return_address(0);
std::cout << "D2 RA:\t\t" << std::hex << ra << std::endl; std::cout << "D2 RA:\t\t" << std::hex << ra << std::endl;
std::cout << "D2 ERA:\t\t" << std::hex << __builtin_extract_return_addr(ra) << std::endl; // gives same value as pure 'ra'
// std::cout << "D2 ERA:\t\t" << std::hex << __builtin_extract_return_addr(ra) << std::endl;
} }

View file

@ -13,25 +13,14 @@ TODO:
Potential algorithms: Potential algorithms:
- mark & sweep - mark & sweep
- easy to implement
- slow
- mark & compact
- no memory fragmentation
- slow
- stop-copy algorithms (?)
- no memory fragmentation
- slow
- maybe good for FP langs?
## Type hierarchy ## Tests TODO
### Library linking
Compile the GC lib and a test separately, link them together
and evalutate the following:
- Heap class __builtin_frame_address(0)
- Holds all memory __builtin_frame_address(1)
- Resizeable array? __builtin_return_address(0)
- Singleton instance __builtin_return_address(1)
- exposes alloc
- Heap chunks
- size
- addr
- marked bit