source: src/Common/GC.cc@ 6fa409e

new-env
Last change on this file since 6fa409e was d318a18, checked in by Aaron Moss <a3moss@…>, 7 years ago

Fix assorted memory bugs with persistent-array environment

  • Property mode set to 100644
File size: 3.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_Object* obj) const {
43 if( obj ) {
44 if( obj->mark != this->mark ) {
45 obj->mark = this->mark;
46 obj->trace( *this );
47 }
48 }
49 return *this;
50}
51
52bool GC::notrace_mark(const GC_Object* obj) const {
53 if ( obj && obj->mark != this->mark ) {
54 obj->mark = this->mark;
55 return true;
56 }
57 return false;
58}
59
60// build with flag GC_TRAP to compile in a breakpoint on register and sweep of a dynamically
61// chosen object. Process to use:
62// break GC::register_object
63// run
64// set variable GC_TRAP_OBJ = <target>
65// disable <first breakpoint>
66// continue
67#ifdef GC_TRAP
68#include <csignal>
69
70/// Set to object to check in debugger
71void* GC_TRAP_OBJ = nullptr;
72#endif
73
74void GC::register_object(GC_Object* obj) {
75 #ifdef GC_TRAP
76 if ( obj == GC_TRAP_OBJ ) std::raise(SIGTRAP);
77 #endif
78 gens[g].push_back(obj);
79 obj->mark = !this->mark; // initialize as un-marked
80}
81
82void GC::register_static_root(BaseSyntaxNode* root) {
83 static_roots.push_back(root);
84}
85
86GC_Guard GC::new_generation() {
87 if ( ++g == gens.size() ) { gens.emplace_back(); } // ensure new generation available
88 mark = !mark; // switch mark so aged young objects will still be unmarked in old
89 return { *this, g };
90}
91
92void GC::trace_static_roots() {
93 PassVisitor<GcTracer> tracer{ *this };
94 for ( BaseSyntaxNode* root : static_roots ) {
95 root->accept( tracer );
96 }
97}
98
99void GC::collect_young() {
100 // get generations and decrement generation
101 assert(g > 0 && "Cannot collect_young without young generation");
102 Generation& young = gens[g];
103 Generation& old = gens[--g];
104
105 // ensure static roots traced
106 trace_static_roots();
107
108 // collect young gen
109 for ( GC_Object*& obj : young ) {
110 if ( obj->mark != mark ) {
111 #ifdef GC_TRAP
112 if ( obj == GC_TRAP_OBJ ) std::raise(SIGTRAP);
113 #endif
114 delete obj;
115 obj = nullptr;
116 }
117 }
118
119 // move uncollected elements into old gen
120 auto end_live = std::remove( young.begin(), young.end(), nullptr );
121 old.insert( old.end(), young.begin(), end_live );
122
123 // clear young gen and reset mark to return to old generation mark
124 young.clear();
125 mark = !mark;
126}
127
128void GC::collect() {
129 // ensure not called when young gen is active
130 assert(g == 0 && "Cannot do old collection when young generation is active");
131 Generation& old = gens[0];
132
133 // ensure static roots traced
134 trace_static_roots();
135
136 // collect old gen
137 for ( GC_Object*& obj : old ) {
138 if ( obj->mark != mark ) {
139 #ifdef GC_TRAP
140 if ( obj == GC_TRAP_OBJ ) std::raise(SIGTRAP);
141 #endif
142 delete obj;
143 obj = nullptr;
144 }
145 }
146
147 // clear collected elements
148 old.erase( std::remove( old.begin(), old.end(), nullptr ), old.end() );
149
150 // reset mark
151 mark = !mark;
152}
153
154GC_Object::GC_Object() {
155 GC::get().register_object( this );
156}
157
158GC_Object::GC_Object( const GC_Object& ) {
159 GC::get().register_object( this );
160}
161
162GC_Object::GC_Object( GC_Object&& ) {
163 GC::get().register_object( this );
164}
165
166// Local Variables: //
167// tab-width: 4 //
168// mode: c++ //
169// compile-command: "make install" //
170// End: //
Note: See TracBrowser for help on using the repository browser.