blob: 3cf53dae3ee40b6d0e297986ca2e8c12103509f7 [file] [log] [blame]
//===----------- MvmGC.h - Garbage Collection Interface -------------------===//
//
// The VMKit project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef MVM_MMTK_GC_H
#define MVM_MMTK_GC_H
#include "MutatorThread.h"
#include "mvm/VirtualMachine.h"
#include "mvm/GC/GC.h"
#include "llvm/Support/MathExtras.h"
#define gc_allocator std::allocator
#define gc_new(Class) __gc_new(Class::VT) Class
#define __gc_new new
#define TRACER tracer()
#define MARK_AND_TRACE markAndTrace()
#define CALL_TRACER tracer()
class gc : public gcRoot {
public:
size_t objectSize() const {
fprintf(stderr, "Implement object size\n");
abort();
return 0;
}
typedef gc* (*MMTkAllocType)(uintptr_t Mutator, int32_t sz, int32_t align,
int32_t offset, int32_t allocator,
int32_t site);
typedef void (*MMTkPostAllocType)(uintptr_t Mutator, uintptr_t ref,
uintptr_t typeref, int32_t bytes,
int32_t allocator);
typedef int (*MMTkCheckAllocatorType)(uintptr_t Mutator, int32_t bytes,
int32_t align, int32_t allocator);
typedef void (*MMTkDelayedRootType)(uintptr_t TraceLocal, void** slot);
typedef void (*MMTkProcessEdgeType)(uintptr_t TraceLocal, void* source,
void* slot);
typedef void (*MMTkProcessRootEdgeType)(uintptr_t TraceLocal, void* slot,
uint8_t untraced);
typedef uint8_t (*MMTkIsLiveType)(uintptr_t TraceLocal, void* obj);
typedef gc* (*MMTkRetainReferentType)(uintptr_t TraceLocal, void* obj);
typedef MMTkRetainReferentType MMTkRetainForFinalizeType;
typedef MMTkRetainReferentType MMTkGetForwardedReferenceType;
typedef MMTkRetainReferentType MMTkGetForwardedReferentType;
typedef MMTkRetainReferentType MMTkGetForwardedFinalizableType;
typedef void (*MMTkCollectType)(uintptr_t, int32_t);
static MMTkAllocType MMTkGCAllocator;
static MMTkPostAllocType MMTkGCPostAllocator;
static MMTkCheckAllocatorType MMTkCheckAllocator;
static MMTkDelayedRootType MMTkDelayedRoot;
static MMTkProcessEdgeType MMTkProcessEdge;
static MMTkProcessRootEdgeType MMTkProcessRootEdge;
static MMTkIsLiveType MMTkIsLive;
static MMTkRetainReferentType MMTkRetainReferent;
static MMTkRetainForFinalizeType MMTkRetainForFinalize;
static MMTkGetForwardedReferenceType MMTkGetForwardedReference;
static MMTkGetForwardedReferentType MMTkGetForwardedReferent;
static MMTkGetForwardedFinalizableType MMTkGetForwardedFinalizable;
static MMTkCollectType MMTkTriggerCollection;
void* operator new(size_t sz, VirtualTable *VT) {
gc* res = 0;
llvm_gcroot(res, 0);
assert(VT->tracer && "VT without a tracer");
sz = llvm::RoundUpToAlignment(sz, sizeof(void*));
uintptr_t Mutator = mvm::MutatorThread::get()->MutatorContext;
int allocator = MMTkCheckAllocator(Mutator, sz, 0, 0);
res = (gc*)MMTkGCAllocator(Mutator, sz, 0, 0, allocator, 0);
assert(res && "Allocation failed");
assert(res->getVirtualTable() == 0 && "Allocation not zeroed");
res->setVirtualTable(VT);
MMTkGCPostAllocator(Mutator, (uintptr_t)res, (uintptr_t)VT, sz, allocator);
// operator new is called by C++ code, that does not call the
// addFinalizationCandidate, unlike application code. Call it here.
if (VT->destructor) {
mvm::Thread::get()->MyVM->addFinalizationCandidate(res);
}
return res;
}
};
namespace mvm {
class Collector {
public:
static uintptr_t TraceLocal;
static bool isLive(gc* ptr) {
return gc::MMTkIsLive(TraceLocal, ptr);
}
static void scanObject(void** ptr) {
assert(gc::MMTkDelayedRoot && "scanning without a function");
assert(TraceLocal && "scanning without a trace local");
gc::MMTkDelayedRoot(TraceLocal, ptr);
}
static void markAndTrace(void* source, void* ptr) {
assert(TraceLocal && "scanning without a trace local");
gc::MMTkProcessEdge(TraceLocal, source, ptr);
}
static void markAndTraceRoot(void* ptr) {
assert(TraceLocal && "scanning without a trace local");
gc::MMTkProcessRootEdge(TraceLocal, ptr, true);
}
static gc* retainForFinalize(gc* val) {
assert(TraceLocal && "scanning without a trace local");
return gc::MMTkRetainForFinalize(TraceLocal, val);
}
static gc* retainReferent(gc* val) {
assert(TraceLocal && "scanning without a trace local");
return gc::MMTkRetainReferent(TraceLocal, val);
}
static gc* getForwardedFinalizable(gc* val) {
assert(TraceLocal && "scanning without a trace local");
return gc::MMTkGetForwardedFinalizable(TraceLocal, val);
}
static gc* getForwardedReference(gc* val) {
assert(TraceLocal && "scanning without a trace local");
return gc::MMTkGetForwardedReference(TraceLocal, val);
}
static gc* getForwardedReferent(gc* val) {
assert(TraceLocal && "scanning without a trace local");
return gc::MMTkGetForwardedReferent(TraceLocal, val);
}
static void collect() {
if (gc::MMTkTriggerCollection) gc::MMTkTriggerCollection(NULL, 2);
}
static void initialise();
static int getMaxMemory() {
return 0;
}
static int getFreeMemory() {
return 0;
}
static int getTotalMemory() {
return 0;
}
void setMaxMemory(size_t sz){
}
void setMinMemory(size_t sz){
}
static void* begOf(gc*);
};
}
#endif