rip gc
Co-authored-by: ValterMiari <ValterMiari@users.noreply.github.com>
This commit is contained in:
parent
ec3aa3cd60
commit
3e188553d6
7 changed files with 252 additions and 19 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
@ -23,7 +23,14 @@ namespace GC
|
|||
MARK_SWEEP = 1 << 2,
|
||||
FREE = 1 << 3,
|
||||
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
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
39
src/GC/tests/pointers.cpp
Normal 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
43
src/GC/tests/revrange.cpp
Normal 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;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue