| //===-------- 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 "VmkitGC.h" |
| #include "../mmtk-j3/MMTkObject.h" |
| |
| #include "vmkit/VirtualMachine.h" |
| |
| #include <sys/mman.h> |
| #include <set> |
| |
| #include "debug.h" |
| |
| using namespace vmkit; |
| |
| 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_prealloc__I(int sz) ALWAYS_INLINE; |
| |
| extern "C" void* JnJVM_org_j3_bindings_Bindings_postalloc__Lorg_vmmagic_unboxed_ObjectReference_2Lorg_vmmagic_unboxed_ObjectReference_2I( |
| void* object, void* type, int sz) ALWAYS_INLINE; |
| |
| extern "C" void* JnJVM_org_j3_bindings_Bindings_vmkitgcmalloc__ILorg_vmmagic_unboxed_ObjectReference_2( |
| int sz, void* VT) ALWAYS_INLINE; |
| |
| extern "C" void* JnJVM_org_j3_bindings_Bindings_VTgcmalloc__ILorg_vmmagic_unboxed_ObjectReference_2( |
| int sz, void* VT) ALWAYS_INLINE; |
| |
| extern "C" void addFinalizationCandidate(gc* obj) ALWAYS_INLINE; |
| |
| /************************************** |
| * Sample of code using pre/post alloc. It is slower but you can have |
| * a better control of objects allocation. |
| * |
| extern "C" void* vmkitgcmalloc(uint32_t sz, void* type) { |
| gc* res = 0; |
| llvm_gcroot(res, 0); |
| sz += gcHeader::hiddenHeaderSize(); |
| res = (gc*) prealloc(sz); |
| postalloc(res, type, sz); |
| return res; |
| } |
| */ |
| extern "C" void* prealloc(uint32_t size) { |
| gc* res = 0; |
| llvm_gcroot(res, 0); |
| gcHeader* head = 0; |
| llvm_gcroot(res, 0); |
| size = llvm::RoundUpToAlignment(size, sizeof(void*)); |
| head = (gcHeader*) JnJVM_org_j3_bindings_Bindings_prealloc__I(size); |
| res = head->toReference(); |
| return res; |
| } |
| |
| extern "C" void postalloc(gc* obj, void* type, uint32_t size) { |
| llvm_gcroot(obj, 0); |
| vmkit::Thread::get()->MyVM->setType(obj, type); |
| JnJVM_org_j3_bindings_Bindings_postalloc__Lorg_vmmagic_unboxed_ObjectReference_2Lorg_vmmagic_unboxed_ObjectReference_2I(obj, type, size); |
| } |
| |
| extern "C" void* vmkitgcmalloc(uint32_t sz, void* type) { |
| gc* res = 0; |
| llvm_gcroot(res, 0); |
| sz += gcHeader::hiddenHeaderSize(); |
| sz = llvm::RoundUpToAlignment(sz, sizeof(void*)); |
| res = ((gcHeader*)JnJVM_org_j3_bindings_Bindings_vmkitgcmalloc__ILorg_vmmagic_unboxed_ObjectReference_2(sz, type))->toReference(); |
| return res; |
| } |
| |
| extern "C" void* vmkitgcmallocUnresolved(uint32_t sz, void* type) { |
| gc* res = 0; |
| llvm_gcroot(res, 0); |
| res = (gc*)vmkitgcmalloc(sz, type); |
| addFinalizationCandidate(res); |
| return res; |
| } |
| |
| /****************************************************************************** |
| * Optimized gcmalloc for VT based object layout. * |
| *****************************************************************************/ |
| |
| extern "C" void* VTgcmalloc(uint32_t sz, void* VT) { |
| gc* res = 0; |
| llvm_gcroot(res, 0); |
| sz += gcHeader::hiddenHeaderSize(); |
| sz = llvm::RoundUpToAlignment(sz, sizeof(void*)); |
| res = ((gcHeader*)JnJVM_org_j3_bindings_Bindings_VTgcmalloc__ILorg_vmmagic_unboxed_ObjectReference_2(sz, VT))->toReference(); |
| return res; |
| } |
| |
| extern "C" void* VTgcmallocUnresolved(uint32_t sz, void* VT) { |
| gc* res = 0; |
| llvm_gcroot(res, 0); |
| res = (gc*)VTgcmalloc(sz, VT); |
| if (((VirtualTable*)VT)->hasDestructor()) addFinalizationCandidate(res); |
| return res; |
| } |
| |
| /*****************************************************************************/ |
| |
| extern "C" void addFinalizationCandidate(gc* obj) { |
| llvm_gcroot(obj, 0); |
| vmkit::Thread::get()->MyVM->addFinalizationCandidate(obj); |
| } |
| |
| extern "C" void arrayWriteBarrier(void* ref, void** ptr, void* value) { |
| llvm_gcroot(ref, 0); |
| llvm_gcroot(value, 0); |
| 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 (vmkit::Thread::get()->doYield) vmkit::Collector::collect(); |
| } |
| |
| extern "C" void fieldWriteBarrier(void* ref, void** ptr, void* value) { |
| llvm_gcroot(ref, 0); |
| llvm_gcroot(value, 0); |
| 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 (vmkit::Thread::get()->doYield) vmkit::Collector::collect(); |
| } |
| |
| extern "C" void nonHeapWriteBarrier(void** ptr, void* value) { |
| llvm_gcroot(value, 0); |
| JnJVM_org_j3_bindings_Bindings_nonHeapWriteBarrier__Lorg_vmmagic_unboxed_Address_2Lorg_vmmagic_unboxed_ObjectReference_2((gc**)ptr, (gc*)value); |
| if (vmkit::Thread::get()->doYield) vmkit::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) { |
| llvm_gcroot(ptr, 0); |
| return JnJVM_org_j3_bindings_Bindings_isLive__Lorg_mmtk_plan_TraceLocal_2Lorg_vmmagic_unboxed_ObjectReference_2(closure, ptr); |
| } |
| |
| void Collector::scanObject(FrameInfo* FI, void** ptr, word_t closure) { |
| if ((*ptr) != NULL) { |
| assert(vmkit::Thread::get()->MyVM->isCorruptedType((gc*)(*ptr))); |
| } |
| 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) { |
| llvm_gcroot(source, 0); |
| void** ptr_ = (void**)ptr; |
| if ((*ptr_) != NULL) { |
| assert(vmkit::Thread::get()->MyVM->isCorruptedType((gc*)(*ptr_))); |
| } |
| if ((*(void**)ptr) != NULL) assert(vmkit::Thread::get()->MyVM->isCorruptedType((gc*)(*(void**)ptr))); |
| 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* source, void* ptr, word_t closure) { |
| llvm_gcroot(source, 0); |
| void** ptr_ = (void**)ptr; |
| if ((*ptr_) != NULL) { |
| assert(vmkit::Thread::get()->MyVM->isCorruptedType((gc*)(*ptr_))); |
| } |
| 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) { |
| llvm_gcroot(val, 0); |
| 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) { |
| llvm_gcroot(val, 0); |
| 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) { |
| llvm_gcroot(val, 0); |
| 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) { |
| llvm_gcroot(val, 0); |
| 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) { |
| llvm_gcroot(val, 0); |
| 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(0, 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, void* type) { |
| gcHeader* head = NULL; |
| size += gcHeader::hiddenHeaderSize(); |
| size = llvm::RoundUpToAlignment(size, sizeof(void*)); |
| head = (gcHeader*)MutatorThread::get()->Allocator.Allocate(size); |
| void* val = head->toReference(); |
| VirtualTable::setVirtualTable((gc*)val, (VirtualTable*)type); |
| // vmkit::Thread::get()->MyVM->setType(val, type); |
| return val; |
| } |
| |
| void Collector::objectReferenceWriteBarrier(gc* ref, gc** slot, gc* value) { |
| llvm_gcroot(ref, 0); |
| llvm_gcroot(value, 0); |
| fieldWriteBarrier((void*)ref, (void**)slot, (void*)value); |
| } |
| |
| void Collector::objectReferenceArrayWriteBarrier(gc* ref, gc** slot, gc* value) { |
| llvm_gcroot(ref, 0); |
| llvm_gcroot(value, 0); |
| arrayWriteBarrier((void*)ref, (void**)slot, (void*)value); |
| } |
| |
| void Collector::objectReferenceNonHeapWriteBarrier(gc** slot, gc* value) { |
| llvm_gcroot(value, 0); |
| nonHeapWriteBarrier((void**)slot, (void*)value); |
| } |
| |
| bool Collector::objectReferenceTryCASBarrier(gc* ref, gc** slot, gc* old, gc* value) { |
| llvm_gcroot(ref, 0); |
| llvm_gcroot(old, 0); |
| llvm_gcroot(value, 0); |
| 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 (vmkit::Thread::get()->doYield) vmkit::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(); |
| } |