Debugged mark()
Co-authored-by: ValterMiari <ValterMiari@users.noreply.github.com>
This commit is contained in:
parent
d40350a263
commit
5f6a18a2ab
5 changed files with 66 additions and 33 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
@ -80,7 +81,7 @@ namespace GC {
|
||||||
|
|
||||||
// We shouldn't do this, since then m_freed_chunks doesnt' have any real purpose,
|
// We shouldn't do this, since then m_freed_chunks doesnt' have any real purpose,
|
||||||
// it should be used in alloc, it isn't if we delete *all* of its contentes
|
// it should be used in alloc, it isn't if we delete *all* of its contentes
|
||||||
//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();
|
||||||
|
|
@ -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,19 +145,23 @@ 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) {
|
||||||
if (!chunk->marked) {
|
uintptr_t c_start = reinterpret_cast<uintptr_t>(chunk->start);
|
||||||
chunk->marked = true;
|
if (!chunk->marked) {
|
||||||
work_list.erase(work_list.begin() + i);
|
chunk->marked = true;
|
||||||
mark(reinterpret_cast<uintptr_t *>(chunk->start + chunk->size), end, work_list); //
|
worklist.erase(worklist.begin() + i);
|
||||||
return;
|
auto new_stack_start = reinterpret_cast<uintptr_t *>(start);
|
||||||
|
mark(new_stack_start, end, worklist); //
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue