Advertisement
tyler569

operator new gc (old)

Aug 18th, 2018
400
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.38 KB | None | 0 0
  1.  
  2. #include <memory>
  3. #include <new>
  4. #include <cstdlib>
  5. #include <cstdio>
  6. #include <utility>
  7. #include <array>
  8. #include <string>
  9. #include <vector>
  10.  
  11. using std::printf;
  12. using std::size_t;
  13. using std::string;
  14. using std::vector;
  15.  
  16. // MALLOCATOR
  17.  
  18. template <typename T>
  19. struct mallocator {
  20.     using value_type = T;
  21.    
  22.     mallocator() = default;
  23.     template <typename U>
  24.     constexpr mallocator(const mallocator<U>&) noexcept {}
  25.  
  26.     [[nodiscard]] T *allocate(size_t count) {
  27.         return static_cast<T *>(std::malloc(count * sizeof(T)));
  28.     }
  29.     void deallocate(T *ptr, size_t) noexcept {
  30.         return free(ptr);
  31.     }
  32. };
  33.  
  34. template <typename T, typename U>
  35. bool operator== (const mallocator<T>&, const mallocator<U>&) { return true; }
  36. template <typename T, typename U>
  37. bool operator!= (const mallocator<T>&, const mallocator<U>&) { return false; }
  38.  
  39. // GARBAGE COLLECTOR
  40.  
  41. bool alloc_debug = false;
  42.  
  43. struct allocation {
  44.     size_t *base;
  45.     size_t *top;
  46.     bool active; // enum class?
  47.     bool marked; // enum class?
  48. };
  49.  
  50. vector<
  51.     allocation,
  52.     mallocator<allocation>
  53. > allocations = {};
  54.  
  55.  
  56. bool heuristic = true;
  57.  
  58. void *GC_allocate(size_t);
  59. void GC_free(void *);
  60. void GC_ondelete(void *);
  61. void GC_collect();
  62.  
  63. void *GC_allocate(size_t len) {
  64.     printf("GC_allocate\n");
  65.     if (heuristic) {
  66.         GC_collect();
  67.     }
  68.  
  69.     auto ptr = std::malloc(len);
  70.     printf("  allocated %p : %lu\n", ptr, len);
  71.  
  72.     size_t *base = static_cast<size_t *>(ptr);
  73.     size_t *top = base + (len / sizeof(size_t));
  74.  
  75.     allocations.push_back({base, top, true, false});
  76.     return ptr;
  77. }
  78.  
  79. void GC_free(void *ptr) {
  80.     printf("GC_free\n");
  81.     std::free(ptr);
  82. }
  83.  
  84. void GC_ondelete(void *) {
  85.     printf("GC_ondelete\n");
  86.     // pass
  87. }
  88.  
  89. size_t *top_of_stack;
  90.  
  91. void scan_mark_recurse(size_t *, size_t *);
  92.  
  93. void mark_from_registers() {
  94.     std::array<size_t *, 9> registers;
  95.  
  96.     asm ("mov %%rax, %0" : "=r"(registers[0]));
  97.     asm ("mov %%rcx, %0" : "=r"(registers[1]));
  98.     asm ("mov %%rbx, %0" : "=r"(registers[2]));
  99.     asm ("mov %%rdx, %0" : "=r"(registers[3]));
  100.     asm ("mov %%rsi, %0" : "=r"(registers[4]));
  101.     asm ("mov %%rdi, %0" : "=r"(registers[5]));
  102.     asm ("mov %%rsp, %0" : "=r"(registers[6]));
  103.     asm ("mov %%rbp, %0" : "=r"(registers[7]));
  104.     // asm ("mov %%rip, %0" : "=r"(registers[8]));
  105.  
  106.     for (auto const& r : registers) {
  107.         // copypaste from below
  108.         for (auto& alloc : allocations) {
  109.             // printf("    looking for allocation: %p\n", (void *)alloc.base);
  110.             if (alloc.marked || !alloc.active) {
  111.                 continue;
  112.             }
  113.             if (r >= alloc.base && r < alloc.top) { // CLEANUP TYPE MESS
  114.                 alloc.marked = true;
  115.                 printf("    found %p\n", (void *)alloc.base);
  116.                 scan_mark_recurse(alloc.base, alloc.top);
  117.                 continue;
  118.             }
  119.         }
  120.     }
  121. }
  122.  
  123. void scan_mark_recurse(size_t *from, size_t *to) {
  124.     printf("scan_mark_recurse(%p, %p);\n", (void *)from, (void *)to);
  125.     int delta = from > to ? -1 : 1;
  126.  
  127.     for (size_t *v = from; v != to; v += delta) {
  128.         printf("    v: %p -> %016lx\n", (void *)v, *v);
  129.         for (auto& alloc : allocations) {
  130.             // printf("    looking for allocation: %p\n", (void *)alloc.base);
  131.             if (alloc.marked || !alloc.active) {
  132.                 continue;
  133.             }
  134.             if ((size_t*)*v >= alloc.base && (size_t*)*v < alloc.top) { // CLEANUP TYPE MESS
  135.                 alloc.marked = true;
  136.                 printf("    found %p\n", (void *)alloc.base);
  137.                 scan_mark_recurse(alloc.base, alloc.top);
  138.                 continue;
  139.             }
  140.         }
  141.     }
  142. }
  143.  
  144. size_t *stack_ptr() {
  145.     size_t *ptr;
  146.     asm ("mov %%rsp, %0" : "=r"(ptr));
  147.     return ptr;
  148. }
  149.  
  150. void GC_collect() {
  151.     printf("GC_collect\n");
  152.     mark_from_registers();
  153.     scan_mark_recurse(top_of_stack, stack_ptr());
  154.  
  155.     size_t allocs = 0, freed = 0;
  156.     for (auto& alloc : allocations) {
  157.         if (!alloc.active) continue;
  158.         if (!alloc.marked) {
  159.             // printf("  %p not found - freeing\n", (void *)alloc.base);
  160.             freed += 1;
  161.             GC_free(alloc.base);
  162.             alloc.active = false; // not final solution - delete from array?
  163.         } else {
  164.             // printf("  %p found - keeping\n", (void *)alloc.base);
  165.             allocs += 1;
  166.             alloc.marked = false;
  167.         }
  168.     }
  169.  
  170.     printf("Did a collection: allocs: %lu, freed %lu\n", allocs, freed);
  171. }
  172.  
  173. // OPERATORS
  174.  
  175. void * operator new(size_t size) {
  176.     return GC_allocate(size);
  177. }
  178. void operator delete(void *ptr) noexcept {
  179.     GC_ondelete(ptr);
  180. }
  181. void operator delete(void *ptr, size_t) noexcept {
  182.     GC_ondelete(ptr);
  183. }
  184.  
  185. // MAIN  /  TEST
  186.  
  187. struct destruct {
  188.     string name;
  189.     destruct(string name) : name(name) {
  190.         printf("destruct (%s) constructed\n", name.c_str());
  191.     }
  192.     ~destruct() {
  193.         printf("destruct (%s) destroyed!\n", name.c_str());
  194.     }
  195. };
  196.  
  197. int *inner() {
  198.     vector<int> v1 = {1, 2, 3};
  199.     vector<int> v2 = {3, 4, 5};
  200.     destruct d{"local"};
  201.     auto e = new destruct{"heap"};
  202.     return &v2[1];
  203. }
  204.  
  205. int main(int argc, char **argv) {
  206.     (void)argc;
  207.     top_of_stack = reinterpret_cast<size_t *>(&argv);
  208.    
  209.     int *f = inner();
  210.     GC_collect();
  211.     printf("%i\n", *f);
  212.     f = nullptr;
  213.     GC_collect();
  214. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement