| //===---------------- gc.cc - Mvm Garbage Collector -----------------------===// |
| // |
| // Mvm |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include <setjmp.h> |
| #include <stdlib.h> |
| |
| #include "mvm/GC/GC.h" |
| #include "gccollector.h" |
| #include "gcerror.h" |
| |
| using namespace mvm; |
| |
| #ifdef MULTIPLE_GC |
| #define COLLECTOR ((GCCollector*)(mvm::Thread::get()->GC))-> |
| #else |
| #define COLLECTOR GCCollector:: |
| #endif |
| |
| |
| typedef void (*memoryError_t)(unsigned int); |
| |
| memoryError_t GCCollector::internMemoryError; |
| |
| #ifdef MULTIPLE_GC |
| void gc::markAndTrace(Collector* GC) const { |
| ((GCCollector*)GC)->markAndTrace((void*)this); |
| } |
| extern "C" void MarkAndTrace(gc* gc, Collector* GC) { |
| ((GCCollector*)GC)->markAndTrace((void*)gc); |
| } |
| #else |
| void gc::markAndTrace() const { |
| GCCollector::markAndTrace((void*)this); |
| } |
| extern "C" void MarkAndTrace(gc* gc) { |
| GCCollector::markAndTrace((void*)gc); |
| } |
| #endif |
| |
| size_t gc::objectSize() const { |
| return COLLECTOR objectSize((gc*)this); |
| } |
| |
| void *gc::operator new(size_t sz, VirtualTable *vt) { |
| return COLLECTOR gcmalloc(vt, sz); |
| } |
| |
| void *gc::operator new(size_t sz) { |
| return malloc(sz); |
| } |
| |
| void gc::operator delete(void *) { |
| gcfatal(0, "never call directly a destructor....."); |
| } |
| |
| void *gc::realloc(size_t n) { |
| return COLLECTOR gcrealloc(this, n); |
| } |
| |
| |
| #ifdef MULTIPLE_GC |
| |
| size_t gc::objectSize(Collector* GC) const { |
| return ((GCCollector*)GC)->objectSize((gc*)this); |
| } |
| |
| void *gc::operator new(size_t sz, VirtualTable *VT, Collector* GC) { |
| return ((GCCollector*)GC)->gcmalloc(VT, sz); |
| } |
| |
| void *gc::operator new(size_t sz, Collector* GC) { |
| return malloc(sz); |
| } |
| |
| void gc::operator delete(void *, Collector* GC) { |
| gcfatal(0, "never call directly a destructor....."); |
| } |
| |
| void *gc::realloc(size_t n, Collector* GC) { |
| return ((GCCollector*)GC)->gcrealloc(this, n); |
| } |
| #endif |
| |
| #undef COLLECTOR |
| #ifdef MULTIPLE_GC |
| #define COLLECTOR ((GCCollector*)this)-> |
| #else |
| #define COLLECTOR GCCollector:: |
| #endif |
| |
| unsigned int Collector::enable(unsigned int n) { |
| return COLLECTOR enable(n); |
| } |
| |
| int Collector::isStable(gc_lock_recovery_fct_t fct, int a0, int a1, int a2, |
| int a3, int a4, int a5, int a6, int a7) { |
| return COLLECTOR isStable(fct, a0, a1, a2, a3, a4, a5, a6, a7); |
| } |
| |
| void Collector::die_if_sigsegv_occured_during_collection(void *addr) { |
| COLLECTOR die_if_sigsegv_occured_during_collection(addr); |
| } |
| |
| void Collector::gcStats(size_t &no, size_t &nbb) { |
| COLLECTOR gcStats(&no, &nbb); |
| } |
| |
| void Collector::initialise(markerFn marker, void *base_sp) { |
| #ifdef MULTIPLE_GC |
| GCCollector* GC = new GCCollector(); |
| GCCollector::bootstrapGC = GC; |
| mvm::Thread::get()->GC = GC; |
| GC->initialise(marker); |
| GC->inject_my_thread(base_sp); |
| #else |
| GCCollector::initialise(marker); |
| GCCollector::inject_my_thread(base_sp); |
| #endif |
| mvm::Thread::get()->baseSP = base_sp; |
| } |
| |
| void Collector::destroy() { |
| COLLECTOR destroy(); |
| } |
| |
| void Collector::inject_my_thread(void *base_sp) { |
| #ifdef HAVE_PTHREAD |
| COLLECTOR inject_my_thread(base_sp); |
| #endif |
| mvm::Thread::get()->baseSP = base_sp; |
| } |
| |
| void Collector::maybeCollect() { |
| COLLECTOR maybeCollect(); |
| } |
| |
| void Collector::collect(void) { |
| COLLECTOR collect(); |
| } |
| |
| gc *Collector::begOf(const void *obj) { |
| return (gc*)COLLECTOR begOf((void*)obj); |
| } |
| |
| int Collector::byteOffset(void *obj) { |
| int beg = (intptr_t)COLLECTOR begOf(obj); |
| intptr_t off = (intptr_t)obj; |
| return (off-beg); |
| } |
| |
| |
| void Collector::applyFunc(void (*func)(gcRoot *o, void *data), void *data) { |
| return COLLECTOR applyFunc(func, data); |
| } |
| |
| int Collector::getMaxMemory(void){ |
| return 0; |
| } |
| |
| int Collector::getFreeMemory(void){ |
| return 0; |
| } |
| |
| int Collector::getTotalMemory(void){ |
| return 0; |
| } |
| |
| void Collector::setMaxMemory(size_t sz){ |
| } |
| |
| void Collector::setMinMemory(size_t sz){ |
| } |
| |
| void Collector::registerMemoryError(void (*func)(unsigned int)){ |
| COLLECTOR internMemoryError = func; |
| //onMemoryError = &COLLECTOR defaultMemoryError; |
| } |
| |
| void Collector::remove_my_thread() { |
| #ifdef HAVE_PTHREAD |
| COLLECTOR remove_thread(COLLECTOR threads->myloc()); |
| #endif |
| } |
| |
| #undef COLLECTOR |
| void GCThread::waitCollection() { |
| #if defined(MULTIPLE_GC) |
| #if defined(SERVICE_GC) |
| GCCollector* GC = GCCollector::collectingGC; |
| #else |
| GCCollector* GC = ((GCCollector*)mvm::Thread::get()->GC); |
| #endif |
| #define COLLECTOR GC-> |
| #else |
| #define COLLECTOR GCCollector:: |
| #endif |
| unsigned int cm = COLLECTOR current_mark; |
| |
| if(Thread::self() != collector_tid) { |
| collectorGo(); |
| while((COLLECTOR current_mark == cm) && |
| (COLLECTOR status == COLLECTOR stat_collect)) |
| _collectionCond.wait(&_stackLock); |
| } |
| } |
| |
| #ifdef HAVE_PTHREAD |
| |
| #undef COLLECTOR |
| void GCCollector::siggc_handler(int) { |
| #if defined(MULTIPLE_GC) |
| #if defined(SERVICE_GC) |
| GCCollector* GC = collectingGC; |
| #else |
| GCCollector* GC = ((GCCollector*)mvm::Thread::get()->GC); |
| #endif |
| #define COLLECTOR GC-> |
| #else |
| #define COLLECTOR GCCollector:: |
| #endif |
| GCThreadCollector *loc = COLLECTOR threads->myloc(); |
| |
| jmp_buf buf; |
| setjmp(buf); |
| |
| COLLECTOR threads->stackLock(); |
| |
| if(!loc) /* a key is being destroyed */ |
| COLLECTOR threads->another_mark(); |
| else { |
| register unsigned int **cur = (unsigned int**)&buf; |
| register unsigned int **max = loc->base_sp(); |
| |
| GCChunkNode *node; |
| |
| for(; cur<max; cur++) { |
| if((node = o2node(*cur)) && (!COLLECTOR isMarked(node))) { |
| node->remove(); |
| node->append(COLLECTOR used_nodes); |
| COLLECTOR mark(node); |
| } |
| } |
| |
| COLLECTOR threads->another_mark(); |
| COLLECTOR threads->waitCollection(); |
| } |
| COLLECTOR threads->stackUnlock(); |
| #undef COLLECTOR |
| } |
| #endif // HAVE_PTHREAD |
| |
| #ifdef MULTIPLE_GC |
| Collector* Collector::allocate() { |
| GCCollector* GC = new GCCollector(); |
| GC->initialise(GCCollector::bootstrapGC->_marker); |
| return GC; |
| } |
| #endif // MULTIPLE_GC |
| |
| #ifdef SERVICE_GC |
| Collector* Collector::getCollectorFromObject(const void* o) { |
| return (Collector*)GCCollector::o2node((void*)o)->meta; |
| } |
| #endif |
| |
| #ifdef MULTIPLE_GC |
| extern "C" gc* gcmalloc(size_t sz, VirtualTable* VT, Collector* GC) { |
| return (gc*)((GCCollector*)GC)->gcmalloc(VT, sz); |
| } |
| #else |
| extern "C" gc* gcmalloc(size_t sz, VirtualTable* VT) { |
| return (gc*)GCCollector::gcmalloc(VT, sz); |
| } |
| #endif |
| |