blob: 02758213a6f66b7ff8e5b005058a742b33696b49 [file] [log] [blame]
//===-------- Selected.cpp - Implementation of the Selected class --------===//
//
// The VMKit project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "MutatorThread.h"
#include "MvmGC.h"
#include "../mmtk-j3/MMTkObject.h"
#include "mvm/VirtualMachine.h"
#include <sys/mman.h>
#include <set>
#include "debug.h"
using namespace mvm;
int Collector::verbose = 0;
extern "C" void Java_org_j3_mmtk_Collection_triggerCollection__I(word_t, int32_t) ALWAYS_INLINE;
extern "C" word_t JnJVM_org_j3_bindings_Bindings_allocateMutator__I(int32_t) ALWAYS_INLINE;
extern "C" void JnJVM_org_j3_bindings_Bindings_freeMutator__Lorg_mmtk_plan_MutatorContext_2(word_t) ALWAYS_INLINE;
extern "C" void JnJVM_org_j3_bindings_Bindings_boot__Lorg_vmmagic_unboxed_Extent_2Lorg_vmmagic_unboxed_Extent_2_3Ljava_lang_String_2(word_t, word_t, mmtk::MMTkObjectArray*) ALWAYS_INLINE;
extern "C" void JnJVM_org_j3_bindings_Bindings_processEdge__Lorg_mmtk_plan_TransitiveClosure_2Lorg_vmmagic_unboxed_ObjectReference_2Lorg_vmmagic_unboxed_Address_2(
word_t closure, void* source, void* slot) ALWAYS_INLINE;
extern "C" void JnJVM_org_j3_bindings_Bindings_reportDelayedRootEdge__Lorg_mmtk_plan_TraceLocal_2Lorg_vmmagic_unboxed_Address_2(
word_t TraceLocal, void** slot) ALWAYS_INLINE;
extern "C" void JnJVM_org_j3_bindings_Bindings_processRootEdge__Lorg_mmtk_plan_TraceLocal_2Lorg_vmmagic_unboxed_Address_2Z(
word_t TraceLocal, void* slot, uint8_t untraced) ALWAYS_INLINE;
extern "C" gc* JnJVM_org_j3_bindings_Bindings_retainForFinalize__Lorg_mmtk_plan_TraceLocal_2Lorg_vmmagic_unboxed_ObjectReference_2(
word_t TraceLocal, void* obj) ALWAYS_INLINE;
extern "C" gc* JnJVM_org_j3_bindings_Bindings_retainReferent__Lorg_mmtk_plan_TraceLocal_2Lorg_vmmagic_unboxed_ObjectReference_2(
word_t TraceLocal, void* obj) ALWAYS_INLINE;
extern "C" gc* JnJVM_org_j3_bindings_Bindings_getForwardedReference__Lorg_mmtk_plan_TraceLocal_2Lorg_vmmagic_unboxed_ObjectReference_2(
word_t TraceLocal, void* obj) ALWAYS_INLINE;
extern "C" gc* JnJVM_org_j3_bindings_Bindings_getForwardedReferent__Lorg_mmtk_plan_TraceLocal_2Lorg_vmmagic_unboxed_ObjectReference_2(
word_t TraceLocal, void* obj) ALWAYS_INLINE;
extern "C" gc* JnJVM_org_j3_bindings_Bindings_getForwardedFinalizable__Lorg_mmtk_plan_TraceLocal_2Lorg_vmmagic_unboxed_ObjectReference_2(
word_t TraceLocal, void* obj) ALWAYS_INLINE;
extern "C" uint8_t JnJVM_org_j3_bindings_Bindings_isLive__Lorg_mmtk_plan_TraceLocal_2Lorg_vmmagic_unboxed_ObjectReference_2(
word_t TraceLocal, void* obj) ALWAYS_INLINE;
extern "C" uint8_t JnJVM_org_j3_bindings_Bindings_writeBarrierCAS__Lorg_vmmagic_unboxed_ObjectReference_2Lorg_vmmagic_unboxed_Address_2Lorg_vmmagic_unboxed_ObjectReference_2Lorg_vmmagic_unboxed_ObjectReference_2(gc* ref, gc** slot, gc* old, gc* value) ALWAYS_INLINE;
extern "C" void JnJVM_org_j3_bindings_Bindings_arrayWriteBarrier__Lorg_vmmagic_unboxed_ObjectReference_2Lorg_vmmagic_unboxed_Address_2Lorg_vmmagic_unboxed_ObjectReference_2(gc* ref, gc** ptr, gc* value) ALWAYS_INLINE;
extern "C" void JnJVM_org_j3_bindings_Bindings_fieldWriteBarrier__Lorg_vmmagic_unboxed_ObjectReference_2Lorg_vmmagic_unboxed_Address_2Lorg_vmmagic_unboxed_ObjectReference_2(gc* ref, gc** ptr, gc* value) ALWAYS_INLINE;
extern "C" void JnJVM_org_j3_bindings_Bindings_nonHeapWriteBarrier__Lorg_vmmagic_unboxed_Address_2Lorg_vmmagic_unboxed_ObjectReference_2(gc** ptr, gc* value) ALWAYS_INLINE;
extern "C" void* JnJVM_org_j3_bindings_Bindings_gcmalloc__ILorg_vmmagic_unboxed_ObjectReference_2(
int sz, void* VT) ALWAYS_INLINE;
extern "C" void* gcmalloc(uint32_t sz, void* VT) {
sz = llvm::RoundUpToAlignment(sz, sizeof(void*));
return (gc*)JnJVM_org_j3_bindings_Bindings_gcmalloc__ILorg_vmmagic_unboxed_ObjectReference_2(sz, VT);
}
extern "C" void addFinalizationCandidate(gc* obj) __attribute__((always_inline));
extern "C" void addFinalizationCandidate(gc* obj) {
llvm_gcroot(obj, 0);
mvm::Thread::get()->MyVM->addFinalizationCandidate(obj);
}
extern "C" void* gcmallocUnresolved(uint32_t sz, VirtualTable* VT) {
gc* res = 0;
llvm_gcroot(res, 0);
res = (gc*)gcmalloc(sz, VT);
if (VT->hasDestructor()) addFinalizationCandidate(res);
return res;
}
extern "C" void arrayWriteBarrier(void* ref, void** ptr, void* value) {
JnJVM_org_j3_bindings_Bindings_arrayWriteBarrier__Lorg_vmmagic_unboxed_ObjectReference_2Lorg_vmmagic_unboxed_Address_2Lorg_vmmagic_unboxed_ObjectReference_2(
(gc*)ref, (gc**)ptr, (gc*)value);
if (mvm::Thread::get()->doYield) mvm::Collector::collect();
}
extern "C" void fieldWriteBarrier(void* ref, void** ptr, void* value) {
JnJVM_org_j3_bindings_Bindings_fieldWriteBarrier__Lorg_vmmagic_unboxed_ObjectReference_2Lorg_vmmagic_unboxed_Address_2Lorg_vmmagic_unboxed_ObjectReference_2(
(gc*)ref, (gc**)ptr, (gc*)value);
if (mvm::Thread::get()->doYield) mvm::Collector::collect();
}
extern "C" void nonHeapWriteBarrier(void** ptr, void* value) {
JnJVM_org_j3_bindings_Bindings_nonHeapWriteBarrier__Lorg_vmmagic_unboxed_Address_2Lorg_vmmagic_unboxed_ObjectReference_2((gc**)ptr, (gc*)value);
if (mvm::Thread::get()->doYield) mvm::Collector::collect();
}
void MutatorThread::init(Thread* _th) {
MutatorThread* th = (MutatorThread*)_th;
th->MutatorContext =
JnJVM_org_j3_bindings_Bindings_allocateMutator__I((int32_t)_th->getThreadID());
th->realRoutine(_th);
word_t context = th->MutatorContext;
th->MutatorContext = 0;
JnJVM_org_j3_bindings_Bindings_freeMutator__Lorg_mmtk_plan_MutatorContext_2(context);
}
bool Collector::isLive(gc* ptr, word_t closure) {
return JnJVM_org_j3_bindings_Bindings_isLive__Lorg_mmtk_plan_TraceLocal_2Lorg_vmmagic_unboxed_ObjectReference_2(closure, ptr);
}
void Collector::scanObject(void** ptr, word_t closure) {
if ((*ptr) != NULL) {
assert(((gc*)(*ptr))->getVirtualTable());
}
JnJVM_org_j3_bindings_Bindings_reportDelayedRootEdge__Lorg_mmtk_plan_TraceLocal_2Lorg_vmmagic_unboxed_Address_2(closure, ptr);
}
void Collector::markAndTrace(void* source, void* ptr, word_t closure) {
void** ptr_ = (void**)ptr;
if ((*ptr_) != NULL) {
assert(((gc*)(*ptr_))->getVirtualTable());
}
if ((*(void**)ptr) != NULL) assert(((gc*)(*(void**)ptr))->getVirtualTable());
JnJVM_org_j3_bindings_Bindings_processEdge__Lorg_mmtk_plan_TransitiveClosure_2Lorg_vmmagic_unboxed_ObjectReference_2Lorg_vmmagic_unboxed_Address_2(closure, source, ptr);
}
void Collector::markAndTraceRoot(void* ptr, word_t closure) {
void** ptr_ = (void**)ptr;
if ((*ptr_) != NULL) {
assert(((gc*)(*ptr_))->getVirtualTable());
}
JnJVM_org_j3_bindings_Bindings_processRootEdge__Lorg_mmtk_plan_TraceLocal_2Lorg_vmmagic_unboxed_Address_2Z(closure, ptr, true);
}
gc* Collector::retainForFinalize(gc* val, word_t closure) {
return JnJVM_org_j3_bindings_Bindings_retainForFinalize__Lorg_mmtk_plan_TraceLocal_2Lorg_vmmagic_unboxed_ObjectReference_2(closure, val);
}
gc* Collector::retainReferent(gc* val, word_t closure) {
return JnJVM_org_j3_bindings_Bindings_retainReferent__Lorg_mmtk_plan_TraceLocal_2Lorg_vmmagic_unboxed_ObjectReference_2(closure, val);
}
gc* Collector::getForwardedFinalizable(gc* val, word_t closure) {
return JnJVM_org_j3_bindings_Bindings_getForwardedFinalizable__Lorg_mmtk_plan_TraceLocal_2Lorg_vmmagic_unboxed_ObjectReference_2(closure, val);
}
gc* Collector::getForwardedReference(gc* val, word_t closure) {
return JnJVM_org_j3_bindings_Bindings_getForwardedReference__Lorg_mmtk_plan_TraceLocal_2Lorg_vmmagic_unboxed_ObjectReference_2(closure, val);
}
gc* Collector::getForwardedReferent(gc* val, word_t closure) {
return JnJVM_org_j3_bindings_Bindings_getForwardedReferent__Lorg_mmtk_plan_TraceLocal_2Lorg_vmmagic_unboxed_ObjectReference_2(closure, val);
}
void Collector::collect() {
Java_org_j3_mmtk_Collection_triggerCollection__I(NULL, 2);
}
static const char* kPrefix = "-X:gc:";
static const int kPrefixLength = strlen(kPrefix);
void Collector::initialise(int argc, char** argv) {
int i = 1;
int count = 0;
ThreadAllocator allocator;
mmtk::MMTkObjectArray* arguments = NULL;
while (i < argc && argv[i][0] == '-') {
if (!strncmp(argv[i], kPrefix, kPrefixLength)) {
count++;
}
i++;
}
if (count > 0) {
arguments = reinterpret_cast<mmtk::MMTkObjectArray*>(
malloc(sizeof(mmtk::MMTkObjectArray) + count * sizeof(mmtk::MMTkString*)));
arguments->size = count;
i = 1;
int arrayIndex = 0;
while (i < argc && argv[i][0] == '-') {
if (!strncmp(argv[i], kPrefix, kPrefixLength)) {
int size = strlen(argv[i]) - kPrefixLength;
mmtk::MMTkArray* array = reinterpret_cast<mmtk::MMTkArray*>(
allocator.Allocate(sizeof(mmtk::MMTkArray) + size * sizeof(uint16_t)));
array->size = size;
for (uint32_t j = 0; j < array->size; j++) {
array->elements[j] = argv[i][j + kPrefixLength];
}
mmtk::MMTkString* str = reinterpret_cast<mmtk::MMTkString*>(
allocator.Allocate(sizeof(mmtk::MMTkString)));
str->value = array;
str->count = array->size;
str->offset = 0;
arguments->elements[arrayIndex++] = str;
}
i++;
}
assert(arrayIndex == count);
}
JnJVM_org_j3_bindings_Bindings_boot__Lorg_vmmagic_unboxed_Extent_2Lorg_vmmagic_unboxed_Extent_2_3Ljava_lang_String_2(20 * 1024 * 1024, 100 * 1024 * 1024, arguments);
}
extern "C" void* MMTkMutatorAllocate(uint32_t size, VirtualTable* VT) {
void* val = MutatorThread::get()->Allocator.Allocate(size);
((void**)val)[0] = VT;
return val;
}
void Collector::objectReferenceWriteBarrier(gc* ref, gc** slot, gc* value) {
fieldWriteBarrier((void*)ref, (void**)slot, (void*)value);
}
void Collector::objectReferenceArrayWriteBarrier(gc* ref, gc** slot, gc* value) {
arrayWriteBarrier((void*)ref, (void**)slot, (void*)value);
}
void Collector::objectReferenceNonHeapWriteBarrier(gc** slot, gc* value) {
nonHeapWriteBarrier((void**)slot, (void*)value);
}
bool Collector::objectReferenceTryCASBarrier(gc* ref, gc** slot, gc* old, gc* value) {
bool res = JnJVM_org_j3_bindings_Bindings_writeBarrierCAS__Lorg_vmmagic_unboxed_ObjectReference_2Lorg_vmmagic_unboxed_Address_2Lorg_vmmagic_unboxed_ObjectReference_2Lorg_vmmagic_unboxed_ObjectReference_2(ref, slot, old, value);
if (mvm::Thread::get()->doYield) mvm::Collector::collect();
return res;
}
extern "C" uint8_t JnJVM_org_j3_bindings_Bindings_needsWriteBarrier__() ALWAYS_INLINE;
extern "C" uint8_t JnJVM_org_j3_bindings_Bindings_needsNonHeapWriteBarrier__() ALWAYS_INLINE;
bool Collector::needsWriteBarrier() {
return JnJVM_org_j3_bindings_Bindings_needsWriteBarrier__();
}
bool Collector::needsNonHeapWriteBarrier() {
return JnJVM_org_j3_bindings_Bindings_needsNonHeapWriteBarrier__();
}
//TODO: Remove these.
std::set<gc*> __InternalSet__;
void* Collector::begOf(gc* obj) {
abort();
}