Continued debugging
Co-authored-by: ValterMiari <ValterMiari@users.noreply.github.com>
This commit is contained in:
parent
5ac9b665a1
commit
42c22bc1eb
6 changed files with 95 additions and 57 deletions
|
|
@ -1,6 +1,9 @@
|
|||
mkfile_path = $(abspath $(lastword $(MAKEFILE_LIST)))
|
||||
current_dir = $(notdir $(patsubst %/,%,$(dir $(mkfile_path))))
|
||||
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
|
||||
|
||||
heap:
|
||||
$(CC) $(CFLAGS)$(PWD) lib/heap.cpp
|
||||
|
|
@ -9,6 +12,14 @@ h_test:
|
|||
rm -f 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:
|
||||
rm -f 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
|
||||
|
|
@ -10,6 +10,11 @@
|
|||
|
||||
#define HEAP_SIZE 65536
|
||||
|
||||
#define MARK (uint) 0x1
|
||||
#define SWEEP (uint) 0x2
|
||||
#define FREE (uint) 0x4
|
||||
#define COLLECT_ALL (uint) 0x7
|
||||
|
||||
namespace GC {
|
||||
|
||||
class Heap {
|
||||
|
|
@ -60,6 +65,6 @@ namespace GC {
|
|||
|
||||
void *alloc(size_t size);
|
||||
void print_contents();
|
||||
void force_collect();
|
||||
void collect(uint flags); // DEBUG ONLY
|
||||
};
|
||||
}
|
||||
|
|
@ -79,17 +79,47 @@ namespace GC {
|
|||
// BELOW SHOULD BE INCLUDED (commented only for tests, to see which objects freed)
|
||||
|
||||
//release free chunks
|
||||
/* while (m_freed_chunks.size()) {
|
||||
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 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
|
||||
// but mark needs some refinements before this can be optimised
|
||||
void Heap::sweep() {
|
||||
// assert(false && "NOT IMPLEMENTED");
|
||||
for (size_t i = 0; i < m_allocated_chunks.size(); i++) {
|
||||
auto chunk = m_allocated_chunks.at(i);
|
||||
if (chunk->marked == false) {
|
||||
|
|
@ -99,32 +129,7 @@ namespace GC {
|
|||
}
|
||||
}
|
||||
|
||||
void Heap::force_collect() {
|
||||
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
|
||||
// TODO: return the worklist filtered on mark = true
|
||||
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 (size_t i = 0; i < work_list.size(); i++) { // fix this
|
||||
|
|
@ -141,6 +146,26 @@ 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
|
||||
void Heap::print_line(Chunk *chunk) {
|
||||
std::cout << "Marked: " << chunk->marked << "\nStart adr: " << chunk->start << "\nSize: " << chunk->size << " B" << std::endl;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ GC::Heap *gc = GC::Heap::the2();
|
|||
|
||||
void init() {
|
||||
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 = 10;
|
||||
a_ptr = &a;
|
||||
|
|
@ -16,7 +17,7 @@ void init() {
|
|||
|
||||
int main() {
|
||||
init();
|
||||
gc->force_collect();
|
||||
gc->collect(MARK | SWEEP);
|
||||
gc->print_contents();
|
||||
//delete gc;
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -14,12 +14,18 @@ int main() {
|
|||
std::cout << "Start:\t\t" << prev1 << std::endl;
|
||||
#pragma clang diagnostic ignored "-Wframe-address"
|
||||
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;
|
||||
|
||||
#pragma clang diagnostic ignored "-Wframe-address"
|
||||
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();
|
||||
|
||||
|
|
@ -27,11 +33,11 @@ int main() {
|
|||
}
|
||||
|
||||
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"
|
||||
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;
|
||||
dummy2();
|
||||
}
|
||||
|
||||
void dummy2() {
|
||||
|
|
@ -40,5 +46,6 @@ void dummy2() {
|
|||
std::cout << "\t\tPrev:\t" << __builtin_frame_address(1) << std::endl;
|
||||
void *ra = __builtin_return_address(0);
|
||||
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;
|
||||
}
|
||||
|
|
@ -13,25 +13,14 @@ TODO:
|
|||
|
||||
Potential algorithms:
|
||||
- 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
|
||||
- Holds all memory
|
||||
- Resizeable array?
|
||||
- Singleton instance
|
||||
- exposes alloc
|
||||
__builtin_frame_address(0)
|
||||
__builtin_frame_address(1)
|
||||
__builtin_return_address(0)
|
||||
__builtin_return_address(1)
|
||||
|
||||
- Heap chunks
|
||||
- size
|
||||
- addr
|
||||
- marked bit
|
||||
Loading…
Add table
Add a link
Reference in a new issue