/* Resp: A programming language * Copyright (C) 2008-2009 David Robillard * * Resp 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. * * Resp 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 Resp. If not, see . */ /** @file * @brief Garbage collection */ #include #include #include #include #include #include #include "resp.hpp" #include "tlsf.h" using namespace std; GC::GC(size_t pool_size) { _pool = tlsf_init(malloc(pool_size), pool_size); } GC::~GC() { tlsf_destroy((tlsf_t*)_pool); } void* GC::alloc(size_t size) { size += (4 - (size % 4)); // Align to 32-bits size += sizeof(Object::Header); void* ret = tlsf_malloc((tlsf_t*)_pool, size); ((Object::Header*)ret)->tag = T_UNKNOWN; ret = (char*)ret + sizeof(Object::Header); _heap.push_back((Object*)ret); return ret; } inline void mark(const Object* obj) { if (obj->tag() == T_SYMBOL) return; if (!obj || obj->marked()) return; if (obj->tag() != T_UNKNOWN) { const ATuple* tup = ((const AST*)obj)->to_tuple(); if (tup) FOREACHP(ATuple::const_iterator, i, tup) mark(*i); } } 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();) { Heap::iterator next = i; ++next; switch ((*i)->tag()) { case T_UNKNOWN: case T_TVAR: case T_SYMBOL: i = next; continue; default: if ((*i)->marked()) { (*i)->mark(false); assert(!(*i)->marked()); } else { tlsf_free((tlsf_t*)_pool, ((char*)(*i) - sizeof(Object::Header))); _heap.erase(i); } i = next; } } //std::cerr << "[GC] Collect " << oldSize << " => " << _heap.size() << endl; } extern "C" { void* __resp_alloc(unsigned size) { static const size_t COLLECT_SIZE = 8 * 1024 * 1024; // 8 MiB static size_t allocated = 0; allocated += size; if (allocated > COLLECT_SIZE) { Object::pool.collect(Object::pool.roots()); allocated = 0; } void* mem = Object::pool.alloc(size); Object* obj = new (mem) Object(); obj->tag(T_UNKNOWN); return mem; } }