Fixed bug in size handling and mark hash

This commit is contained in:
valtermiari 2023-05-05 13:16:45 +02:00
parent 0b96f3b7e5
commit 208ff861df
3 changed files with 88 additions and 12 deletions

View file

@ -71,6 +71,7 @@ namespace GC
void free_overlap(Heap &heap);
void mark(uintptr_t *start, const uintptr_t *end, std::vector<Chunk *> &worklist);
void mark_hash(uintptr_t *start, const uintptr_t *end);
Chunk* find_pointer_hash(uintptr_t *start, const uintptr_t *end);
void create_table();
void print_line(Chunk *chunk);
void print_worklist(std::vector<Chunk *> &list);

View file

@ -41,7 +41,8 @@ namespace GC
// clang complains because arg for __b_f_a is not 0 which is "unsafe"
#pragma clang diagnostic ignored "-Wframe-address"
heap.m_stack_top = static_cast<uintptr_t *>(__builtin_frame_address(1));
heap.m_heap_top = heap.m_heap;
// TODO: handle this below
//heap.m_heap_top = heap.m_heap;
}
void Heap::set_profiler_log_options(RecordOption flags)
@ -98,12 +99,11 @@ namespace GC
}
//throw std::runtime_error(std::string("Error: Heap out of memory"));
}
if (heap.m_size + size > HEAP_SIZE)
{
if (profiler_enabled)
Profiler::dispose();
throw std::runtime_error(std::string("Error: Heap out of memory"));
}
if (heap.m_size + size > HEAP_SIZE)
{
if (profiler_enabled)
Profiler::dispose();
throw std::runtime_error(std::string("Error: Heap out of memory"));
}
// If a chunk was recycled, return the old chunk address
@ -123,7 +123,8 @@ namespace GC
auto new_chunk = new Chunk(size, (uintptr_t *)(heap.m_heap + heap.m_size));
heap.m_size += size;
heap.m_total_size += size;
// TODO: handle this below
//heap.m_total_size += size;
heap.m_allocated_chunks.push_back(new_chunk);
if (profiler_enabled)
@ -287,7 +288,7 @@ namespace GC
chunk->m_marked = true;
it = worklist.erase(it);
Chunk *next = find_pointer((uintptr_t *) c_start, (uintptr_t *) c_end, worklist);
/* Chunk *next = find_pointer((uintptr_t *) c_start, (uintptr_t *) c_end, worklist);
while (next != NULL) {
if (!next->m_marked)
{
@ -297,7 +298,7 @@ namespace GC
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);
@ -370,6 +371,62 @@ namespace GC
}
}
void Heap::create_table()
{
Heap &heap = Heap::the();
unordered_map<uintptr_t, Chunk*> chunk_table;
for (auto chunk : heap.m_allocated_chunks) {
auto pair = std::make_pair(reinterpret_cast<uintptr_t>(chunk->m_start), chunk);
heap.m_chunk_table.insert(pair);
}
}
void Heap::mark_hash(uintptr_t *start, const uintptr_t* const end)
{
Heap &heap = Heap::the();
bool profiler_enabled = heap.m_profiler_enable;
if (profiler_enabled)
Profiler::record(MarkStart);
for (; start <= end; start++)
{
auto search = heap.m_chunk_table.find(*start);
if (search != heap.m_chunk_table.end())
{
Chunk *chunk = search->second;
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 (!chunk->m_marked)
{
chunk->m_marked = true;
if (profiler_enabled)
Profiler::record(ChunkMarked, chunk);
//mark_hash(chunk->m_start, c_end);
Chunk *next = find_pointer_hash((uintptr_t *) c_start, (uintptr_t *) c_end);
while (next != NULL)
{
if (!next->m_marked)
{
next->m_marked = true;
if (profiler_enabled)
Profiler::record(ChunkMarked, chunk);
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_hash((uintptr_t *) c_start, (uintptr_t *) c_end);
}
}
}
}
}
}
/**
* Sweeps the heap, unmarks the marked chunks for the next cycle,
* adds the unmarked nodes to the list of freed chunks; to be freed.
@ -406,7 +463,9 @@ namespace GC
Profiler::record(ChunkSwept, chunk);
heap.m_freed_chunks.push_back(chunk);
iter = heap.m_allocated_chunks.erase(iter);
heap.m_size -= chunk->m_size;
//heap.m_size -= chunk->m_size;
cout << "Decremented total heap size with: " << chunk->m_size << endl;
cout << "Total size is: " << heap.m_size << endl;
}
}
std::cout << "Chunks left: " << heap.m_allocated_chunks.size() << std::endl;
@ -440,6 +499,8 @@ namespace GC
if (profiler_enabled)
Profiler::record(ChunkFreed, chunk);
heap.m_size -= chunk->m_size;
cout << "Decremented total heap size with: " << chunk->m_size << endl;
cout << "Total size is: " << heap.m_size << endl;
delete chunk;
}
}
@ -503,6 +564,8 @@ namespace GC
if (profiler_enabled)
Profiler::record(ChunkFreed, chunk);
heap.m_size -= chunk->m_size;
cout << "Decremented total heap size with: " << chunk->m_size << endl;
cout << "Total size is: " << heap.m_size << endl;
delete chunk;
}
else
@ -539,6 +602,18 @@ namespace GC
}
}
// Checks if a given chunk points to another chunk and returns it
Chunk* Heap::find_pointer_hash(uintptr_t *start, const uintptr_t* const end) {
Heap &heap = Heap::the();
for (; start <= end; start++) {
auto search = heap.m_chunk_table.find(*start);
if (search != heap.m_chunk_table.end()) {
return search->second;
}
return NULL;
}
}
#ifdef HEAP_DEBUG
/**
* Prints the result of Heap::init() and a dummy value

View file

@ -106,7 +106,7 @@ 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);
//GC::Profiler::set_log_options(GC::AllOps);
make_test();