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
|
# 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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
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