Added Hash map marking

This commit is contained in:
valtermiari 2023-05-04 13:51:53 +02:00 committed by Victor Olin
parent 3e188553d6
commit a5c5d122b2
8 changed files with 133 additions and 28 deletions

View file

@ -7,7 +7,11 @@
extern "C" { extern "C" {
#endif #endif
<<<<<<< HEAD
#define WRAPPER_DEBUG #define WRAPPER_DEBUG
=======
#define DEBUG
>>>>>>> 74e0282 (Added Hash map marking)
#ifdef WRAPPER_DEBUG #ifdef WRAPPER_DEBUG
typedef struct cheap typedef struct cheap

View file

@ -3,13 +3,20 @@
#include <list> #include <list>
#include <stdlib.h> #include <stdlib.h>
#include <vector> #include <vector>
#include <unordered_map>
#include "chunk.hpp" #include "chunk.hpp"
#include "profiler.hpp" #include "profiler.hpp"
<<<<<<< HEAD
#define HEAP_SIZE 320//65536 #define HEAP_SIZE 320//65536
#define FREE_THRESH (uint) 0 #define FREE_THRESH (uint) 0
// #define HEAP_DEBUG // #define HEAP_DEBUG
=======
#define HEAP_SIZE 2097152 //256 //65536 //2097152
#define FREE_THRESH (uint) 100000 //1000
#define DEBUG
>>>>>>> 74e0282 (Added Hash map marking)
namespace GC namespace GC
{ {
@ -52,14 +59,22 @@ namespace GC
char *const m_heap; char *const m_heap;
size_t m_size {0}; size_t m_size {0};
<<<<<<< HEAD
char *m_heap_top {nullptr}; char *m_heap_top {nullptr};
=======
size_t m_total_size {0};
>>>>>>> 74e0282 (Added Hash map marking)
// static Heap *m_instance {nullptr}; // static Heap *m_instance {nullptr};
uintptr_t *m_stack_top {nullptr}; uintptr_t *m_stack_top {nullptr};
bool m_profiler_enable {false}; bool m_profiler_enable {false};
std::vector<Chunk *> m_allocated_chunks; std::vector<Chunk *> m_allocated_chunks;
std::vector<Chunk *> m_freed_chunks; std::vector<Chunk *> m_freed_chunks;
<<<<<<< HEAD
std::list<Chunk *> m_free_list; std::list<Chunk *> m_free_list;
=======
std::unordered_map<uintptr_t, Chunk*> m_chunk_table;
>>>>>>> 74e0282 (Added Hash map marking)
static bool profiler_enabled(); static bool profiler_enabled();
// static Chunk *get_at(std::vector<Chunk *> &list, size_t n); // static Chunk *get_at(std::vector<Chunk *> &list, size_t n);
@ -69,6 +84,8 @@ namespace GC
void free(Heap &heap); void free(Heap &heap);
void free_overlap(Heap &heap); void free_overlap(Heap &heap);
void mark(uintptr_t *start, const uintptr_t *end, std::vector<Chunk *> &worklist); void mark(uintptr_t *start, const uintptr_t *end, std::vector<Chunk *> &worklist);
void mark_hash(uintptr_t *start, const uintptr_t *end);
void create_table();
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);

View file

@ -2,6 +2,7 @@
#include <stdexcept> #include <stdexcept>
#include <stdlib.h> #include <stdlib.h>
#include <vector> #include <vector>
<<<<<<< HEAD
#include <chrono> #include <chrono>
#include "heap.hpp" #include "heap.hpp"
@ -10,6 +11,13 @@
#define to_us std::chrono::duration_cast<std::chrono::microseconds> #define to_us std::chrono::duration_cast<std::chrono::microseconds>
using std::cout, std::endl, std::vector, std::hex, std::dec; using std::cout, std::endl, std::vector, std::hex, std::dec;
=======
#include <unordered_map>
#include "heap.hpp"
using std::cout, std::endl, std::vector, std::hex, std::dec, std::unordered_map;
>>>>>>> 74e0282 (Added Hash map marking)
namespace GC namespace GC
{ {
@ -91,12 +99,20 @@ namespace GC
// Profiler::record(AllocStart, a_ms); // Profiler::record(AllocStart, a_ms);
heap.collect(); heap.collect();
// If memory is not enough after collect, crash with OOM error // If memory is not enough after collect, crash with OOM error
<<<<<<< HEAD
if (heap.m_size + size > HEAP_SIZE) if (heap.m_size + size > HEAP_SIZE)
{ {
if (profiler_enabled) if (profiler_enabled)
Profiler::dispose(); Profiler::dispose();
throw std::runtime_error(std::string("Error: Heap out of memory")); throw std::runtime_error(std::string("Error: Heap out of memory"));
} }
=======
if (heap.m_size > HEAP_SIZE)
{
throw std::runtime_error(std::string("Error: Heap out of memory"));
}
//throw std::runtime_error(std::string("Error: Heap out of memory"));
>>>>>>> 74e0282 (Added Hash map marking)
} }
// If a chunk was recycled, return the old chunk address // If a chunk was recycled, return the old chunk address
@ -116,6 +132,7 @@ namespace GC
auto new_chunk = new Chunk(size, (uintptr_t *)(heap.m_heap + heap.m_size)); auto new_chunk = new Chunk(size, (uintptr_t *)(heap.m_heap + heap.m_size));
heap.m_size += size; heap.m_size += size;
heap.m_total_size += size;
heap.m_allocated_chunks.push_back(new_chunk); heap.m_allocated_chunks.push_back(new_chunk);
if (profiler_enabled) if (profiler_enabled)
@ -152,7 +169,8 @@ namespace GC
//auto chunk = Heap::get_at(heap.m_freed_chunks, i); //auto chunk = Heap::get_at(heap.m_freed_chunks, i);
auto chunk = heap.m_freed_chunks[i]; auto chunk = heap.m_freed_chunks[i];
auto iter = heap.m_freed_chunks.begin(); auto iter = heap.m_freed_chunks.begin();
advance(iter, i); i++;
//advance(iter, i);
if (chunk->m_size > size) if (chunk->m_size > size)
{ {
// Split the chunk, use one part and add the remaining part to // Split the chunk, use one part and add the remaining part to
@ -214,8 +232,12 @@ namespace GC
uintptr_t *stack_top = heap.m_stack_top; uintptr_t *stack_top = heap.m_stack_top;
auto work_list = heap.m_allocated_chunks; //auto work_list = heap.m_allocated_chunks;
mark(stack_bottom, stack_top, work_list); //mark(stack_bottom, stack_top, work_list);
// Testing mark_hash, previous woking implementation above
create_table();
mark_hash(stack_bottom, stack_top);
sweep(heap); sweep(heap);
@ -306,6 +328,7 @@ namespace GC
rangeWL.clear(); rangeWL.clear();
} }
<<<<<<< HEAD
void Heap::mark_range(vector<AddrRange *> &ranges, vector<Chunk *> &worklist) void Heap::mark_range(vector<AddrRange *> &ranges, vector<Chunk *> &worklist)
{ {
Heap &heap = Heap::the(); Heap &heap = Heap::the();
@ -352,10 +375,42 @@ namespace GC
{ {
wliter++; wliter++;
} }
=======
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();
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;
mark_hash(chunk->m_start, c_end);
>>>>>>> 74e0282 (Added Hash map marking)
} }
} }
} }
} }
<<<<<<< HEAD
=======
>>>>>>> 74e0282 (Added Hash map marking)
/** /**
* Sweeps the heap, unmarks the marked chunks for the next cycle, * Sweeps the heap, unmarks the marked chunks for the next cycle,
@ -426,6 +481,7 @@ namespace GC
heap.m_freed_chunks.pop_back(); heap.m_freed_chunks.pop_back();
if (profiler_enabled) if (profiler_enabled)
Profiler::record(ChunkFreed, chunk); Profiler::record(ChunkFreed, chunk);
heap.m_size -= chunk->m_size;
delete chunk; delete chunk;
} }
} }
@ -488,6 +544,7 @@ namespace GC
{ {
if (profiler_enabled) if (profiler_enabled)
Profiler::record(ChunkFreed, chunk); Profiler::record(ChunkFreed, chunk);
heap.m_size -= chunk->m_size;
delete chunk; delete chunk;
} }
else else

View file

@ -11,7 +11,7 @@
#include "event.hpp" #include "event.hpp"
#include "profiler.hpp" #include "profiler.hpp"
// #define MAC_OS #define MAC_OS
namespace GC namespace GC
{ {

View file

@ -11,7 +11,7 @@ struct Node {
}; };
Node *create_chain(int depth) { Node *create_chain(int depth) {
cout << "entering create_chain"; cout << "entering create_chain" << endl;
std::vector<Node*> nodes; std::vector<Node*> nodes;
if (depth > 0) { if (depth > 0) {
Node *last_node = static_cast<Node *>(GC::Heap::alloc(sizeof(Node))); Node *last_node = static_cast<Node *>(GC::Heap::alloc(sizeof(Node)));
@ -36,14 +36,14 @@ void create_array(size_t size) {
} }
void detach_pointer(long **ptr) { void detach_pointer(long **ptr) {
cout << "entering detach_pointer"; cout << "entering detach_pointer" << endl;
long *dummy_ptr = nullptr; long *dummy_ptr = nullptr;
*ptr = dummy_ptr; *ptr = dummy_ptr;
cout << "\nexiting detach_pointer" << endl; cout << "\nexiting detach_pointer" << endl;
} }
Node *test_chain(int depth, bool detach) { Node *test_chain(int depth, bool detach) {
cout << "entering test_chain"; cout << "entering test_chain" << endl;
auto stack_start = reinterpret_cast<uintptr_t *>(__builtin_frame_address(0)); auto stack_start = reinterpret_cast<uintptr_t *>(__builtin_frame_address(0));
Node *node_chain = create_chain(depth); Node *node_chain = create_chain(depth);
@ -86,9 +86,8 @@ int main() {
Node *root1 = static_cast<Node *>(gc.alloc(sizeof(Node))); Node *root1 = static_cast<Node *>(gc.alloc(sizeof(Node)));
Node *root2 = static_cast<Node *>(gc.alloc(sizeof(Node))); Node *root2 = static_cast<Node *>(gc.alloc(sizeof(Node)));
root1 = test_chain(58000, false); root1 = test_chain(100000, false);
root2 = test_chain(58000, false); //root2 = test_chain(58000, false);
gc.collect(GC::COLLECT_ALL); gc.collect(GC::COLLECT_ALL);
auto end = std::chrono::high_resolution_clock::now(); auto end = std::chrono::high_resolution_clock::now();

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleIdentifier</key>
<string>com.apple.xcode.dsym.h_test.out</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>dSYM</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>

View file

@ -12,17 +12,7 @@ typedef struct node {
Node *HEAD = NULL; Node *HEAD = NULL;
Node *CURRENT = NULL; Node *CURRENT = NULL;
// Creates a linked list of length depth. Global head "HEAD" is updated. void insert_first(int node_id) {
void *create_linked_list(int depth) {
HEAD = (Node*)(cheap_alloc(sizeof(Node)));
HEAD->id = 0;
// Purposely omitting adding a child to "last_node", since its the last node
for (int i = 1; i < depth - 1; i++) {
insert_first(i);
}
}
void *insert_first(int node_id) {
Node *new_head; Node *new_head;
new_head = (Node*)(cheap_alloc(sizeof(Node))); new_head = (Node*)(cheap_alloc(sizeof(Node)));
new_head->id = node_id; new_head->id = node_id;
@ -31,15 +21,33 @@ void *insert_first(int node_id) {
HEAD = new_head; HEAD = new_head;
} }
void test_linked_list(int list_length){ // Creates a linked list of length depth. Global head "HEAD" is updated.
Node *create_linked_list(int depth) {
HEAD = (Node*)(cheap_alloc(sizeof(Node)));
HEAD->id = 0;
// Purposely omitting adding a child to "last_node", since its the last node
for (int i = 1; i < depth - 1; i++) {
insert_first(i);
}
return HEAD;
}
void create_garbage(int amount) {
for (int i = 0; i < amount; i++) {
long *garbage = (long*)(cheap_alloc(sizeof(long)));
}
}
int main () {
cheap_init(); cheap_init();
cheap_t *heap = cheap_the(); cheap_t *heap = cheap_the();
cheap_set_profiler(heap, true); cheap_set_profiler(heap, true);
create_linked_list(list_length);
cheap_dispose();
free(heap);
}
int main (int argc, char **argv) { // Every node in this list should be marked
test_linked_list(30); Node *head = create_linked_list(5);
// Everything create here should be swept
create_garbage(30);
cheap_dispose();
return 0;
} }