Co-authored-by: ValterMiari <ValterMiari@users.noreply.github.com>
This commit is contained in:
Victor Olin 2023-05-04 18:18:25 +02:00
parent ec3aa3cd60
commit 3e188553d6
7 changed files with 252 additions and 19 deletions

View file

@ -66,9 +66,9 @@ static_lib:
# remove old files
rm -f lib/event.o lib/profiler.o lib/heap.o lib/gcoll.a tests/extern_lib.out
# compile object files
$(CC) $(STDFLAGS) $(WFLAGS) $(LIB_INCL) -O3 -c -o lib/event.o lib/event.cpp -fPIC
$(CC) $(STDFLAGS) $(WFLAGS) $(LIB_INCL) -O3 -c -o lib/profiler.o lib/profiler.cpp -fPIC
$(CC) $(STDFLAGS) $(WFLAGS) $(LIB_INCL) -O3 -c -o lib/heap.o lib/heap.cpp -fPIC
$(CC) $(STDFLAGS) $(WFLAGS) $(LIB_INCL) -c -o lib/event.o lib/event.cpp -fPIC
$(CC) $(STDFLAGS) $(WFLAGS) $(LIB_INCL) -c -o lib/profiler.o lib/profiler.cpp -fPIC
$(CC) $(STDFLAGS) $(WFLAGS) $(LIB_INCL) -c -o lib/heap.o lib/heap.cpp -fPIC
# create static library
ar r lib/gcoll.a lib/event.o lib/profiler.o lib/heap.o
@ -103,7 +103,16 @@ alloc_free_list: static_lib
linked_list_test: static_lib
$(CC) $(STDFLAGS) $(WFLAGS) $(LIB_INCL) -o tests/linkedlist.out tests/linkedlist.cpp lib/gcoll.a
<<<<<<< HEAD
>>>>>>> d7ea27e (testing testing...)
=======
revrange: static_lib
$(CC) $(STDFLAGS) $(WFLAGS) $(LIB_INCL) -o tests/revrange.out tests/revrange.cpp lib/gcoll.a
pointers: static_lib
$(CC) $(STDFLAGS) $(WFLAGS) $(LIB_INCL) -o tests/pointers.out tests/pointers.cpp lib/gcoll.a
>>>>>>> a910d54 (rip gc)
wrapper:
# remove old files
rm -f lib/event.o lib/profiler.o lib/heap.o lib/coll.a tests/wrapper.out

View file

@ -7,9 +7,9 @@
#include "chunk.hpp"
#include "profiler.hpp"
#define HEAP_SIZE 65536
#define FREE_THRESH (uint) 100
#define HEAP_DEBUG
#define HEAP_SIZE 320//65536
#define FREE_THRESH (uint) 0
// #define HEAP_DEBUG
namespace GC
{
@ -25,6 +25,13 @@ namespace GC
COLLECT_ALL = 0b1111 // all flags above
};
struct AddrRange
{
const uintptr_t *start, *end;
AddrRange(uintptr_t *_start, uintptr_t *_end) : start(_start), end(_end) {}
};
/**
* The heap class to represent the heap for the
* garbage collection. The heap is a singleton
@ -65,6 +72,7 @@ namespace GC
void print_line(Chunk *chunk);
void print_worklist(std::vector<Chunk *> &list);
void mark_step(uintptr_t start, uintptr_t end, std::vector<Chunk *> &worklist);
void mark_range(std::vector<AddrRange *> &ranges, std::vector<Chunk *> &worklist);
// Temporary
Chunk *try_recycle_chunks_new(size_t size);

View file

@ -14,7 +14,7 @@ namespace GC {
enum RecordOption
{
FunctionCalls = (GC::AllocStart | GC::CollectStart | GC::MarkStart | GC::SweepStart),
FunctionCalls = (GC::AllocStart | GC::CollectStart | GC::MarkStart | GC::SweepStart | GC::FreeStart),
ChunkOps = (GC::ChunkMarked | GC::ChunkSwept | GC::ChunkFreed | GC::NewChunk | GC::ReusedChunk),
AllOps = 0xFFFFFF
};

View file

@ -207,7 +207,7 @@ namespace GC
Profiler::record(CollectStart);
// get current stack frame
auto stack_bottom = reinterpret_cast<uintptr_t *>(__builtin_frame_address(0));
auto stack_bottom = reinterpret_cast<uintptr_t *>(__builtin_frame_address(2));
if (heap.m_stack_top == nullptr)
throw std::runtime_error(std::string("Error: Heap is not initialized, read the docs!"));
@ -244,11 +244,14 @@ namespace GC
*/
void Heap::mark(uintptr_t *start, const uintptr_t* const end, vector<Chunk *> &worklist)
{
// cout << "\nWorklist size: " << worklist.size() << "\n";
Heap &heap = Heap::the();
bool profiler_enabled = heap.m_profiler_enable;
if (profiler_enabled)
Profiler::record(MarkStart);
vector<AddrRange *> rangeWL;
// To find adresses thats in the worklist
for (; start <= end; start++)
{
@ -258,8 +261,8 @@ namespace GC
{
Chunk *chunk = *it;
auto c_start = reinterpret_cast<uintptr_t>(chunk->m_start);
auto c_size = reinterpret_cast<uintptr_t>(chunk->m_size);
auto c_end = reinterpret_cast<uintptr_t>(c_start + c_size);
auto c_size = reinterpret_cast<uintptr_t>(chunk->m_size);
auto c_end = reinterpret_cast<uintptr_t>(c_start + c_size);
// Check if the stack pointer points to something within the chunk
if (c_start <= *start && *start < c_end)
@ -271,8 +274,22 @@ namespace GC
chunk->m_marked = true;
it = worklist.erase(it);
Chunk *next = find_pointer((uintptr_t *) c_start, (uintptr_t *) c_end, worklist);
while (next != NULL) {
if (!next->m_marked)
{
next->m_marked = true;
auto c_start = reinterpret_cast<uintptr_t>(next->m_start);
auto c_size = reinterpret_cast<uintptr_t>(next->m_size);
auto c_end = reinterpret_cast<uintptr_t>(c_start + c_size);
next = find_pointer((uintptr_t *) c_start, (uintptr_t *) c_end, worklist);
}
}
// Recursively call mark, to see if the reachable chunk further points to another chunk
mark((uintptr_t *)c_start, (uintptr_t *)c_end, worklist);
// mark((uintptr_t *)c_start, (uintptr_t *)c_end, worklist);
// AddrRange *range = new AddrRange((uintptr_t *)c_start, (uintptr_t *)c_end);
rangeWL.push_back(new AddrRange((uintptr_t *)c_start, (uintptr_t *)c_end));
}
else
{
@ -285,8 +302,60 @@ namespace GC
}
}
}
mark_range(rangeWL, worklist);
rangeWL.clear();
}
void Heap::mark_range(vector<AddrRange *> &ranges, vector<Chunk *> &worklist)
{
Heap &heap = Heap::the();
bool profiler_enabled = heap.m_profiler_enable;
if (profiler_enabled)
Profiler::record(MarkStart);
auto iter = ranges.begin();
auto stop = ranges.end();
while (iter != stop)
{
auto range = *iter++;
uintptr_t *start = (uintptr_t *)range->start;
const uintptr_t *end = range->end;
if (start == nullptr)
cout << "\nstart is null\n";
for (; start <= end; start++)
{
auto wliter = worklist.begin();
auto wlstop = worklist.end();
while (wliter != wlstop)
{
Chunk *chunk = *wliter;
auto c_start = reinterpret_cast<uintptr_t>(chunk->m_start);
auto c_size = reinterpret_cast<uintptr_t>(chunk->m_size);
auto c_end = reinterpret_cast<uintptr_t>(c_start + c_size);
if (c_start <= *start && *start < c_end)
{
if (!chunk->m_marked)
{
chunk->m_marked = true;
wliter = worklist.erase(wliter);
ranges.push_back(new AddrRange((uintptr_t *)c_start, (uintptr_t *)c_end));
stop = ranges.end();
}
else
{
wliter++;
}
}
else
{
wliter++;
}
}
}
}
}
/**
* Sweeps the heap, unmarks the marked chunks for the next cycle,
@ -304,6 +373,7 @@ namespace GC
if (profiler_enabled)
Profiler::record(SweepStart);
auto iter = heap.m_allocated_chunks.begin();
std::cout << "Chunks alloced: " << heap.m_allocated_chunks.size() << std::endl;
// This cannot "iter != stop", results in seg fault, since the end gets updated, I think.
while (iter != heap.m_allocated_chunks.end())
{
@ -326,6 +396,7 @@ namespace GC
heap.m_size -= chunk->m_size;
}
}
std::cout << "Chunks left: " << heap.m_allocated_chunks.size() << std::endl;
}
/**
@ -390,7 +461,7 @@ namespace GC
auto prev = heap.m_freed_chunks[i++];
prev->m_marked = true;
filtered.push_back(prev);
cout << filtered.back()->m_start << endl;
// cout << filtered.back()->m_start << endl;
for (; i < heap.m_freed_chunks.size(); i++)
{
prev = filtered.back();
@ -432,6 +503,27 @@ namespace GC
heap.m_profiler_enable = mode;
}
Chunk* find_pointer(uintptr_t *start, const uintptr_t* const end, vector<Chunk *> &worklist) {
for (; start <= end; start++) {
auto it = worklist.begin();
auto stop = worklist.end();
while (it != stop)
{
Chunk *chunk = *it;
auto c_start = reinterpret_cast<uintptr_t>(chunk->m_start);
auto c_size = reinterpret_cast<uintptr_t>(chunk->m_size);
auto c_end = reinterpret_cast<uintptr_t>(c_start + c_size);
// Check if the stack pointer points to something within the chunk
if (c_start <= *start && *start < c_end)
{
return chunk;
}
return NULL;
}
}
}
#ifdef HEAP_DEBUG
/**
* Prints the result of Heap::init() and a dummy value

View file

@ -19,10 +19,11 @@ Node *create_list(size_t length)
head->value = 0;
Node *prev = head;
Node *next;
for (size_t i = 1; i < length; i++)
{
Node *next = allocNode;
next = allocNode;
next->value = i;
prev->next = next;
prev = next;
@ -52,10 +53,51 @@ void clear_list(Node *head)
}
}
void run_list_test()
#define LIST_SIZE 10
void list_test1()
{
Node *list = create_list(10);
print_list(list);
Node *list_1 = create_list(LIST_SIZE);
// print_list(list_1);
}
void list_test2()
{
Node *list_2 = create_list(LIST_SIZE);
// print_list(list_2);
}
void list_test3()
{
Node *list_3 = create_list(LIST_SIZE);
// print_list(list_3);
}
void list_test4()
{
Node *list_4 = create_list(LIST_SIZE);
// print_list(list_4);
}
void list_test5()
{
Node *list_5 = create_list(LIST_SIZE);
// print_list(list_5);
}
void list_test6()
{
Node *list_6 = create_list(LIST_SIZE);
// print_list(list_6);
}
void make_test() {
list_test1();
list_test2();
list_test3();
list_test4();
list_test5();
list_test6();
}
int main()
@ -64,9 +106,9 @@ int main()
GC::Heap &heap = GC::Heap::the();
heap.set_profiler(true);
GC::Profiler::set_log_options(GC::FunctionCalls);
// GC::Profiler::set_log_options(GC::AllOps);
for (int i = 0; i < 10; i++)
run_list_test();
make_test();
GC::Heap::dispose();

39
src/GC/tests/pointers.cpp Normal file
View file

@ -0,0 +1,39 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "heap.hpp"
using std::cout, std::endl, std::hex;
struct Node {
int value;
Node *next {nullptr};
};
void test(Node *n) {
size_t n_size = 16;
auto c_start = reinterpret_cast<uintptr_t>(n);
auto c_size = reinterpret_cast<uintptr_t>(n_size);
auto c_end = reinterpret_cast<uintptr_t>(c_start + c_size);
cout << "Node *n:\t" << n << "\n";
cout << "n_size: \t0x" << std::hex << n_size << "\n";
cout << "c_start:\t0x" << std::hex << c_start << "\n";
cout << "c_size: \t0x" << std::hex << c_size << "\n";
cout << "c_end: \t0x" << std::hex << c_end << endl;
}
int main() {
GC::Heap::init();
GC::Heap &heap = GC::Heap::the();
heap.set_profiler(true);
heap.set_profiler_log_options(GC::FunctionCalls);
Node *n = static_cast<Node *>(GC::Heap::alloc(sizeof(Node)));
test(n);
GC::Heap::dispose();
return 0;
}

43
src/GC/tests/revrange.cpp Normal file
View file

@ -0,0 +1,43 @@
#include <iostream>
#include <stdint.h>
#include <stdlib.h>
#include "heap.hpp"
#define allocNode static_cast<Node *>(GC::Heap::alloc(sizeof(Node)))
using std::cout, std::endl;
struct Node {
int value;
Node *next {nullptr};
};
void revRange(int n) {
Node *next = nullptr;
Node *prev = allocNode;
while (n > 0) {
next = allocNode;
prev->next = next;
prev->value = n--;
prev = next;
}
}
void make_test() {
int n = 10;
while (n > 0)
revRange(1000);
}
int main() {
GC::Heap::init();
GC::Heap &heap = GC::Heap::the();
heap.set_profiler(true);
GC::Profiler::set_log_options(GC::FunctionCalls);
make_test();
GC::Heap::dispose();
return 0;
}