source: src/Common/GC.cc@ 04570c7

new-env with_gc
Last change on this file since 04570c7 was 04570c7, checked in by Aaron Moss <a3moss@…>, 8 years ago

First draft of arbitrarily-generational GC

  • Property mode set to 100644
File size: 2.7 KB
Line 
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
18#include "Common/PassVisitor.h"
19
20#include "SynTree/GcTracer.h"
21
22#include <algorithm>
23#include <cassert>
24
25GC& GC::get() {
26 static GC gc;
27 return gc;
28}
29
30GC::GC() : gens(1), static_roots(), mark(false), g(0) {
31 gens[0].reserve(70000);
32}
33
34GC::~GC() {
35 for ( unsigned i = 0; i <= g; ++i ) {
36 for ( GC_Object* o : gens[i] ) {
37 delete o;
38 }
39 }
40}
41
42const GC& GC::operator<< (const GC_Traceable* obj) const {
43 if( obj )
44 {
45 if( obj->mark != this->mark ) {
46 obj->mark = this->mark;
47 obj->trace( *this );
48 }
49 }
50 return *this;
51}
52
53void GC::register_object(GC_Object* obj) {
54 gens[g].push_back(obj);
55 obj->mark = !this->mark; // initialize as un-marked
56}
57
58void GC::register_static_root(BaseSyntaxNode* root) {
59 static_roots.push_back(root);
60}
61
62void GC::new_generation() {
63 if ( ++g == gens.size() ) { gens.emplace_back(); } // ensure new generation available
64 mark = !mark; // switch mark so aged young objects will still be unmarked in old
65}
66
67void GC::trace_static_roots() {
68 PassVisitor<GcTracer> tracer{ *this };
69 for ( BaseSyntaxNode* root : static_roots ) {
70 root->accept( tracer );
71 }
72}
73
74void GC::collect_young() {
75 // get generations and decrement generation
76 assert(g > 0 && "Cannot collect_young without young generation");
77 Generation& young = gens[g];
78 Generation& old = gens[--g];
79
80 // collect young gen
81 for ( GC_Object*& obj : young ) {
82 if ( obj->mark != mark ) {
83 delete obj;
84 obj = nullptr;
85 }
86 }
87
88 // move uncollected elements into old gen
89 auto end_live = std::remove( young.begin(), young.end(), nullptr );
90 old.insert( old.end(), young.begin(), end_live );
91
92 // clear young gen and reset mark to return to old generation mark
93 young.clear();
94 mark = !mark;
95}
96
97void GC::collect() {
98 // ensure not called when young gen is active
99 assert(g == 0 && "Cannot do old collection when young generation is active");
100 Generation& old = gens[0];
101
102 // collect old gen
103 for ( GC_Object*& obj : old ) {
104 if ( obj->mark != mark ) {
105 delete obj;
106 obj = nullptr;
107 }
108 }
109
110 // clear collected elements
111 old.erase( std::remove( old.begin(), old.end(), nullptr ), old.end() );
112
113 // reset mark
114 mark = !mark;
115}
116
117GC_Object::GC_Object() {
118 GC::get().register_object( this );
119}
120
121// Local Variables: //
122// tab-width: 4 //
123// mode: c++ //
124// compile-command: "make install" //
125// End: //
Note: See TracBrowser for help on using the repository browser.