diff options
author | David Robillard <d@drobilla.net> | 2009-06-20 06:08:23 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2009-06-20 06:08:23 +0000 |
commit | fa0cdd6234aa73ab0680c37f23664ff8c73cc1cb (patch) | |
tree | dc6dc1fa926be9cc933d53978e3153aa96d4ade9 /gc.cpp | |
parent | 865c00be395701cc973d62f05eadf358bbd5e9e0 (diff) | |
download | resp-fa0cdd6234aa73ab0680c37f23664ff8c73cc1cb.tar.gz resp-fa0cdd6234aa73ab0680c37f23664ff8c73cc1cb.tar.bz2 resp-fa0cdd6234aa73ab0680c37f23664ff8c73cc1cb.zip |
Garbage collection of code-allocated stack frames.
git-svn-id: http://svn.drobilla.net/resp/tuplr@130 ad02d1e2-f140-0410-9f75-f8b11f17cedd
Diffstat (limited to 'gc.cpp')
-rw-r--r-- | gc.cpp | 59 |
1 files changed, 42 insertions, 17 deletions
@@ -15,6 +15,7 @@ * along with Tuplr. If not, see <http://www.gnu.org/licenses/>. */ +#include <cassert> #include <set> #include <iostream> #include "tuplr.hpp" @@ -22,48 +23,72 @@ using namespace std; void* -GC::alloc(size_t size) +GC::alloc(size_t size, GC::Tag tag) { + size += (4 - (size % 4)); // Align to 32-bits + size += sizeof(Object::Header); void* ret = malloc(size); + ((Object::Header*)ret)->mark = 0; + ((Object::Header*)ret)->tag = tag; + ret = (char*)ret + sizeof(Object::Header); _heap.push_back((Object*)ret); return ret; } inline void -mark(CEnv& cenv, const Object* obj) +mark(const Object* obj) { - if (!obj || obj->used) + if (!obj || obj->marked()) return; - obj->used = true; - const ATuple* tup = dynamic_cast<const ATuple*>(obj); - if (tup) { - FOREACH(ATuple::const_iterator, i, *tup) - mark(cenv, *i); + obj->mark(true); + if (obj->tag() == GC::TAG_AST) { + const AST* ast = static_cast<const AST*>(obj); + const ATuple* tup = dynamic_cast<const ATuple*>(ast); + if (tup) { + FOREACH(ATuple::const_iterator, i, *tup) + mark(*i); + } } } void -GC::collect(CEnv& cenv, const Roots& roots) +GC::collect(const Roots& roots) { + //const size_t oldSize = _heap.size(); + for (Roots::const_iterator i = roots.begin(); i != roots.end(); ++i) - mark(cenv, *i); + mark(*i); for (Heap::iterator i = _heap.begin(); i != _heap.end();) { + assert((*i)->tag() == GC::TAG_AST || (*i)->tag() == GC::TAG_FRAME + ||(*i)->tag() == GC::TAG_TYPE); Heap::iterator next = i; ++next; - if ((*i)->used) { - (*i)->used = false; + + if ((*i)->marked()) { + (*i)->mark(false); } else { - AType* t = dynamic_cast<AType*>(*i); - // Don't delete types that are keys in the current type substitution - if (!t || cenv.tsubst.find(t) == cenv.tsubst.end()) { - (*i)->~Object(); - free(*i); + AST* ast; + switch ((GC::Tag)(*i)->tag()) { + case GC::TAG_FRAME: + free((char*)(*i) - sizeof(Object::Header)); + _heap.erase(i); + break; + case GC::TAG_TYPE: + // Don't delete types that are keys in the current type substitution + break; + case GC::TAG_AST: + ast = (AST*)*i; + assert(!ast->to<AType*>()); + (ast)->~AST(); + free((char*)(*i) - sizeof(Object::Header)); _heap.erase(i); + break; } } i = next; } + //std::cerr << "[GC] Collect " << oldSize << " => " << _heap.size() << endl; } |