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
|
||||
|
||||
heap:
|
||||
$(CC) $(CFLAGS)$(PWD_V) lib/heap.cpp
|
||||
$(CC) $(CFLAGS)$(PWD) lib/heap.cpp
|
||||
|
||||
h_test:
|
||||
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:
|
||||
make h_test
|
||||
valgrind $(VGFLAGS) tests/h_test.out
|
||||
|
||||
h_test_dbg:
|
||||
make h_test
|
||||
lldb tests/h_test.out launch
|
||||
|
||||
linker:
|
||||
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:
|
||||
make linker
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ namespace GC {
|
|||
// void compact();
|
||||
void mark(uintptr_t *start, const uintptr_t *end, std::vector<Chunk *> worklist);
|
||||
void print_line(Chunk *chunk);
|
||||
void print_worklist(std::vector<Chunk *> list);
|
||||
|
||||
inline static Heap *m_instance = nullptr;
|
||||
const char *m_heap;
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ namespace GC {
|
|||
}
|
||||
|
||||
// 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++) {
|
||||
auto cp = m_freed_chunks.at(i);
|
||||
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,
|
||||
// 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()) {
|
||||
auto chunk_pointer = m_freed_chunks.back();
|
||||
m_freed_chunks.pop_back();
|
||||
|
|
@ -90,7 +91,14 @@ namespace GC {
|
|||
|
||||
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
|
||||
auto stack_start = reinterpret_cast<uintptr_t *>(__builtin_frame_address(0));
|
||||
cout << "Stack start:\t" << stack_start << endl;
|
||||
|
|
@ -101,6 +109,7 @@ namespace GC {
|
|||
// reinterpret_cast<const uintptr_t *>(__builtin_frame_address(10));
|
||||
|
||||
auto work_list = m_allocated_chunks;
|
||||
// print_worklist(work_list);
|
||||
|
||||
if (flags & MARK) {
|
||||
mark(stack_start, stack_end, work_list);
|
||||
|
|
@ -136,19 +145,23 @@ namespace GC {
|
|||
}
|
||||
|
||||
// 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
|
||||
cout << "Value of start pointer:\t" << start << endl;
|
||||
for (size_t i = 0; i < work_list.size(); i++) { // fix this
|
||||
auto chunk = work_list.at(i);
|
||||
cout << "Chunk value:\t" << chunk->start << endl;
|
||||
cout << "Chunk pointer value:\t" << &chunk << endl;
|
||||
if (chunk->start <= start && start < chunk->start + chunk->size) {
|
||||
if (!chunk->marked) {
|
||||
chunk->marked = true;
|
||||
work_list.erase(work_list.begin() + i);
|
||||
mark(reinterpret_cast<uintptr_t *>(chunk->start + chunk->size), end, work_list); //
|
||||
return;
|
||||
if (*start % 8 == 0) { // all pointers must be aligned as double words
|
||||
for (size_t i = 0; i < worklist.size(); i++) { // fix this
|
||||
auto chunk = worklist.at(i);
|
||||
uintptr_t c_start = reinterpret_cast<uintptr_t>(chunk->start);
|
||||
uintptr_t c_end = reinterpret_cast<uintptr_t>(chunk->start + chunk->size);
|
||||
if (c_start <= *start && *start < c_end) {
|
||||
uintptr_t c_start = reinterpret_cast<uintptr_t>(chunk->start);
|
||||
if (!chunk->marked) {
|
||||
chunk->marked = true;
|
||||
worklist.erase(worklist.begin() + i);
|
||||
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;
|
||||
}
|
||||
|
||||
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() {
|
||||
if (m_allocated_chunks.size()) {
|
||||
cout << "\nALLOCATED CHUNKS #" << m_allocated_chunks.size() << endl;
|
||||
|
|
|
|||
|
|
@ -5,28 +5,26 @@ GC::Heap *gc = GC::Heap::the2();
|
|||
void init() {
|
||||
|
||||
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 << "Imaginary stack end:\t" << stack_end << std::endl;
|
||||
int *arr = static_cast<int *>(gc->alloc(sizeof(int) * 300));
|
||||
for (int i = 0; i < (sizeof(int) * 300); i++) {
|
||||
int *arr = static_cast<int *>(gc->alloc(sizeof(int) * 100));
|
||||
std::cout << "Arr_ptr" << std::hex << arr << "\n\n\n" << std::endl;
|
||||
for (int i = 0; i < (sizeof(int) * 100); i++) {
|
||||
arr[i] = i;
|
||||
}
|
||||
std::cout << "First stack pointer:\t" << &arr << std::endl;
|
||||
long a = 20;
|
||||
long *l = static_cast<long *>(gc->alloc(sizeof(long)));
|
||||
*l = 20;
|
||||
// This doesn't get allocated on our heap, but how is it viewed on valgr?
|
||||
int *arr2 = new int[1000];
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
arr2[i] = i;
|
||||
}
|
||||
l = &a;
|
||||
//*l = 20;
|
||||
}
|
||||
|
||||
int main() {
|
||||
auto stack_start = reinterpret_cast<uintptr_t *>(__builtin_frame_address(0));
|
||||
std::cout << "Stack start from main:\t" << stack_start << std::endl;
|
||||
init();
|
||||
gc->collect(MARK | SWEEP);
|
||||
gc->collect(MARK | SWEEP | FREE);
|
||||
gc->print_contents();
|
||||
//delete gc;
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -6,16 +6,13 @@ Goal for next week (17/2):
|
|||
- Functioning garbage collector
|
||||
- Test it with valgrind
|
||||
|
||||
TODO:
|
||||
## GC TODO:
|
||||
- Merge to main branch
|
||||
|
||||
## Algorithm
|
||||
|
||||
Potential algorithms:
|
||||
- mark & sweep
|
||||
- Don't empty m_free_chunks, reuse in a better way **Victor fixes this**
|
||||
|
||||
## Tests TODO
|
||||
### Library linking
|
||||
**Victor fixes this**
|
||||
Compile the GC lib and a test separately, link them together
|
||||
and evalutate the following:
|
||||
|
||||
|
|
@ -24,3 +21,17 @@ and evalutate the following:
|
|||
__builtin_return_address(0)
|
||||
__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