Added Hash map marking
This commit is contained in:
parent
3e188553d6
commit
a5c5d122b2
8 changed files with 133 additions and 28 deletions
|
|
@ -7,7 +7,11 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
<<<<<<< HEAD
|
||||
#define WRAPPER_DEBUG
|
||||
=======
|
||||
#define DEBUG
|
||||
>>>>>>> 74e0282 (Added Hash map marking)
|
||||
|
||||
#ifdef WRAPPER_DEBUG
|
||||
typedef struct cheap
|
||||
|
|
|
|||
|
|
@ -3,13 +3,20 @@
|
|||
#include <list>
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "chunk.hpp"
|
||||
#include "profiler.hpp"
|
||||
|
||||
<<<<<<< HEAD
|
||||
#define HEAP_SIZE 320//65536
|
||||
#define FREE_THRESH (uint) 0
|
||||
// #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
|
||||
{
|
||||
|
|
@ -52,14 +59,22 @@ namespace GC
|
|||
|
||||
char *const m_heap;
|
||||
size_t m_size {0};
|
||||
<<<<<<< HEAD
|
||||
char *m_heap_top {nullptr};
|
||||
=======
|
||||
size_t m_total_size {0};
|
||||
>>>>>>> 74e0282 (Added Hash map marking)
|
||||
// static Heap *m_instance {nullptr};
|
||||
uintptr_t *m_stack_top {nullptr};
|
||||
bool m_profiler_enable {false};
|
||||
|
||||
std::vector<Chunk *> m_allocated_chunks;
|
||||
std::vector<Chunk *> m_freed_chunks;
|
||||
<<<<<<< HEAD
|
||||
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 Chunk *get_at(std::vector<Chunk *> &list, size_t n);
|
||||
|
|
@ -69,6 +84,8 @@ namespace GC
|
|||
void free(Heap &heap);
|
||||
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);
|
||||
void create_table();
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include <stdexcept>
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
<<<<<<< HEAD
|
||||
#include <chrono>
|
||||
|
||||
#include "heap.hpp"
|
||||
|
|
@ -10,6 +11,13 @@
|
|||
#define to_us std::chrono::duration_cast<std::chrono::microseconds>
|
||||
|
||||
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
|
||||
{
|
||||
|
|
@ -91,12 +99,20 @@ namespace GC
|
|||
// Profiler::record(AllocStart, a_ms);
|
||||
heap.collect();
|
||||
// If memory is not enough after collect, crash with OOM error
|
||||
<<<<<<< HEAD
|
||||
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 > 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
|
||||
|
|
@ -116,6 +132,7 @@ 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;
|
||||
heap.m_allocated_chunks.push_back(new_chunk);
|
||||
|
||||
if (profiler_enabled)
|
||||
|
|
@ -152,7 +169,8 @@ namespace GC
|
|||
//auto chunk = Heap::get_at(heap.m_freed_chunks, i);
|
||||
auto chunk = heap.m_freed_chunks[i];
|
||||
auto iter = heap.m_freed_chunks.begin();
|
||||
advance(iter, i);
|
||||
i++;
|
||||
//advance(iter, i);
|
||||
if (chunk->m_size > size)
|
||||
{
|
||||
// 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;
|
||||
|
||||
auto work_list = heap.m_allocated_chunks;
|
||||
mark(stack_bottom, stack_top, work_list);
|
||||
//auto work_list = heap.m_allocated_chunks;
|
||||
//mark(stack_bottom, stack_top, work_list);
|
||||
|
||||
// Testing mark_hash, previous woking implementation above
|
||||
create_table();
|
||||
mark_hash(stack_bottom, stack_top);
|
||||
|
||||
sweep(heap);
|
||||
|
||||
|
|
@ -306,6 +328,7 @@ namespace GC
|
|||
rangeWL.clear();
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
void Heap::mark_range(vector<AddrRange *> &ranges, vector<Chunk *> &worklist)
|
||||
{
|
||||
Heap &heap = Heap::the();
|
||||
|
|
@ -352,10 +375,42 @@ namespace GC
|
|||
{
|
||||
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,
|
||||
|
|
@ -426,6 +481,7 @@ namespace GC
|
|||
heap.m_freed_chunks.pop_back();
|
||||
if (profiler_enabled)
|
||||
Profiler::record(ChunkFreed, chunk);
|
||||
heap.m_size -= chunk->m_size;
|
||||
delete chunk;
|
||||
}
|
||||
}
|
||||
|
|
@ -488,6 +544,7 @@ namespace GC
|
|||
{
|
||||
if (profiler_enabled)
|
||||
Profiler::record(ChunkFreed, chunk);
|
||||
heap.m_size -= chunk->m_size;
|
||||
delete chunk;
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
#include "event.hpp"
|
||||
#include "profiler.hpp"
|
||||
|
||||
// #define MAC_OS
|
||||
#define MAC_OS
|
||||
|
||||
namespace GC
|
||||
{
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ struct Node {
|
|||
};
|
||||
|
||||
Node *create_chain(int depth) {
|
||||
cout << "entering create_chain";
|
||||
cout << "entering create_chain" << endl;
|
||||
std::vector<Node*> nodes;
|
||||
if (depth > 0) {
|
||||
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) {
|
||||
cout << "entering detach_pointer";
|
||||
cout << "entering detach_pointer" << endl;
|
||||
long *dummy_ptr = nullptr;
|
||||
*ptr = dummy_ptr;
|
||||
cout << "\nexiting detach_pointer" << endl;
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
Node *node_chain = create_chain(depth);
|
||||
|
|
@ -86,9 +86,8 @@ int main() {
|
|||
|
||||
Node *root1 = static_cast<Node *>(gc.alloc(sizeof(Node)));
|
||||
Node *root2 = static_cast<Node *>(gc.alloc(sizeof(Node)));
|
||||
root1 = test_chain(58000, false);
|
||||
root2 = test_chain(58000, false);
|
||||
|
||||
root1 = test_chain(100000, false);
|
||||
//root2 = test_chain(58000, false);
|
||||
|
||||
gc.collect(GC::COLLECT_ALL);
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
|
|
|
|||
20
src/GC/tests/h_test.out.dSYM/Contents/Info.plist
Normal file
20
src/GC/tests/h_test.out.dSYM/Contents/Info.plist
Normal 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>
|
||||
BIN
src/GC/tests/h_test.out.dSYM/Contents/Resources/DWARF/h_test.out
Normal file
BIN
src/GC/tests/h_test.out.dSYM/Contents/Resources/DWARF/h_test.out
Normal file
Binary file not shown.
|
|
@ -12,17 +12,7 @@ typedef struct node {
|
|||
Node *HEAD = NULL;
|
||||
Node *CURRENT = NULL;
|
||||
|
||||
// Creates a linked list of length depth. Global head "HEAD" is updated.
|
||||
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) {
|
||||
void insert_first(int node_id) {
|
||||
Node *new_head;
|
||||
new_head = (Node*)(cheap_alloc(sizeof(Node)));
|
||||
new_head->id = node_id;
|
||||
|
|
@ -31,15 +21,33 @@ void *insert_first(int node_id) {
|
|||
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_t *heap = cheap_the();
|
||||
cheap_set_profiler(heap, true);
|
||||
create_linked_list(list_length);
|
||||
cheap_dispose();
|
||||
free(heap);
|
||||
}
|
||||
|
||||
int main (int argc, char **argv) {
|
||||
test_linked_list(30);
|
||||
// Every node in this list should be marked
|
||||
Node *head = create_linked_list(5);
|
||||
// Everything create here should be swept
|
||||
create_garbage(30);
|
||||
|
||||
cheap_dispose();
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue