| [68f9c43] | 1 | // | 
|---|
|  | 2 | // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo | 
|---|
|  | 3 | // | 
|---|
|  | 4 | // The contents of this file are covered under the licence agreement in the | 
|---|
|  | 5 | // file "LICENCE" distributed with Cforall. | 
|---|
|  | 6 | // | 
|---|
|  | 7 | // GC.cc -- | 
|---|
|  | 8 | // | 
|---|
|  | 9 | // Author           : Aaron B. Moss | 
|---|
|  | 10 | // Created On       : Thu Mar 15 14:47:00 2018 | 
|---|
|  | 11 | // Last Modified By : Aaron B. Moss | 
|---|
|  | 12 | // Last Modified On : Thu Mar 15 14:47:00 2018 | 
|---|
|  | 13 | // Update Count     : 1 | 
|---|
|  | 14 | // | 
|---|
|  | 15 |  | 
|---|
|  | 16 | #include "GC.h" | 
|---|
|  | 17 |  | 
|---|
| [bd06384] | 18 | #include "Common/PassVisitor.h" | 
|---|
|  | 19 |  | 
|---|
|  | 20 | #include "SynTree/GcTracer.h" | 
|---|
|  | 21 |  | 
|---|
| [68f9c43] | 22 | #include <algorithm> | 
|---|
| [7e4b44db] | 23 | #include <cassert> | 
|---|
| [68f9c43] | 24 |  | 
|---|
|  | 25 | GC& GC::get() { | 
|---|
|  | 26 | static GC gc; | 
|---|
|  | 27 | return gc; | 
|---|
|  | 28 | } | 
|---|
|  | 29 |  | 
|---|
| [04570c7] | 30 | GC::GC() : gens(1), static_roots(), mark(false), g(0) { | 
|---|
|  | 31 | gens[0].reserve(70000); | 
|---|
| [68f9c43] | 32 | } | 
|---|
|  | 33 |  | 
|---|
|  | 34 | GC::~GC() { | 
|---|
| [04570c7] | 35 | for ( unsigned i = 0; i <= g; ++i ) { | 
|---|
|  | 36 | for ( GC_Object* o : gens[i] ) { | 
|---|
|  | 37 | delete o; | 
|---|
|  | 38 | } | 
|---|
| [68f9c43] | 39 | } | 
|---|
|  | 40 | } | 
|---|
|  | 41 |  | 
|---|
| [24de7b1] | 42 | const GC& GC::operator<< (const GC_Object* obj) const { | 
|---|
| [68f9c43] | 43 | if( obj ) | 
|---|
|  | 44 | { | 
|---|
| [f229fc2] | 45 | if( obj->mark != this->mark ) { | 
|---|
| [68f9c43] | 46 | obj->mark = this->mark; | 
|---|
|  | 47 | obj->trace( *this ); | 
|---|
|  | 48 | } | 
|---|
|  | 49 | } | 
|---|
|  | 50 | return *this; | 
|---|
|  | 51 | } | 
|---|
|  | 52 |  | 
|---|
| [fb97252f] | 53 | // build with flag GC_TRAP to compile in a breakpoint on register and sweep of a dynamically | 
|---|
|  | 54 | // chosen object. Process to use: | 
|---|
|  | 55 | //     break GC::register_object | 
|---|
|  | 56 | //     run | 
|---|
|  | 57 | //     set variable GC_TRAP_OBJ = <target> | 
|---|
|  | 58 | //     disable <first breakpoint> | 
|---|
| [5af7306] | 59 | //     continue | 
|---|
| [fb97252f] | 60 | #ifdef GC_TRAP | 
|---|
|  | 61 | #include <csignal> | 
|---|
|  | 62 |  | 
|---|
|  | 63 | /// Set to object to check in debugger | 
|---|
|  | 64 | void* GC_TRAP_OBJ = nullptr; | 
|---|
|  | 65 | #endif | 
|---|
|  | 66 |  | 
|---|
| [68f9c43] | 67 | void GC::register_object(GC_Object* obj) { | 
|---|
| [fb97252f] | 68 | #ifdef GC_TRAP | 
|---|
|  | 69 | if ( obj == GC_TRAP_OBJ ) std::raise(SIGTRAP); | 
|---|
|  | 70 | #endif | 
|---|
| [04570c7] | 71 | gens[g].push_back(obj); | 
|---|
| [f229fc2] | 72 | obj->mark = !this->mark;  // initialize as un-marked | 
|---|
| [68f9c43] | 73 | } | 
|---|
|  | 74 |  | 
|---|
| [bd06384] | 75 | void GC::register_static_root(BaseSyntaxNode* root) { | 
|---|
|  | 76 | static_roots.push_back(root); | 
|---|
|  | 77 | } | 
|---|
|  | 78 |  | 
|---|
| [2efe4b8] | 79 | GC_Guard GC::new_generation() { | 
|---|
| [04570c7] | 80 | if ( ++g == gens.size() ) { gens.emplace_back(); }  // ensure new generation available | 
|---|
|  | 81 | mark = !mark;  // switch mark so aged young objects will still be unmarked in old | 
|---|
| [2efe4b8] | 82 | return { *this, g }; | 
|---|
| [68f9c43] | 83 | } | 
|---|
|  | 84 |  | 
|---|
| [bd06384] | 85 | void GC::trace_static_roots() { | 
|---|
|  | 86 | PassVisitor<GcTracer> tracer{ *this }; | 
|---|
|  | 87 | for ( BaseSyntaxNode* root : static_roots ) { | 
|---|
|  | 88 | root->accept( tracer ); | 
|---|
|  | 89 | } | 
|---|
|  | 90 | } | 
|---|
|  | 91 |  | 
|---|
| [68f9c43] | 92 | void GC::collect_young() { | 
|---|
| [04570c7] | 93 | // get generations and decrement generation | 
|---|
|  | 94 | assert(g > 0 && "Cannot collect_young without young generation"); | 
|---|
|  | 95 | Generation& young = gens[g]; | 
|---|
|  | 96 | Generation& old = gens[--g]; | 
|---|
|  | 97 |  | 
|---|
| [7a37f258] | 98 | // ensure static roots traced | 
|---|
|  | 99 | trace_static_roots(); | 
|---|
|  | 100 |  | 
|---|
| [68f9c43] | 101 | // collect young gen | 
|---|
|  | 102 | for ( GC_Object*& obj : young ) { | 
|---|
|  | 103 | if ( obj->mark != mark ) { | 
|---|
| [fb97252f] | 104 | #ifdef GC_TRAP | 
|---|
|  | 105 | if ( obj == GC_TRAP_OBJ ) std::raise(SIGTRAP); | 
|---|
|  | 106 | #endif | 
|---|
| [68f9c43] | 107 | delete obj; | 
|---|
|  | 108 | obj = nullptr; | 
|---|
|  | 109 | } | 
|---|
|  | 110 | } | 
|---|
|  | 111 |  | 
|---|
|  | 112 | // move uncollected elements into old gen | 
|---|
|  | 113 | auto end_live = std::remove( young.begin(), young.end(), nullptr ); | 
|---|
|  | 114 | old.insert( old.end(), young.begin(), end_live ); | 
|---|
|  | 115 |  | 
|---|
| [04570c7] | 116 | // clear young gen and reset mark to return to old generation mark | 
|---|
| [68f9c43] | 117 | young.clear(); | 
|---|
|  | 118 | mark = !mark; | 
|---|
|  | 119 | } | 
|---|
|  | 120 |  | 
|---|
|  | 121 | void GC::collect() { | 
|---|
| [f229fc2] | 122 | // ensure not called when young gen is active | 
|---|
| [04570c7] | 123 | assert(g == 0 && "Cannot do old collection when young generation is active"); | 
|---|
|  | 124 | Generation& old = gens[0]; | 
|---|
| [f229fc2] | 125 |  | 
|---|
| [7a37f258] | 126 | // ensure static roots traced | 
|---|
|  | 127 | trace_static_roots(); | 
|---|
|  | 128 |  | 
|---|
| [68f9c43] | 129 | // collect old gen | 
|---|
|  | 130 | for ( GC_Object*& obj : old ) { | 
|---|
|  | 131 | if ( obj->mark != mark ) { | 
|---|
| [fb97252f] | 132 | #ifdef GC_TRAP | 
|---|
|  | 133 | if ( obj == GC_TRAP_OBJ ) std::raise(SIGTRAP); | 
|---|
|  | 134 | #endif | 
|---|
| [68f9c43] | 135 | delete obj; | 
|---|
|  | 136 | obj = nullptr; | 
|---|
|  | 137 | } | 
|---|
|  | 138 | } | 
|---|
|  | 139 |  | 
|---|
|  | 140 | // clear collected elements | 
|---|
|  | 141 | old.erase( std::remove( old.begin(), old.end(), nullptr ), old.end() ); | 
|---|
|  | 142 |  | 
|---|
| [f229fc2] | 143 | // reset mark | 
|---|
|  | 144 | mark = !mark; | 
|---|
| [68f9c43] | 145 | } | 
|---|
|  | 146 |  | 
|---|
|  | 147 | GC_Object::GC_Object() { | 
|---|
|  | 148 | GC::get().register_object( this ); | 
|---|
|  | 149 | } | 
|---|
|  | 150 |  | 
|---|
| [24de7b1] | 151 | GC_Object::GC_Object( const GC_Object& ) { | 
|---|
|  | 152 | GC::get().register_object( this ); | 
|---|
|  | 153 | } | 
|---|
|  | 154 |  | 
|---|
|  | 155 | GC_Object::GC_Object( GC_Object&& ) { | 
|---|
|  | 156 | GC::get().register_object( this ); | 
|---|
|  | 157 | } | 
|---|
|  | 158 |  | 
|---|
| [68f9c43] | 159 | // Local Variables: // | 
|---|
|  | 160 | // tab-width: 4 // | 
|---|
|  | 161 | // mode: c++ // | 
|---|
|  | 162 | // compile-command: "make install" // | 
|---|
|  | 163 | // End: // | 
|---|