From 2d925912c38c2557ac853fb1b6de5fd6e5d4c5b5 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sun, 28 Jun 2009 23:29:27 +0000 Subject: Move code into src directory. git-svn-id: http://svn.drobilla.net/resp/tuplr@160 ad02d1e2-f140-0410-9f75-f8b11f17cedd --- src/gc.cpp | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 src/gc.cpp (limited to 'src/gc.cpp') diff --git a/src/gc.cpp b/src/gc.cpp new file mode 100644 index 0000000..3964324 --- /dev/null +++ b/src/gc.cpp @@ -0,0 +1,92 @@ +/* Tuplr: A programming language + * Copyright (C) 2008-2009 David Robillard + * + * Tuplr is free software: you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Tuplr is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General + * Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Tuplr. If not, see . + */ + +#include +#include +#include +#include "tuplr.hpp" + +using namespace std; + +void* +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(const Object* obj) +{ + if (!obj || obj->marked()) + return; + + obj->mark(true); + switch (obj->tag()) { + case GC::TAG_FRAME: + break; + case GC::TAG_AST: + const ATuple* tup = dynamic_cast((AST*)obj); + if (tup) + FOREACH(ATuple::const_iterator, i, *tup) + mark(*i); + break; + } +} + +void +GC::collect(const Roots& roots) +{ + //const size_t oldSize = _heap.size(); + + for (Roots::const_iterator i = roots.begin(); i != roots.end(); ++i) + mark(*i); + + for (Heap::iterator i = _heap.begin(); i != _heap.end();) { + assert((*i)->tag() == GC::TAG_AST || (*i)->tag() == GC::TAG_FRAME); + Heap::iterator next = i; + ++next; + + if ((*i)->marked()) { + (*i)->mark(false); + } else { + switch ((*i)->tag()) { + case GC::TAG_FRAME: + free((char*)(*i) - sizeof(Object::Header)); + _heap.erase(i); + break; + case GC::TAG_AST: + AST* ast = (AST*)*i; + if (!ast->to()) { // FIXME + (ast)->~AST(); + free((char*)(*i) - sizeof(Object::Header)); + _heap.erase(i); + } + break; + } + } + i = next; + } + //std::cerr << "[GC] Collect " << oldSize << " => " << _heap.size() << endl; +} + -- cgit v1.2.1