/* 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; (ast)->~AST(); free((char*)(*i) - sizeof(Object::Header)); _heap.erase(i); break; } } i = next; } //std::cerr << "[GC] Collect " << oldSize << " => " << _heap.size() << endl; }