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 # remove old files
rm -f lib/event.o lib/profiler.o lib/heap.o lib/gcoll.a tests/extern_lib.out rm -f lib/event.o lib/profiler.o lib/heap.o lib/gcoll.a tests/extern_lib.out
# compile object files # compile object files
$(CC) $(STDFLAGS) $(WFLAGS) $(LIB_INCL) -O3 -c -o lib/event.o lib/event.cpp -fPIC $(CC) $(STDFLAGS) $(WFLAGS) $(LIB_INCL) -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) -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/heap.o lib/heap.cpp -fPIC
# create static library # create static library
ar r lib/gcoll.a lib/event.o lib/profiler.o lib/heap.o 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 linked_list_test: static_lib
$(CC) $(STDFLAGS) $(WFLAGS) $(LIB_INCL) -o tests/linkedlist.out tests/linkedlist.cpp lib/gcoll.a $(CC) $(STDFLAGS) $(WFLAGS) $(LIB_INCL) -o tests/linkedlist.out tests/linkedlist.cpp lib/gcoll.a
<<<<<<< HEAD
>>>>>>> d7ea27e (testing testing...) >>>>>>> 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: wrapper:
# remove old files # remove old files
rm -f lib/event.o lib/profiler.o lib/heap.o lib/coll.a tests/wrapper.out 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 "chunk.hpp"
#include "profiler.hpp" #include "profiler.hpp"
#define HEAP_SIZE 65536 #define HEAP_SIZE 320//65536
#define FREE_THRESH (uint) 100 #define FREE_THRESH (uint) 0
#define HEAP_DEBUG // #define HEAP_DEBUG
namespace GC namespace GC
{ {
@ -23,7 +23,14 @@ namespace GC
MARK_SWEEP = 1 << 2, MARK_SWEEP = 1 << 2,
FREE = 1 << 3, FREE = 1 << 3,
COLLECT_ALL = 0b1111 // all flags above 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 * The heap class to represent the heap for the
@ -65,6 +72,7 @@ namespace GC
void print_line(Chunk *chunk); void print_line(Chunk *chunk);
void print_worklist(std::vector<Chunk *> &list); void print_worklist(std::vector<Chunk *> &list);
void mark_step(uintptr_t start, uintptr_t end, std::vector<Chunk *> &worklist); 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 // Temporary
Chunk *try_recycle_chunks_new(size_t size); Chunk *try_recycle_chunks_new(size_t size);

View file

@ -14,7 +14,7 @@ namespace GC {
enum RecordOption 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), ChunkOps = (GC::ChunkMarked | GC::ChunkSwept | GC::ChunkFreed | GC::NewChunk | GC::ReusedChunk),
AllOps = 0xFFFFFF AllOps = 0xFFFFFF
}; };

View file

@ -207,7 +207,7 @@ namespace GC
Profiler::record(CollectStart); Profiler::record(CollectStart);
// get current stack frame // 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) if (heap.m_stack_top == nullptr)
throw std::runtime_error(std::string("Error: Heap is not initialized, read the docs!")); 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) void Heap::mark(uintptr_t *start, const uintptr_t* const end, vector<Chunk *> &worklist)
{ {
// cout << "\nWorklist size: " << worklist.size() << "\n";
Heap &heap = Heap::the(); Heap &heap = Heap::the();
bool profiler_enabled = heap.m_profiler_enable; bool profiler_enabled = heap.m_profiler_enable;
if (profiler_enabled) if (profiler_enabled)
Profiler::record(MarkStart); Profiler::record(MarkStart);
vector<AddrRange *> rangeWL;
// To find adresses thats in the worklist // To find adresses thats in the worklist
for (; start <= end; start++) for (; start <= end; start++)
{ {
@ -258,8 +261,8 @@ namespace GC
{ {
Chunk *chunk = *it; Chunk *chunk = *it;
auto c_start = reinterpret_cast<uintptr_t>(chunk->m_start); auto c_start = reinterpret_cast<uintptr_t>(chunk->m_start);
auto c_size = reinterpret_cast<uintptr_t>(chunk->m_size); auto c_size = reinterpret_cast<uintptr_t>(chunk->m_size);
auto c_end = reinterpret_cast<uintptr_t>(c_start + c_size); auto c_end = reinterpret_cast<uintptr_t>(c_start + c_size);
// Check if the stack pointer points to something within the chunk // Check if the stack pointer points to something within the chunk
if (c_start <= *start && *start < c_end) if (c_start <= *start && *start < c_end)
@ -271,8 +274,22 @@ namespace GC
chunk->m_marked = true; chunk->m_marked = true;
it = worklist.erase(it); 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 // 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 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, * Sweeps the heap, unmarks the marked chunks for the next cycle,
@ -304,6 +373,7 @@ namespace GC
if (profiler_enabled) if (profiler_enabled)
Profiler::record(SweepStart); Profiler::record(SweepStart);
auto iter = heap.m_allocated_chunks.begin(); 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. // This cannot "iter != stop", results in seg fault, since the end gets updated, I think.
while (iter != heap.m_allocated_chunks.end()) while (iter != heap.m_allocated_chunks.end())
{ {
@ -326,6 +396,7 @@ namespace GC
heap.m_size -= chunk->m_size; 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++]; auto prev = heap.m_freed_chunks[i++];
prev->m_marked = true; prev->m_marked = true;
filtered.push_back(prev); filtered.push_back(prev);
cout << filtered.back()->m_start << endl; // cout << filtered.back()->m_start << endl;
for (; i < heap.m_freed_chunks.size(); i++) for (; i < heap.m_freed_chunks.size(); i++)
{ {
prev = filtered.back(); prev = filtered.back();
@ -432,6 +503,27 @@ namespace GC
heap.m_profiler_enable = mode; 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 #ifdef HEAP_DEBUG
/** /**
* Prints the result of Heap::init() and a dummy value * 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; head->value = 0;
Node *prev = head; Node *prev = head;
Node *next;
for (size_t i = 1; i < length; i++) for (size_t i = 1; i < length; i++)
{ {
Node *next = allocNode; next = allocNode;
next->value = i; next->value = i;
prev->next = next; prev->next = next;
prev = 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); Node *list_1 = create_list(LIST_SIZE);
print_list(list); // 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() int main()
@ -64,9 +106,9 @@ int main()
GC::Heap &heap = GC::Heap::the(); GC::Heap &heap = GC::Heap::the();
heap.set_profiler(true); heap.set_profiler(true);
GC::Profiler::set_log_options(GC::FunctionCalls); GC::Profiler::set_log_options(GC::FunctionCalls);
// GC::Profiler::set_log_options(GC::AllOps);
for (int i = 0; i < 10; i++) make_test();
run_list_test();
GC::Heap::dispose(); 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;
}