diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..8057192 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,77 @@ +{ + "files.associations": { + "array": "cpp", + "bitset": "cpp", + "string_view": "cpp", + "initializer_list": "cpp", + "ranges": "cpp", + "span": "cpp", + "utility": "cpp", + "__hash_table": "cpp", + "__split_buffer": "cpp", + "deque": "cpp", + "queue": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "atomic": "cpp", + "bit": "cpp", + "*.tcc": "cpp", + "cctype": "cpp", + "charconv": "cpp", + "chrono": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "compare": "cpp", + "concepts": "cpp", + "condition_variable": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "new": "cpp", + "ostream": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "stop_token": "cpp", + "streambuf": "cpp", + "thread": "cpp", + "typeinfo": "cpp", + "variant": "cpp", + "__bit_reference": "cpp", + "__config": "cpp", + "__debug": "cpp", + "__errc": "cpp", + "__locale": "cpp", + "__mutex_base": "cpp", + "__node_handle": "cpp", + "__threading_support": "cpp", + "__verbose_abort": "cpp", + "ios": "cpp", + "locale": "cpp", + "semaphore": "cpp" + } +} \ No newline at end of file diff --git a/src/GC/heap.cpp b/src/GC/heap.cpp index 194a553..7cdb7dc 100644 --- a/src/GC/heap.cpp +++ b/src/GC/heap.cpp @@ -1,6 +1,9 @@ #pragma once +#include #include +#include +#include #include #include #include @@ -10,19 +13,106 @@ namespace GC { - size_t Heap::getSize() { - return m_size; + // alloc assumes that after the collect phase, the aligned memory in the heap is compacted from the start, + void *Heap::alloc(size_t size) { + auto heap = Heap::the(); + assert(size > 0 && "Heap: Cannot alloc less than 0B"); + if (heap.m_size + size > HEAP_SIZE) { + // try collect + collect(); + assert(heap.m_size + size <= HEAP_SIZE && "Heap: Out Of Memory"); + } + + // kolla freed chunks innan + for (size_t i = 0; i < m_freed_chunks.size(); i++) { + auto cp = m_freed_chunks.at(i); + if (cp->size > size) + { + // dela upp chunken och sno ena delen + size_t diff = cp->size - size; + + auto chunk_complement = new Chunk; + chunk_complement->size = diff; + chunk_complement->start = cp->start + cp->size; + + m_freed_chunks.erase(m_freed_chunks.begin() + i); + m_freed_chunks.push_back(chunk_complement); + m_allocated_chunks.push_back(cp); + + return cp->start; + } + else if (cp->size == size) + { + // sno hela chunken + m_freed_chunks.erase(m_freed_chunks.begin()+i); + m_allocated_chunks.push_back(cp); + return cp->start; + } + } + + // Om inga free chunks finns, skapa ny chunk + auto new_chunk = new Chunk; + new_chunk->size = size; + new_chunk->start = (void *)m_heap + m_size; + + m_size += size; + + m_allocated_chunks.push_back(new_chunk); + + return new_chunk->start; } - void *Heap::alloc(size_t size) { - auto heap = Heap::the(); - assert(heap.getSize() + size <= HEAP_SIZE); - - return m_heap + m_size; + bool compareChunks(Chunk *c1, Chunk *c2) { + return c1->start < c2->start; } void Heap::collect() { - // TODO + // mark all objs + // compact(); + // free all unmarked (m_freed_chunks.add(jalkdsj)) + + // get the frame adress, whwere local variables and saved registers are located + auto stack_start = reinterpret_cast(__builtin_frame_address(0)); + auto stack_end = reinterpret_cast(0ul); + + + //release free chunks + while (m_freed_chunks.size()) { + auto chunk_pointer = m_freed_chunks.back(); + m_freed_chunks.pop_back(); + delete chunk_pointer; + } + } + + void Heap::compact() { + + // sort alloced_chunks by their start-addresses + std::sort(m_allocated_chunks.begin(), m_allocated_chunks.end(), compareChunks); + + // move all chunks to the start of the heap + auto heap_curr = (char *)m_heap; + for (auto space : m_allocated_chunks) { + if (space->start != heap_curr) { + memmove(heap_curr, space->start, space->size); + space->start = heap_curr; + heap_curr += space->size; + } else { + heap_curr += space->size; + } + } } -} + void Heap::mark(uintptr_t *start, uintptr_t *end) { + for (; start < end; start += 1) { // start < end??? + for (auto chunk : m_allocated_chunks) { + if (chunk->start <= start && start < chunk->start + chunk->size) { + if (!chunk->marked) { + chunk->marked = true; + //mark(chunk) // + //TODO + } + } + } + } + } +} \ No newline at end of file diff --git a/src/GC/include/chunk.hpp b/src/GC/include/chunk.hpp new file mode 100644 index 0000000..b0cd33d --- /dev/null +++ b/src/GC/include/chunk.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include + +#define CHUNK_LIST_CAP 1024 + +namespace GC { + + struct Chunk { + bool marked; + void *start; + size_t size; + }; + +} \ No newline at end of file diff --git a/src/GC/include/heap.hpp b/src/GC/include/heap.hpp index 16c4989..142af33 100644 --- a/src/GC/include/heap.hpp +++ b/src/GC/include/heap.hpp @@ -5,6 +5,9 @@ #include #include #include +using namespace std; + +#include "include/chunk.hpp" #define HEAP_SIZE 65536 @@ -21,7 +24,10 @@ namespace GC { return *m_instance; } - size_t getSize(); + ~Heap() { + free((char *)m_heap); + } + void *alloc(size_t size); private: @@ -33,10 +39,18 @@ namespace GC { } void collect(); + void compact(); + void mark(uintptr_t *start, uintptr_t *end); + + bool compareChunks(Chunk *c1, Chunk *c2); inline static Heap *m_instance = nullptr; - char *m_heap; + const char *m_heap; size_t m_size; size_t m_allocated_size; - } + + std::vector m_allocated_chunks; + std::vector m_freed_chunks; + + }; } \ No newline at end of file